diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6a00bb42785..4409d4f33afc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,9 +165,6 @@ jobs: - name: install sccache run: src/ci/scripts/install-sccache.sh - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - - name: install clang run: src/ci/scripts/install-clang.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b5699dcd098..3f052eca48e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ the Zulip stream is the best place to *ask* for help. Documentation for contributing to the compiler or tooling is located in the [Guide to Rustc Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the -standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. +standard library is in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. ## Making changes to subtrees and submodules diff --git a/Cargo.lock b/Cargo.lock index 63c7d97bce43..4307639a5099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,9 +184,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03341eae1125472b0672fbf35cc9aa7b74cd8e0c3d02f02c28a04678f12aaa7a" +checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" dependencies = [ "askama_macros", "itoa", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461bd78f3da90b5e44eee4272cfb1c4832aa3dcdb6c370aedd3eb253d2b9e3ca" +checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" dependencies = [ "askama_parser", "basic-toml", @@ -214,18 +214,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba49fb22ee3074574b8510abd9495d4f0bb9b8f87e8e45ee31e2cee508f7a8e5" +checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e33eb7484958aaa1f27e9adb556f5d557331cd891bdbb33781bc1f9550b6f6e" +checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" dependencies = [ "rustc-hash 2.1.1", "serde", @@ -580,9 +580,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -1298,9 +1298,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -3490,7 +3490,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -3515,7 +3514,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_macros", "rustc_session", "rustc_span", @@ -3541,9 +3539,9 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", + "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_lexer", "rustc_macros", @@ -3574,7 +3572,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -3602,7 +3599,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_lexer", @@ -3636,7 +3632,6 @@ dependencies = [ "rustc_codegen_ssa", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", @@ -3674,7 +3669,6 @@ dependencies = [ "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", @@ -3684,7 +3678,6 @@ dependencies = [ "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_query_system", "rustc_serialize", "rustc_session", "rustc_span", @@ -3694,7 +3687,6 @@ dependencies = [ "serde_json", "smallvec", "tempfile", - "thin-vec", "thorin-dwp", "tracing", "wasm-encoder 0.219.2", @@ -3711,7 +3703,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -3777,25 +3768,16 @@ dependencies = [ "libc", "rustc_abi", "rustc_ast", - "rustc_ast_lowering", - "rustc_ast_passes", "rustc_ast_pretty", - "rustc_attr_parsing", - "rustc_borrowck", - "rustc_builtin_macros", "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir_analysis", "rustc_hir_pretty", - "rustc_hir_typeck", - "rustc_incremental", "rustc_index", - "rustc_infer", "rustc_interface", "rustc_lexer", "rustc_lint", @@ -3804,21 +3786,13 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_mir_build", - "rustc_mir_dataflow", "rustc_mir_transform", - "rustc_monomorphize", "rustc_parse", - "rustc_passes", - "rustc_pattern_analysis", - "rustc_privacy", "rustc_public", - "rustc_query_system", "rustc_resolve", "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", - "rustc_ty_utils", "serde_json", "shlex", "tracing", @@ -3862,7 +3836,6 @@ dependencies = [ "rustc_data_structures", "rustc_error_codes", "rustc_error_messages", - "rustc_fluent_macro", "rustc_hashes", "rustc_index", "rustc_lint_defs", @@ -3887,7 +3860,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_lexer", "rustc_lint_defs", @@ -3915,19 +3887,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc_fluent_macro" -version = "0.0.0" -dependencies = [ - "annotate-snippets 0.11.5", - "fluent-bundle", - "fluent-syntax", - "proc-macro2", - "quote", - "syn 2.0.110", - "unic-langid", -] - [[package]] name = "rustc_fs_util" version = "0.0.0" @@ -3982,7 +3941,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4029,7 +3987,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_hir_analysis", "rustc_hir_pretty", @@ -4051,10 +4008,8 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "rand 0.9.2", - "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_graphviz", "rustc_hashes", @@ -4064,7 +4019,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "thin-vec", "tracing", ] @@ -4093,7 +4047,6 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4124,7 +4077,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_analysis", @@ -4141,7 +4093,6 @@ dependencies = [ "rustc_passes", "rustc_privacy", "rustc_query_impl", - "rustc_query_system", "rustc_resolve", "rustc_session", "rustc_span", @@ -4177,7 +4128,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4229,6 +4179,8 @@ dependencies = [ name = "rustc_macros" version = "0.0.0" dependencies = [ + "fluent-bundle", + "fluent-syntax", "proc-macro2", "quote", "syn 2.0.110", @@ -4250,7 +4202,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_pretty", @@ -4274,6 +4225,7 @@ dependencies = [ "bitflags", "either", "gsgdt", + "parking_lot", "polonius-engine", "rustc_abi", "rustc_apfloat", @@ -4284,7 +4236,6 @@ dependencies = [ "rustc_error_messages", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hashes", "rustc_hir", @@ -4315,7 +4266,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4336,11 +4286,10 @@ dependencies = [ "polonius-engine", "regex", "rustc_abi", - "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", + "rustc_hir", "rustc_index", "rustc_macros", "rustc_middle", @@ -4354,7 +4303,6 @@ name = "rustc_mir_transform" version = "0.0.0" dependencies = [ "either", - "hashbrown 0.16.1", "itertools", "rustc_abi", "rustc_arena", @@ -4362,7 +4310,6 @@ dependencies = [ "rustc_const_eval", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4384,7 +4331,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4421,7 +4367,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_index", "rustc_lexer", "rustc_macros", @@ -4454,7 +4399,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4477,7 +4421,6 @@ dependencies = [ "rustc_arena", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4497,7 +4440,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_macros", "rustc_middle", @@ -4550,14 +4492,19 @@ name = "rustc_query_impl" version = "0.0.0" dependencies = [ "measureme", + "rustc_abi", "rustc_data_structures", + "rustc_errors", "rustc_hashes", "rustc_hir", "rustc_index", + "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_serialize", + "rustc_session", "rustc_span", + "rustc_thread_pool", "tracing", ] @@ -4565,24 +4512,17 @@ dependencies = [ name = "rustc_query_system" version = "0.0.0" dependencies = [ - "hashbrown 0.16.1", - "parking_lot", "rustc_abi", "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", - "rustc_hashes", "rustc_hir", - "rustc_index", "rustc_macros", "rustc_serialize", "rustc_session", "rustc_span", - "rustc_thread_pool", "smallvec", - "tracing", ] [[package]] @@ -4600,13 +4540,11 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_query_system", "rustc_session", "rustc_span", "smallvec", @@ -4654,7 +4592,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", @@ -4761,7 +4698,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_infer", "rustc_macros", @@ -4810,7 +4746,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hashes", "rustc_hir", "rustc_index", @@ -5623,7 +5558,7 @@ version = "0.1.0" dependencies = [ "build_helper", "cargo_metadata 0.21.0", - "fluent-syntax", + "clap", "globset", "ignore", "miropt-test-tools", diff --git a/INSTALL.md b/INSTALL.md index dd6c64b3df5f..0e998101fcd1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -233,7 +233,7 @@ itself back on after some time). ### MSVC -MSVC builds of Rust additionally requires an installation of: +MSVC builds of Rust additionally require an installation of: - Visual Studio 2022 (or later) build tools so `rustc` can use its linker. Older Visual Studio versions such as 2019 *may* work but aren't actively tested. diff --git a/RELEASES.md b/RELEASES.md index 424e12ceec05..29c787f4e14c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,12 @@ +Version 1.93.1 (2026-02-12) +=========================== + + + +- [Don't try to recover keyword as non-keyword identifier](https://github.com/rust-lang/rust/pull/150590), fixing an ICE that especially [affected rustfmt](https://github.com/rust-lang/rustfmt/issues/6739). +- [Fix `clippy::panicking_unwrap` false-positive on field access with implicit deref](https://github.com/rust-lang/rust-clippy/pull/16196). +- [Revert "Update wasm-related dependencies in CI"](https://github.com/rust-lang/rust/pull/152259), fixing file descriptor leaks on the `wasm32-wasip2` target. + Version 1.93.0 (2026-01-22) ========================== @@ -1546,7 +1555,7 @@ Compatibility Notes - [Check well-formedness of the source type's signature in fn pointer casts.](https://github.com/rust-lang/rust/pull/129021) This partly closes a soundness hole that comes when casting a function item to function pointer - [Use equality instead of subtyping when resolving type dependent paths.](https://github.com/rust-lang/rust/pull/129073) - Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . -- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect.](https://github.com/rust-lang/rust/pull/129422) +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previously did not have any effect.](https://github.com/rust-lang/rust/pull/129422) - The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. @@ -1722,7 +1731,7 @@ Cargo Compatibility Notes ------------------- - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. -- The standard library has a new implementation of `binary_search` which is significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. +- The standard library has a new implementation of `binary_search` which significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. - [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. - [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) - The WebAssembly target features `multivalue` and `reference-types` are now @@ -1872,7 +1881,7 @@ 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. -- [Add a Rust-for Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) +- [Add a Rust-for-Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) Version 1.80.1 (2024-08-08) =========================== @@ -4510,7 +4519,7 @@ Compatibility Notes saturating to `0` instead][89926]. In the real world the panic happened mostly on platforms with buggy monotonic clock implementations rather than catching programming errors like reversing the start and end times. Such programming - errors will now results in `0` rather than a panic. + errors will now result in `0` rather than a panic. - In a future release we're planning to increase the baseline requirements for the Linux kernel to version 3.2, and for glibc to version 2.17. We'd love your feedback in [PR #95026][95026]. diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 89c61cdf00a5..30d64b05cfde 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -3,6 +3,8 @@ // Several crates are depended upon but unused so that they are present in the sysroot #![expect(unused_crate_dependencies)] +use std::process::ExitCode; + // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see @@ -38,6 +40,6 @@ #[cfg(feature = "jemalloc")] use tikv_jemalloc_sys as _; -fn main() { +fn main() -> ExitCode { rustc_driver::main() } diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 66c8056d0c2a..66d4dca00726 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -35,6 +35,7 @@ impl Reg { reg_ctor!(f32, Float, 32); reg_ctor!(f64, Float, 64); + reg_ctor!(f128, Float, 128); } impl Reg { diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 41ad14f550ab..aafb124986e1 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -290,7 +290,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// function call isn't allowed (a.k.a. `va_list`). /// /// This function handles transparent types automatically. - pub fn pass_indirectly_in_non_rustic_abis(mut self, cx: &C) -> bool + pub fn pass_indirectly_in_non_rustic_abis(self, cx: &C) -> bool + where + Ty: TyAbiInterface<'a, C> + Copy, + { + let base = self.peel_transparent_wrappers(cx); + Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base) + } + + /// Recursively peel away transparent wrappers, returning the inner value. + /// + /// The return value is not `repr(transparent)` and/or does + /// not have a non-1zst field. + pub fn peel_transparent_wrappers(mut self, cx: &C) -> Self where Ty: TyAbiInterface<'a, C> + Copy, { @@ -300,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { self = field; } - Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self) + self } /// Finds the one field that is not a 1-ZST. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 061ad8617893..88f8b7cc5170 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,6 +1,6 @@ // tidy-alphabetical-start +#![cfg_attr(all(feature = "nightly", bootstrap, test), feature(assert_matches))] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", feature(assert_matches))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(step_trait))] // tidy-alphabetical-end diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 5e81ec28ee35..97dd21db07e7 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -13,7 +13,6 @@ #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(test(no_crate_inject, attr(deny(warnings), allow(internal_features))))] -#![feature(core_intrinsics)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(never_type)] @@ -26,7 +25,7 @@ use std::cell::{Cell, RefCell}; use std::marker::PhantomData; use std::mem::{self, MaybeUninit}; use std::ptr::{self, NonNull}; -use std::{cmp, intrinsics, slice}; +use std::{cmp, hint, slice}; use smallvec::SmallVec; @@ -172,8 +171,22 @@ impl TypedArena { available_bytes >= additional_bytes } + /// Allocates storage for `len >= 1` values in this arena, and returns a + /// raw pointer to the first value's storage. + /// + /// # Safety + /// + /// Caller must initialize each of the `len` slots to a droppable value + /// before the arena is dropped. + /// + /// In practice, this typically means that the caller must be able to + /// raw-copy `len` already-initialized values into the slice without any + /// possibility of panicking. + /// + /// FIXME(Zalathar): This is *very* fragile; perhaps we need a different + /// approach to arena-allocating slices of droppable values. #[inline] - fn alloc_raw_slice(&self, len: usize) -> *mut T { + unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T { assert!(size_of::() != 0); assert!(len != 0); @@ -208,7 +221,7 @@ impl TypedArena { &self, iter: impl IntoIterator>, ) -> Result<&mut [T], E> { - // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason + // Despite the similarity with `DroplessArena`, we cannot reuse their fast case. The reason // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a // reference to `self` and adding elements to the arena during iteration. // @@ -229,9 +242,15 @@ impl TypedArena { } // Move the content to the arena by copying and then forgetting it. let len = vec.len(); - let start_ptr = self.alloc_raw_slice(len); + + // SAFETY: After allocating raw storage for exactly `len` values, we + // must fully initialize the storage without panicking, and we must + // also prevent the stale values in the vec from being dropped. Ok(unsafe { + let start_ptr = self.alloc_raw_slice(len); + // Initialize the newly-allocated storage without panicking. vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + // Prevent the stale values in the vec from being dropped. vec.set_len(0); slice::from_raw_parts_mut(start_ptr, len) }) @@ -432,7 +451,7 @@ impl DroplessArena { 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)) }; + unsafe { hint::assert_unchecked(end == align_down(end, DROPLESS_ALIGNMENT)) }; if let Some(sub) = end.checked_sub(bytes) { let new_end = align_down(sub, layout.align()); @@ -490,19 +509,6 @@ impl DroplessArena { } } - /// Used by `Lift` to check whether this slice is allocated - /// in this arena. - #[inline] - pub fn contains_slice(&self, slice: &[T]) -> bool { - for chunk in self.chunks.borrow_mut().iter_mut() { - let ptr = slice.as_ptr().cast::().cast_mut(); - if chunk.start() <= ptr && chunk.end() >= ptr { - return true; - } - } - false - } - /// Allocates a string slice that is copied into the `DroplessArena`, returning a /// reference to it. Will panic if passed an empty string. /// @@ -584,7 +590,7 @@ impl DroplessArena { &self, iter: impl IntoIterator>, ) -> Result<&mut [T], E> { - // Despite the similarlty with `alloc_from_iter`, we cannot reuse their fast case, as we + // Despite the similarity with `alloc_from_iter`, we cannot reuse their fast case, as we // cannot know the minimum length of the iterator in this case. assert!(size_of::() != 0); diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 591abdaa2683..fa323b7cf581 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -656,11 +656,7 @@ impl Pat { // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)` // assuming `T0` to `Tn` are all syntactically valid as types. PatKind::Tuple(pats) => { - let mut tys = ThinVec::with_capacity(pats.len()); - // FIXME(#48994) - could just be collected into an Option - for pat in pats { - tys.push(pat.to_ty()?); - } + let tys = pats.iter().map(|pat| pat.to_ty()).collect::>>()?; TyKind::Tup(tys) } _ => return None, @@ -3873,27 +3869,44 @@ pub struct ConstItem { pub ident: Ident, pub generics: Generics, pub ty: Box, - pub rhs: Option, + pub rhs_kind: ConstItemRhsKind, pub define_opaque: Option>, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] -pub enum ConstItemRhs { - TypeConst(AnonConst), - Body(Box), +pub enum ConstItemRhsKind { + Body { rhs: Option> }, + TypeConst { rhs: Option }, } -impl ConstItemRhs { - pub fn span(&self) -> Span { - self.expr().span +impl ConstItemRhsKind { + pub fn new_body(rhs: Box) -> Self { + Self::Body { rhs: Some(rhs) } } - pub fn expr(&self) -> &Expr { + pub fn span(&self) -> Option { + Some(self.expr()?.span) + } + + pub fn expr(&self) -> Option<&Expr> { match self { - ConstItemRhs::TypeConst(anon_const) => &anon_const.value, - ConstItemRhs::Body(expr) => expr, + Self::Body { rhs: Some(body) } => Some(&body), + Self::TypeConst { rhs: Some(anon) } => Some(&anon.value), + _ => None, } } + + pub fn has_expr(&self) -> bool { + match self { + Self::Body { rhs: Some(_) } => true, + Self::TypeConst { rhs: Some(_) } => true, + _ => false, + } + } + + pub fn is_type_const(&self) -> bool { + matches!(self, &Self::TypeConst { .. }) + } } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index e346a56bcf40..8d8e8ffc562f 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -354,7 +354,13 @@ fn make_attr_token_stream( FrameData { open_delim_sp: Some((delim, span, spacing)), inner: vec![] }, )); } else if let Some(delim) = kind.close_delim() { - let frame_data = mem::replace(&mut stack_top, stack_rest.pop().unwrap()); + // If there's no matching opening delimiter, the token stream is malformed, + // likely due to a improper delimiter positions in the source code. + // It's not delimiter mismatch, and lexer can not detect it, so we just ignore it here. + let Some(frame) = stack_rest.pop() else { + return AttrTokenStream::new(stack_top.inner); + }; + let frame_data = mem::replace(&mut stack_top, frame); let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap(); assert!( open_delim.eq_ignoring_invisible_origin(&delim), diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 51614460d3c4..8556e8288670 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -427,7 +427,7 @@ macro_rules! common_visitor_and_walkers { Const, ConstBlockItem, ConstItem, - ConstItemRhs, + ConstItemRhsKind, Defaultness, Delegation, DelegationMac, diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6ac258155fe9..c00bac5d3c5a 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -15,7 +15,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } 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_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl deleted file mode 100644 index 0cd5c4f303de..000000000000 --- a/compiler/rustc_ast_lowering/messages.ftl +++ /dev/null @@ -1,191 +0,0 @@ -ast_lowering_abi_specified_multiple_times = - `{$prev_name}` ABI specified multiple times - .label = previously specified here - .note = these ABIs are equivalent on the current target - -ast_lowering_arbitrary_expression_in_pattern = - arbitrary expressions aren't allowed in patterns - .pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression - .const_block_in_pattern_help = use a named `const`-item or an `if`-guard (`x if x == const {"{ ... }"}`) instead - -ast_lowering_argument = argument - -ast_lowering_assoc_ty_binding_in_dyn = - associated type bounds are not allowed in `dyn` types - .suggestion = use `impl Trait` to introduce a type instead - -ast_lowering_assoc_ty_parentheses = - parenthesized generic arguments cannot be used in associated type constraints - -ast_lowering_async_bound_not_on_trait = - `async` bound modifier only allowed on trait, not `{$descr}` - -ast_lowering_async_bound_only_for_fn_traits = - `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits - -ast_lowering_async_coroutines_not_supported = - `async` coroutines are not yet supported - -ast_lowering_att_syntax_only_x86 = - the `att_syntax` option is only supported on x86 - -ast_lowering_await_only_in_async_fn_and_blocks = - `await` is only allowed inside `async` functions and blocks - .label = only allowed inside `async` functions and blocks - -ast_lowering_bad_return_type_notation_inputs = - argument types not allowed with return type notation - .suggestion = remove the input types - -ast_lowering_bad_return_type_notation_needs_dots = return type notation arguments must be elided with `..` - .suggestion = use the correct syntax by adding `..` to the arguments - -ast_lowering_bad_return_type_notation_output = - return type not allowed with return type notation -ast_lowering_bad_return_type_notation_output_suggestion = use the right argument notation and remove the return type - -ast_lowering_bad_return_type_notation_position = return type notation not allowed in this position yet - -ast_lowering_clobber_abi_not_supported = - `clobber_abi` is not supported on this target - -ast_lowering_closure_cannot_be_static = closures cannot be static - -ast_lowering_coroutine_too_many_parameters = - too many parameters for a coroutine (expected 0 or 1 parameters) - -ast_lowering_default_field_in_tuple = default fields are not supported in tuple structs - .label = default fields are only supported on structs - -ast_lowering_delegation_cycle_in_signature_resolution = encountered a cycle during delegation signature resolution -ast_lowering_delegation_unresolved_callee = failed to resolve delegation callee -ast_lowering_does_not_support_modifiers = - the `{$class_name}` register class does not support template modifiers - -ast_lowering_extra_double_dot = - `..` can only be used once per {$ctx} pattern - .label = can only be used once per {$ctx} pattern - -ast_lowering_functional_record_update_destructuring_assignment = - functional record updates are not allowed in destructuring assignments - .suggestion = consider removing the trailing pattern - -ast_lowering_generic_param_default_in_binder = - defaults for generic parameters are not allowed in `for<...>` binders - -ast_lowering_generic_type_with_parentheses = - parenthesized type parameters may only be used with a `Fn` trait - .label = only `Fn` traits may use parentheses - -ast_lowering_inclusive_range_with_no_end = inclusive range with no end - -ast_lowering_inline_asm_unsupported_target = - inline assembly is unsupported on this target - -ast_lowering_invalid_abi = - invalid ABI: found `{$abi}` - .label = invalid ABI - .note = invoke `{$command}` for a full list of supported calling conventions - -ast_lowering_invalid_abi_clobber_abi = - invalid ABI for `clobber_abi` - .note = the following ABIs are supported on this target: {$supported_abis} - -ast_lowering_invalid_abi_suggestion = there's a similarly named valid ABI `{$suggestion}` - -ast_lowering_invalid_asm_template_modifier_const = - asm template modifiers are not allowed for `const` arguments - -ast_lowering_invalid_asm_template_modifier_label = - asm template modifiers are not allowed for `label` arguments - -ast_lowering_invalid_asm_template_modifier_reg_class = - invalid asm template modifier for this register class - -ast_lowering_invalid_asm_template_modifier_sym = - asm template modifiers are not allowed for `sym` arguments - -ast_lowering_invalid_legacy_const_generic_arg = - invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items - -ast_lowering_invalid_legacy_const_generic_arg_suggestion = - try using a const generic argument instead - -ast_lowering_invalid_register = - invalid register `{$reg}`: {$error} - -ast_lowering_invalid_register_class = - invalid register class `{$reg_class}`: unknown register class - .note = the following register classes are supported on this target: {$supported_register_classes} - -ast_lowering_match_arm_with_no_body = - `match` arm with no body - .suggestion = add a body after the pattern - -ast_lowering_misplaced_double_dot = - `..` patterns are not allowed here - .note = only allowed in tuple, tuple struct, and slice patterns - -ast_lowering_misplaced_impl_trait = - `impl Trait` is not allowed in {$position} - .note = `impl Trait` is only allowed in arguments and return types of functions and methods - -ast_lowering_never_pattern_with_body = - a never pattern is always unreachable - .label = this will never be executed - .suggestion = remove this expression - -ast_lowering_never_pattern_with_guard = - a guard on a never pattern will never be run - .suggestion = remove this guard - -ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` - -ast_lowering_previously_used_here = previously used here - -ast_lowering_register1 = register `{$reg1_name}` - -ast_lowering_register2 = register `{$reg2_name}` - -ast_lowering_register_class_only_clobber = - register class `{$reg_class_name}` can only be used as a clobber, not as an input or output -ast_lowering_register_class_only_clobber_stable = - register class `{$reg_class_name}` can only be used as a clobber in stable - -ast_lowering_register_conflict = - register `{$reg1_name}` conflicts with register `{$reg2_name}` - .help = use `lateout` instead of `out` to avoid conflict - -ast_lowering_remove_parentheses = remove these parentheses - -ast_lowering_sub_tuple_binding = - `{$ident_name} @` is not allowed in a {$ctx} - .label = this is only allowed in slice patterns - .help = remove this and bind each tuple field independently - -ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields - -ast_lowering_support_modifiers = - the `{$class_name}` register class supports the following template modifiers: {$modifiers} - -ast_lowering_template_modifier = template modifier - -ast_lowering_this_not_async = this is not `async` - -ast_lowering_underscore_expr_lhs_assign = - in expressions, `_` can only be used on the left-hand side of an assignment - .label = `_` not allowed here - -ast_lowering_union_default_field_values = unions cannot have default field values - -ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture -ast_lowering_unstable_inline_assembly_label_operand_with_outputs = - using both label and output operands for inline assembly is unstable -ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable - -ast_lowering_use_angle_brackets = use angle brackets instead - -ast_lowering_yield = yield syntax is experimental -ast_lowering_yield_in_closure = - `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - .suggestion = use `#[coroutine]` to make this closure a coroutine diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 36fcd4b924c8..a7bf1c99a7e2 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -3,6 +3,7 @@ use std::fmt::Write; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_session::parse::feature_err; @@ -19,8 +20,7 @@ use super::errors::{ RegisterConflict, }; use crate::{ - AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, - ResolverAstLoweringExt, fluent_generated as fluent, + AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt, }; impl<'a, 'hir> LoweringContext<'a, 'hir> { @@ -67,7 +67,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_experimental_arch, sp, - fluent::ast_lowering_unstable_inline_assembly, + msg!("inline assembly is not stable yet on this architecture"), ) .emit(); } @@ -84,7 +84,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_unwind, sp, - fluent::ast_lowering_unstable_may_unwind, + msg!("the `may_unwind` option is unstable"), ) .emit(); } @@ -499,7 +499,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { sess, sym::asm_goto_with_outputs, *op_sp, - fluent::ast_lowering_unstable_inline_assembly_label_operand_with_outputs, + msg!("using both label and output operands for inline assembly is unstable"), ) .emit(); } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 88e69e67d8a5..1eb72727df66 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -4,17 +4,17 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; #[derive(Diagnostic)] -#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)] +#[diag("parenthesized type parameters may only be used with a `Fn` trait", code = E0214)] pub(crate) struct GenericTypeWithParentheses { #[primary_span] - #[label] + #[label("only `Fn` traits may use parentheses")] pub span: Span, #[subdiagnostic] pub sub: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")] +#[multipart_suggestion("use angle brackets instead", applicability = "maybe-incorrect")] pub(crate) struct UseAngleBrackets { #[suggestion_part(code = "<")] pub open_param: Span, @@ -23,11 +23,11 @@ pub(crate) struct UseAngleBrackets { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_abi, code = E0703)] -#[note] +#[diag("invalid ABI: found `{$abi}`", code = E0703)] +#[note("invoke `{$command}` for a full list of supported calling conventions")] pub(crate) struct InvalidAbi { #[primary_span] - #[label] + #[label("invalid ABI")] pub span: Span, pub abi: Symbol, pub command: String, @@ -36,16 +36,16 @@ pub(crate) struct InvalidAbi { } #[derive(Diagnostic)] -#[diag(ast_lowering_default_field_in_tuple)] +#[diag("default fields are not supported in tuple structs")] pub(crate) struct TupleStructWithDefault { #[primary_span] - #[label] + #[label("default fields are only supported on structs")] pub span: Span, } #[derive(Subdiagnostic)] #[suggestion( - ast_lowering_invalid_abi_suggestion, + "there's a similarly named valid ABI `{$suggestion}`", code = "\"{suggestion}\"", applicability = "maybe-incorrect", style = "verbose" @@ -57,7 +57,7 @@ pub(crate) struct InvalidAbiSuggestion { } #[derive(Diagnostic)] -#[diag(ast_lowering_assoc_ty_parentheses)] +#[diag("parenthesized generic arguments cannot be used in associated type constraints")] pub(crate) struct AssocTyParentheses { #[primary_span] pub span: Span, @@ -67,12 +67,12 @@ pub(crate) struct AssocTyParentheses { #[derive(Subdiagnostic)] pub(crate) enum AssocTyParenthesesSub { - #[multipart_suggestion(ast_lowering_remove_parentheses)] + #[multipart_suggestion("remove these parentheses")] Empty { #[suggestion_part(code = "")] parentheses_span: Span, }, - #[multipart_suggestion(ast_lowering_use_angle_brackets)] + #[multipart_suggestion("use angle brackets instead")] NotEmpty { #[suggestion_part(code = "<")] open_param: Span, @@ -82,8 +82,8 @@ pub(crate) enum AssocTyParenthesesSub { } #[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_impl_trait, code = E0562)] -#[note] +#[diag("`impl Trait` is not allowed in {$position}", code = E0562)] +#[note("`impl Trait` is only allowed in arguments and return types of functions and methods")] pub(crate) struct MisplacedImplTrait<'a> { #[primary_span] pub span: Span, @@ -91,97 +91,106 @@ pub(crate) struct MisplacedImplTrait<'a> { } #[derive(Diagnostic)] -#[diag(ast_lowering_assoc_ty_binding_in_dyn)] +#[diag("associated type bounds are not allowed in `dyn` types")] pub(crate) struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, - #[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "use `impl Trait` to introduce a type instead", + code = " = impl", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_underscore_expr_lhs_assign)] +#[diag("in expressions, `_` can only be used on the left-hand side of an assignment")] pub(crate) struct UnderscoreExprLhsAssign { #[primary_span] - #[label] + #[label("`_` not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)] +#[diag("`await` is only allowed inside `async` functions and blocks", code = E0728)] pub(crate) struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] - #[label] + #[label("only allowed inside `async` functions and blocks")] pub await_kw_span: Span, - #[label(ast_lowering_this_not_async)] + #[label("this is not `async`")] pub item_span: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)] +#[diag("too many parameters for a coroutine (expected 0 or 1 parameters)", code = E0628)] pub(crate) struct CoroutineTooManyParameters { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_closure_cannot_be_static, code = E0697)] +#[diag("closures cannot be static", code = E0697)] pub(crate) struct ClosureCannotBeStatic { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_functional_record_update_destructuring_assignment)] +#[diag("functional record updates are not allowed in destructuring assignments")] pub(crate) struct FunctionalRecordUpdateDestructuringAssignment { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "consider removing the trailing pattern", + code = "", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)] +#[diag("`async` coroutines are not yet supported", code = E0727)] pub(crate) struct AsyncCoroutinesNotSupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)] +#[diag("inline assembly is unsupported on this target", code = E0472)] pub(crate) struct InlineAsmUnsupportedTarget { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_att_syntax_only_x86)] +#[diag("the `att_syntax` option is only supported on x86")] pub(crate) struct AttSyntaxOnlyX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_abi_specified_multiple_times)] +#[diag("`{$prev_name}` ABI specified multiple times")] pub(crate) struct AbiSpecifiedMultipleTimes { #[primary_span] pub abi_span: Span, pub prev_name: Symbol, - #[label] + #[label("previously specified here")] pub prev_span: Span, - #[note] + #[note("these ABIs are equivalent on the current target")] pub equivalent: bool, } #[derive(Diagnostic)] -#[diag(ast_lowering_clobber_abi_not_supported)] +#[diag("`clobber_abi` is not supported on this target")] pub(crate) struct ClobberAbiNotSupported { #[primary_span] pub abi_span: Span, } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_invalid_abi_clobber_abi)] +#[note("the following ABIs are supported on this target: {$supported_abis}")] +#[diag("invalid ABI for `clobber_abi`")] pub(crate) struct InvalidAbiClobberAbi { #[primary_span] pub abi_span: Span, @@ -189,7 +198,7 @@ pub(crate) struct InvalidAbiClobberAbi { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_register)] +#[diag("invalid register `{$reg}`: {$error}")] pub(crate) struct InvalidRegister<'a> { #[primary_span] pub op_span: Span, @@ -198,8 +207,10 @@ pub(crate) struct InvalidRegister<'a> { } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_invalid_register_class)] +#[note( + "the following register classes are supported on this target: {$supported_register_classes}" +)] +#[diag("invalid register class `{$reg_class}`: unknown register class")] pub(crate) struct InvalidRegisterClass { #[primary_span] pub op_span: Span, @@ -208,12 +219,12 @@ pub(crate) struct InvalidRegisterClass { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)] +#[diag("invalid asm template modifier for this register class")] pub(crate) struct InvalidAsmTemplateModifierRegClass { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, #[subdiagnostic] pub sub: InvalidAsmTemplateModifierRegClassSub, @@ -221,44 +232,48 @@ pub(crate) struct InvalidAsmTemplateModifierRegClass { #[derive(Subdiagnostic)] pub(crate) enum InvalidAsmTemplateModifierRegClassSub { - #[note(ast_lowering_support_modifiers)] + #[note( + "the `{$class_name}` register class supports the following template modifiers: {$modifiers}" + )] SupportModifier { class_name: Symbol, modifiers: String }, - #[note(ast_lowering_does_not_support_modifiers)] + #[note("the `{$class_name}` register class does not support template modifiers")] DoesNotSupportModifier { class_name: Symbol }, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_const)] +#[diag("asm template modifiers are not allowed for `const` arguments")] pub(crate) struct InvalidAsmTemplateModifierConst { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_sym)] +#[diag("asm template modifiers are not allowed for `sym` arguments")] pub(crate) struct InvalidAsmTemplateModifierSym { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_label)] +#[diag("asm template modifiers are not allowed for `label` arguments")] pub(crate) struct InvalidAsmTemplateModifierLabel { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_register_class_only_clobber)] +#[diag( + "register class `{$reg_class_name}` can only be used as a clobber, not as an input or output" +)] pub(crate) struct RegisterClassOnlyClobber { #[primary_span] pub op_span: Span, @@ -266,7 +281,7 @@ pub(crate) struct RegisterClassOnlyClobber { } #[derive(Diagnostic)] -#[diag(ast_lowering_register_class_only_clobber_stable)] +#[diag("register class `{$reg_class_name}` can only be used as a clobber in stable")] pub(crate) struct RegisterClassOnlyClobberStable { #[primary_span] pub op_span: Span, @@ -274,27 +289,27 @@ pub(crate) struct RegisterClassOnlyClobberStable { } #[derive(Diagnostic)] -#[diag(ast_lowering_register_conflict)] +#[diag("register `{$reg1_name}` conflicts with register `{$reg2_name}`")] pub(crate) struct RegisterConflict<'a> { #[primary_span] - #[label(ast_lowering_register1)] + #[label("register `{$reg1_name}`")] pub op_span1: Span, - #[label(ast_lowering_register2)] + #[label("register `{$reg2_name}`")] pub op_span2: Span, pub reg1_name: &'a str, pub reg2_name: &'a str, - #[help] + #[help("use `lateout` instead of `out` to avoid conflict")] pub in_out: Option, } #[derive(Diagnostic)] -#[help] -#[diag(ast_lowering_sub_tuple_binding)] +#[help("remove this and bind each tuple field independently")] +#[diag("`{$ident_name} @` is not allowed in a {$ctx}")] pub(crate) struct SubTupleBinding<'a> { #[primary_span] - #[label] + #[label("this is only allowed in slice patterns")] #[suggestion( - ast_lowering_sub_tuple_binding_suggestion, + "if you don't need to use the contents of {$ident}, discard the tuple's remaining fields", style = "verbose", code = "..", applicability = "maybe-incorrect" @@ -306,63 +321,67 @@ pub(crate) struct SubTupleBinding<'a> { } #[derive(Diagnostic)] -#[diag(ast_lowering_extra_double_dot)] +#[diag("`..` can only be used once per {$ctx} pattern")] pub(crate) struct ExtraDoubleDot<'a> { #[primary_span] - #[label] + #[label("can only be used once per {$ctx} pattern")] pub span: Span, - #[label(ast_lowering_previously_used_here)] + #[label("previously used here")] pub prev_span: Span, pub ctx: &'a str, } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_misplaced_double_dot)] +#[note("only allowed in tuple, tuple struct, and slice patterns")] +#[diag("`..` patterns are not allowed here")] pub(crate) struct MisplacedDoubleDot { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_match_arm_with_no_body)] +#[diag("`match` arm with no body")] pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, - #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] + #[suggestion( + "add a body after the pattern", + code = " => todo!(),", + applicability = "has-placeholders" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_never_pattern_with_body)] +#[diag("a never pattern is always unreachable")] pub(crate) struct NeverPatternWithBody { #[primary_span] - #[label] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[label("this will never be executed")] + #[suggestion("remove this expression", code = "", applicability = "maybe-incorrect")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_never_pattern_with_guard)] +#[diag("a guard on a never pattern will never be run")] pub(crate) struct NeverPatternWithGuard { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove this guard", code = "", applicability = "maybe-incorrect")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_arbitrary_expression_in_pattern)] +#[diag("arbitrary expressions aren't allowed in patterns")] pub(crate) struct ArbitraryExpressionInPattern { #[primary_span] pub span: Span, - #[note(ast_lowering_pattern_from_macro_note)] + #[note("the `expr` fragment specifier forces the metavariable's content to be an expression")] pub pattern_from_macro_note: bool, - #[help(ast_lowering_const_block_in_pattern_help)] + #[help("use a named `const`-item or an `if`-guard (`x if x == const {\"{ ... }\"}`) instead")] pub const_block_in_pattern_help: bool, } #[derive(Diagnostic)] -#[diag(ast_lowering_inclusive_range_with_no_end)] +#[diag("inclusive range with no end")] pub(crate) struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, @@ -370,7 +389,7 @@ pub(crate) struct InclusiveRangeWithNoEnd { #[derive(Subdiagnostic)] #[multipart_suggestion( - ast_lowering_bad_return_type_notation_output_suggestion, + "use the right argument notation and remove the return type", applicability = "machine-applicable", style = "verbose" )] @@ -384,26 +403,36 @@ pub(crate) struct RTNSuggestion { #[derive(Diagnostic)] pub(crate) enum BadReturnTypeNotation { - #[diag(ast_lowering_bad_return_type_notation_inputs)] + #[diag("argument types not allowed with return type notation")] Inputs { #[primary_span] - #[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the input types", + code = "(..)", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, - #[diag(ast_lowering_bad_return_type_notation_output)] + #[diag("return type not allowed with return type notation")] Output { #[primary_span] span: Span, #[subdiagnostic] suggestion: RTNSuggestion, }, - #[diag(ast_lowering_bad_return_type_notation_needs_dots)] + #[diag("return type notation arguments must be elided with `..`")] NeedsDots { #[primary_span] - #[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use the correct syntax by adding `..` to the arguments", + code = "(..)", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, - #[diag(ast_lowering_bad_return_type_notation_position)] + #[diag("return type notation not allowed in this position yet")] Position { #[primary_span] span: Span, @@ -411,14 +440,14 @@ pub(crate) enum BadReturnTypeNotation { } #[derive(Diagnostic)] -#[diag(ast_lowering_generic_param_default_in_binder)] +#[diag("defaults for generic parameters are not allowed in `for<...>` binders")] pub(crate) struct GenericParamDefaultInBinder { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_async_bound_not_on_trait)] +#[diag("`async` bound modifier only allowed on trait, not `{$descr}`")] pub(crate) struct AsyncBoundNotOnTrait { #[primary_span] pub span: Span, @@ -426,30 +455,37 @@ pub(crate) struct AsyncBoundNotOnTrait { } #[derive(Diagnostic)] -#[diag(ast_lowering_async_bound_only_for_fn_traits)] +#[diag("`async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits")] pub(crate) struct AsyncBoundOnlyForFnTraits { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_no_precise_captures_on_apit)] +#[diag("`use<...>` precise capturing syntax not allowed in argument-position `impl Trait`")] pub(crate) struct NoPreciseCapturesOnApit { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_yield_in_closure)] +#[diag("`yield` can only be used in `#[coroutine]` closures, or `gen` blocks")] pub(crate) struct YieldInClosure { #[primary_span] pub span: Span, - #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "use `#[coroutine]` to make this closure a coroutine", + code = "#[coroutine] ", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_legacy_const_generic_arg)] +#[diag( + "invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items" +)] pub(crate) struct InvalidLegacyConstGenericArg { #[primary_span] pub span: Span, @@ -459,7 +495,7 @@ pub(crate) struct InvalidLegacyConstGenericArg { #[derive(Subdiagnostic)] #[multipart_suggestion( - ast_lowering_invalid_legacy_const_generic_arg_suggestion, + "try using a const generic argument instead", applicability = "maybe-incorrect" )] pub(crate) struct UseConstGenericArg { @@ -472,21 +508,21 @@ pub(crate) struct UseConstGenericArg { } #[derive(Diagnostic)] -#[diag(ast_lowering_union_default_field_values)] +#[diag("unions cannot have default field values")] pub(crate) struct UnionWithDefault { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_delegation_unresolved_callee)] +#[diag("failed to resolve delegation callee")] pub(crate) struct UnresolvedDelegationCallee { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_delegation_cycle_in_signature_resolution)] +#[diag("encountered a cycle during delegation signature resolution")] pub(crate) struct CycleInDelegationSignatureResolution { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9fbfeb7a11e6..b034e250b58d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; @@ -28,9 +29,7 @@ use super::{ GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; -use crate::{ - AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope, fluent_generated, -}; +use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope}; struct WillCreateDefIdsVisitor {} @@ -967,14 +966,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); this.arena.alloc(this.expr(gen_future_span, expr_break)) }); - self.arm(ready_pat, break_x) + self.arm(ready_pat, break_x, span) }; // `::std::task::Poll::Pending => {}` let pending_arm = { let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); - self.arm(pending_pat, empty_block) + self.arm(pending_pat, empty_block, span) }; let inner_match_stmt = { @@ -1028,7 +1027,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); // mut __awaitee => loop { ... } - let awaitee_arm = self.arm(awaitee_pat, loop_expr); + let awaitee_arm = self.arm(awaitee_pat, loop_expr, span); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_expr = match await_kind { @@ -1703,7 +1702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &self.tcx.sess, sym::yield_expr, span, - fluent_generated::ast_lowering_yield, + msg!("yield syntax is experimental"), ) .emit(); } @@ -1818,7 +1817,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_expr = self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span)); let pat = self.pat_none(for_span); - self.arm(pat, break_expr) + self.arm(pat, break_expr, for_span) }; // Some() => , @@ -1827,7 +1826,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_block = self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false)); let body_expr = self.arena.alloc(self.expr_block(body_block)); - self.arm(some_pat, body_expr) + self.arm(some_pat, body_expr, for_span) }; // `mut iter` @@ -1886,7 +1885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span }); // `mut iter => { ... }` - let iter_arm = self.arm(iter_pat, loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr, for_span); let match_expr = match loop_kind { ForLoopKind::For => { @@ -1931,7 +1930,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::IntoAsyncIterIntoIter, arena_vec![self; head], ); - let iter_arm = self.arm(async_iter_pat, inner_match_expr); + let iter_arm = self.arm(async_iter_pat, inner_match_expr, for_span); self.arena.alloc(self.expr_match( for_span, iter, @@ -1998,7 +1997,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_expr = self.expr_ident(span, val_ident, val_pat_nid); self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); - self.arm(continue_pat, val_expr) + self.arm(continue_pat, val_expr, try_span) }; // `ControlFlow::Break(residual) => @@ -2041,7 +2040,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); - self.arm(break_pat, ret_expr) + self.arm(break_pat, ret_expr, try_span) }; hir::ExprKind::Match( @@ -2369,12 +2368,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>, + span: Span, ) -> hir::Arm<'hir> { hir::Arm { hir_id: self.next_id(), pat, guard: None, - span: self.lower_span(expr.span), + span: self.lower_span(span), body: expr, } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b497c6beeb98..9922ed8a5c58 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -288,7 +288,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { let ident = self.lower_ident(*ident); @@ -301,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); - let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span); + let rhs = this.lower_const_item_rhs(rhs_kind, span); (ty, rhs) }, ); @@ -827,7 +827,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, def_id: self.local_def_id(v.id), data: self.lower_variant_data(hir_id, item_kind, &v.data), - disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)), + disr_expr: v + .disr_expr + .as_ref() + .map(|e| self.lower_anon_const_to_anon_const(e, e.value.span)), ident: self.lower_ident(v.ident), span: self.lower_span(v.span), } @@ -917,7 +920,10 @@ impl<'hir> LoweringContext<'_, 'hir> { None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, vis_span: self.lower_span(f.vis.span), - default: f.default.as_ref().map(|v| self.lower_anon_const_to_anon_const(v)), + default: f + .default + .as_ref() + .map(|v| self.lower_anon_const_to_anon_const(v, v.value.span)), ty, safety: self.lower_safety(f.safety, hir::Safety::Safe), } @@ -935,7 +941,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ident, generics, kind, has_default) = match &i.kind { AssocItemKind::Const(box ConstItem { - ident, generics, ty, rhs, define_opaque, .. + ident, + generics, + ty, + rhs_kind, + define_opaque, + .. }) => { let (generics, kind) = self.lower_generics( generics, @@ -946,15 +957,18 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); - let rhs = rhs - .as_ref() - .map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span)); - hir::TraitItemKind::Const(ty, rhs) + // Trait associated consts don't need an expression/body. + let rhs = if rhs_kind.has_expr() { + Some(this.lower_const_item_rhs(rhs_kind, i.span)) + } else { + None + }; + hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into()) }, ); if define_opaque.is_some() { - if rhs.is_some() { + if rhs_kind.has_expr() { self.lower_define_opaque(hir_id, &define_opaque); } else { self.dcx().span_err( @@ -964,7 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - (*ident, generics, kind, rhs.is_some()) + (*ident, generics, kind, rhs_kind.has_expr()) } AssocItemKind::Fn(box Fn { sig, ident, generics, body: None, define_opaque, .. @@ -1148,7 +1162,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ident, (generics, kind)) = match &i.kind { AssocItemKind::Const(box ConstItem { - ident, generics, ty, rhs, define_opaque, .. + ident, + generics, + ty, + rhs_kind, + define_opaque, + .. }) => ( *ident, self.lower_generics( @@ -1161,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); this.lower_define_opaque(hir_id, &define_opaque); - let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span); + let rhs = this.lower_const_item_rhs(rhs_kind, i.span); hir::ImplItemKind::Const(ty, rhs) }, ), @@ -1391,7 +1410,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. return self.lower_fn_body(decl, contract, |this| { - if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) + if find_attr!(attrs, AttributeKind::RustcIntrinsic) || this.tcx.is_sdylib_interface_build() { let span = this.lower_span(span); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8c6ee9d6bc63..6265a06410d5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -88,8 +88,6 @@ mod pat; mod path; pub mod stability; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, @@ -880,7 +878,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static { .. } | LifetimeRes::Error => return None, + LifetimeRes::Static { .. } | LifetimeRes::Error(..) => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -1933,26 +1931,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { source: LifetimeSource, syntax: LifetimeSyntax, ) -> &'hir hir::Lifetime { - let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); - let res = match res { - LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param), - LifetimeRes::Fresh { param, .. } => { - assert_eq!(ident.name, kw::UnderscoreLifetime); - let param = self.local_def_id(param); - hir::LifetimeKind::Param(param) - } - LifetimeRes::Infer => { - assert_eq!(ident.name, kw::UnderscoreLifetime); - hir::LifetimeKind::Infer - } - LifetimeRes::Static { .. } => { - assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); - hir::LifetimeKind::Static - } - LifetimeRes::Error => hir::LifetimeKind::Error, - LifetimeRes::ElidedAnchor { .. } => { - panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); + let res = if let Some(res) = self.resolver.get_lifetime_res(id) { + match res { + LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param), + LifetimeRes::Fresh { param, .. } => { + assert_eq!(ident.name, kw::UnderscoreLifetime); + let param = self.local_def_id(param); + hir::LifetimeKind::Param(param) + } + LifetimeRes::Infer => { + assert_eq!(ident.name, kw::UnderscoreLifetime); + hir::LifetimeKind::Infer + } + LifetimeRes::Static { .. } => { + assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); + hir::LifetimeKind::Static + } + LifetimeRes::Error(guar) => hir::LifetimeKind::Error(guar), + LifetimeRes::ElidedAnchor { .. } => { + panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); + } } + } else { + hir::LifetimeKind::Error(self.dcx().span_delayed_bug(ident.span, "unresolved lifetime")) }; debug!(?res); @@ -2016,12 +2017,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // AST resolution emitted an error on those parameters, so we lower them using // `ParamName::Error`. let ident = self.lower_ident(param.ident); - let param_name = - if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) { - ParamName::Error(ident) - } else { - ParamName::Plain(ident) - }; + let param_name = if let Some(LifetimeRes::Error(..)) = + self.resolver.get_lifetime_res(param.id) + { + ParamName::Error(ident) + } else { + ParamName::Plain(ident) + }; let kind = hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }; @@ -2376,15 +2378,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_const_item_rhs( &mut self, - attrs: &[hir::Attribute], - rhs: Option<&ConstItemRhs>, + rhs_kind: &ConstItemRhsKind, span: Span, ) -> hir::ConstItemRhs<'hir> { - match rhs { - Some(ConstItemRhs::TypeConst(anon)) => { + match rhs_kind { + ConstItemRhsKind::Body { rhs: Some(body) } => { + hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body))) + } + ConstItemRhsKind::Body { rhs: None } => { + hir::ConstItemRhs::Body(self.lower_const_body(span, None)) + } + ConstItemRhsKind::TypeConst { rhs: Some(anon) } => { hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg_and_alloc(anon)) } - None if find_attr!(attrs, AttributeKind::TypeConst(_)) => { + ConstItemRhsKind::TypeConst { rhs: None } => { let const_arg = ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Error( @@ -2394,10 +2401,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg)) } - Some(ConstItemRhs::Body(body)) => { - hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body))) - } - None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)), } } @@ -2427,15 +2430,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let lowered_args = self.arena.alloc_from_iter(args.iter().map(|arg| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &arg.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(arg) - }; - + let const_arg = self.lower_expr_to_const_arg_direct(arg); &*self.arena.alloc(const_arg) })); @@ -2447,16 +2442,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Tup(exprs) => { let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| { - let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&expr) - }; - + let expr = self.lower_expr_to_const_arg_direct(&expr); &*self.arena.alloc(expr) })); @@ -2496,16 +2482,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // then go unused as the `Target::ExprField` is not actually // corresponding to `Node::ExprField`. self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); - - let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&f.expr) - }; + let expr = self.lower_expr_to_const_arg_direct(&f.expr); &*self.arena.alloc(hir::ConstArgExprField { hir_id, @@ -2523,13 +2500,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Array(elements) => { let lowered_elems = self.arena.alloc_from_iter(elements.iter().map(|element| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &element.kind { - let def_id = self.local_def_id(anon_const.id); - assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(element) - }; + let const_arg = self.lower_expr_to_const_arg_direct(element); &*self.arena.alloc(const_arg) })); let array_expr = self.arena.alloc(hir::ConstArgArrayExpr { @@ -2559,6 +2530,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ExprKind::Call(..) | ExprKind::Tup(..) | ExprKind::Array(..) + | ExprKind::ConstBlock(..) ) { return self.lower_expr_to_const_arg_direct(expr); @@ -2572,10 +2544,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ConstArg { hir_id: self.lower_node_id(expr.id), - kind: hir::ConstArgKind::Literal(literal.node), + kind: hir::ConstArgKind::Literal { lit: literal.node, negated: false }, span, } } + ExprKind::Unary(UnOp::Neg, inner_expr) + if let ExprKind::Lit(literal) = &inner_expr.kind => + { + let span = expr.span; + let literal = self.lower_lit(literal, span); + + ConstArg { + hir_id: self.lower_node_id(expr.id), + kind: hir::ConstArgKind::Literal { lit: literal.node, negated: true }, + span, + } + } + ExprKind::ConstBlock(anon_const) => { + let def_id = self.local_def_id(anon_const.id); + assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); + self.lower_anon_const_to_const_arg(anon_const, span) + } _ => overly_complex_const(self), } } @@ -2586,11 +2575,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, anon: &AnonConst, ) -> &'hir hir::ConstArg<'hir> { - self.arena.alloc(self.lower_anon_const_to_const_arg(anon)) + self.arena.alloc(self.lower_anon_const_to_const_arg(anon, anon.value.span)) } #[instrument(level = "debug", skip(self))] - fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { + fn lower_anon_const_to_const_arg( + &mut self, + anon: &AnonConst, + span: Span, + ) -> hir::ConstArg<'hir> { let tcx = self.tcx; // We cannot change parsing depending on feature gates available, @@ -2601,7 +2594,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if tcx.features().min_generic_const_args() { return match anon.mgca_disambiguation { MgcaDisambiguation::AnonConst => { - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2647,7 +2640,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; } - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, anon.value.span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2657,7 +2650,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. - fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + fn lower_anon_const_to_anon_const( + &mut self, + c: &AnonConst, + span: Span, + ) -> &'hir hir::AnonConst { self.arena.alloc(self.with_new_scopes(c.value.span, |this| { let def_id = this.local_def_id(c.id); let hir_id = this.lower_node_id(c.id); @@ -2665,7 +2662,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, hir_id, body: this.lower_const_body(c.value.span, Some(&c.value)), - span: this.lower_span(c.value.span), + span: this.lower_span(span), } })) } diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 3e04f8b11ec9..fdc735fa8d4f 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -13,7 +13,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } 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_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl deleted file mode 100644 index b9117c83ae2f..000000000000 --- a/compiler/rustc_ast_passes/messages.ftl +++ /dev/null @@ -1,342 +0,0 @@ -ast_passes_abi_cannot_be_coroutine = - functions with the {$abi} ABI cannot be `{$coroutine_kind_str}` - .suggestion = remove the `{$coroutine_kind_str}` keyword from this definition - -ast_passes_abi_custom_safe_foreign_function = - foreign functions with the "custom" ABI cannot be safe - .suggestion = remove the `safe` keyword from this definition - -ast_passes_abi_custom_safe_function = - functions with the "custom" ABI must be unsafe - .suggestion = add the `unsafe` keyword to this definition - -ast_passes_abi_must_not_have_parameters_or_return_type= - invalid signature for `extern {$abi}` function - .note = functions with the {$abi} ABI cannot have any parameters or return type - .suggestion = remove the parameters and return type - -ast_passes_abi_must_not_have_return_type= - invalid signature for `extern {$abi}` function - .note = functions with the {$abi} ABI cannot have a return type - .help = remove the return type - -ast_passes_abi_x86_interrupt = - invalid signature for `extern "x86-interrupt"` function - .note = functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found {$param_count}) - -ast_passes_assoc_const_without_body = - associated constant in `impl` without body - .suggestion = provide a definition for the constant - -ast_passes_assoc_fn_without_body = - associated function in `impl` without body - .suggestion = provide a definition for the function - -ast_passes_assoc_type_without_body = - associated type in `impl` without body - .suggestion = provide a definition for the type - -ast_passes_async_fn_in_const_trait_or_trait_impl = - async functions are not allowed in `const` {$context -> - [trait_impl] trait impls - [impl] impls - *[trait] traits - } - .label = associated functions of `const` cannot be declared `async` - -ast_passes_at_least_one_trait = at least one trait must be specified - -ast_passes_auto_generic = auto traits cannot have generic parameters - .label = auto trait cannot have generic parameters - .suggestion = remove the parameters - -ast_passes_auto_items = auto traits cannot have associated items - .label = {ast_passes_auto_items} - .suggestion = remove the associated items - -ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds - .label = {ast_passes_auto_super_lifetime} - .suggestion = remove the super traits or lifetime bounds - -ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block - .cannot_have = cannot have a body - .invalid = the invalid body - .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body - -ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect - -ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions - .label = `extern "{$abi}"` because of this - .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -ast_passes_c_variadic_bad_naked_extern = `...` is not supported for `extern "{$abi}"` naked functions - .label = `extern "{$abi}"` because of this - .help = C-variadic function must have a compatible calling convention - -ast_passes_c_variadic_must_be_unsafe = - functions with a C variable argument list must be unsafe - .suggestion = add the `unsafe` keyword to this definition - -ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions - .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -ast_passes_c_variadic_not_supported = the `{$target}` target does not support c-variadic functions - -ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic - .const = `const` because of this - .variadic = C-variadic because of this - -ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}` - .const = `const` because of this - .coroutine = `{$coroutine_kind}` because of this - .label = {""} - -ast_passes_const_auto_trait = auto traits cannot be const - .help = remove the `const` keyword - -ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types - -ast_passes_const_without_body = - free constant item without body - .suggestion = provide a definition for the constant - -ast_passes_constraint_on_negative_bound = - associated type constraints not allowed on negative bounds - -ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic - .const = `{$coroutine_kind}` because of this - .variadic = C-variadic because of this - -ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses - .label = not supported - .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax - .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax - .note = see issue #20041 for more information - -ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block - -ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have `{$kw}` qualifier - .label = in this `extern` block - .suggestion = remove the `{$kw}` qualifier - -ast_passes_extern_invalid_safety = items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - .suggestion = add `unsafe` to this `extern` block - -ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers - .label = in this `extern` block - .note = this limitation may be lifted in the future; see issue #83942 for more information - -ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html - -ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr} - .suggestion = remove the {$remove_descr} - .label = `extern` block begins here - -ast_passes_extern_without_abi = `extern` declarations without an explicit ABI are disallowed - .suggestion = specify an ABI - .help = prior to Rust 2024, a default ABI was inferred - -ast_passes_extern_without_abi_sugg = `extern` declarations without an explicit ABI are deprecated - .label = ABI should be specified here - .suggestion = explicitly specify the {$default_abi} ABI - -ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel - .suggestion = remove the attribute - .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable - -ast_passes_fieldless_union = unions cannot have zero fields - -ast_passes_fn_body_extern = incorrect function inside `extern` block - .cannot_have = cannot have a body - .suggestion = remove the invalid body - .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block - .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body - -ast_passes_fn_param_c_var_args_not_last = - `...` must be the last argument of a C-variadic function - -ast_passes_fn_param_doc_comment = - documentation comments cannot be applied to function parameters - .label = doc comments are not allowed here - -ast_passes_fn_param_forbidden_attr = - allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - -ast_passes_fn_param_forbidden_self = - `self` parameter is only allowed in associated functions - .label = not semantically valid as function parameter - .note = associated functions are those in `impl` or `trait` definitions - -ast_passes_fn_param_too_many = - function can not have more than {$max_num_args} arguments - -ast_passes_fn_ptr_invalid_safety = function pointers cannot be declared with `safe` safety qualifier - .suggestion = remove safe from this item - -ast_passes_fn_without_body = - free function without a body - .suggestion = provide a definition for the function - -ast_passes_forbidden_bound = - bounds cannot be used in this context - -ast_passes_forbidden_const_param = - late-bound const parameters cannot be used currently - -ast_passes_forbidden_default = - `default` is only allowed on items in trait impls - .label = `default` because of this - -ast_passes_forbidden_non_lifetime_param = - only lifetime parameters can be used in this context - -ast_passes_generic_before_constraints = generic arguments must come before the first constraint - .constraints = {$constraint_len -> - [one] constraint - *[other] constraints - } - .args = generic {$args_len -> - [one] argument - *[other] arguments - } - .empty_string = {""}, - .suggestion = move the {$constraint_len -> - [one] constraint - *[other] constraints - } after the generic {$args_len -> - [one] argument - *[other] arguments - } - -ast_passes_generic_default_trailing = generic parameters with a default must be trailing - -ast_passes_impl_fn_const = - redundant `const` fn marker in const impl - .parent_constness = this declares all associated functions implicitly const - .label = remove the `const` - -ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed - .help = remove one of these features - -ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier - .suggestion = remove safe from this item - -ast_passes_item_underscore = `{$kind}` items in this context need a name - .label = `_` is not a valid name for this `{$kind}` item - -ast_passes_match_arm_with_no_body = - `match` arm with no body - .suggestion = add a body after the pattern - -ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe - .suggestion = needs `unsafe` before the extern keyword - -ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe - .suggestion = needs `unsafe` before the extern keyword - -ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name - .help = consider using the `#[path]` attribute to specify filesystem path - -ast_passes_negative_bound_not_supported = - negative bounds are not supported - -ast_passes_negative_bound_with_parenthetical_notation = - parenthetical notation may not be used for negative bounds - -ast_passes_nested_impl_trait = nested `impl Trait` is not allowed - .outer = outer `impl Trait` - .inner = nested `impl Trait` here - -ast_passes_nested_lifetimes = nested quantification of lifetimes - -ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier - -ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax - .help = use `auto trait Trait {"{}"}` instead - -ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters - .suggestion = reorder the parameters: lifetimes, then consts and types - -ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies - .label = pattern not allowed in function without body - -ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types - -ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations - .label = pattern not allowed in foreign function - -ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing syntax - .label = second `use<...>` here - -ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc} - -ast_passes_scalable_vector_not_tuple_struct = scalable vectors must be tuple structs - -ast_passes_static_without_body = - free static item without body - .suggestion = provide a definition for the static - -ast_passes_tilde_const_disallowed = `[const]` is not allowed here - .closure = closures cannot have `[const]` trait bounds - .function = this function is not `const`, so it cannot have `[const]` trait bounds - .trait = this trait is not `const`, so it cannot have `[const]` trait bounds - .trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds - .impl = inherent impls cannot have `[const]` trait bounds - .trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds - .trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds - .inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds - .struct = structs cannot have `[const]` trait bounds - .enum = enums cannot have `[const]` trait bounds - .union = unions cannot have `[const]` trait bounds - .anon_const = anonymous constants cannot have `[const]` trait bounds - .object = trait objects cannot have `[const]` trait bounds - .item = this item cannot have `[const]` trait bounds - -ast_passes_trait_fn_const = - functions in {$in_impl -> - [true] trait impls - *[false] traits - } cannot be declared const - .label = functions in {$in_impl -> - [true] trait impls - *[false] traits - } cannot be const - .const_context_label = this declares all associated functions implicitly const - .remove_const_sugg = remove the `const`{$requires_multiple_changes -> - [true] {" ..."} - *[false] {""} - } - .make_impl_const_sugg = ... and declare the impl to be const instead - .make_trait_const_sugg = ... and declare the trait to be const instead - -ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted - -ast_passes_ty_alias_without_body = - free type alias without body - .suggestion = provide a definition for the type - -ast_passes_unsafe_item = {$kind} cannot be declared unsafe - -ast_passes_unsafe_negative_impl = negative impls cannot be unsafe - .negative = negative because of this - .unsafe = unsafe because of this - -ast_passes_unsafe_static = - static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - -ast_passes_visibility_not_permitted = - visibility qualifiers are not permitted here - .enum_variant = enum variants and their fields always share the visibility of the enum they are in - .trait_impl = trait items always share the visibility of their trait - .individual_impl_items = place qualifiers on individual impl items instead - .individual_foreign_items = place qualifiers on individual foreign items instead - .remove_qualifier_sugg = remove the qualifier - -ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases - .note = see issue #112792 for more information - .help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable - -ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases - .note = see issue #89122 for more information - .remove_suggestion = remove this `where` - .move_suggestion = move it to the end of the type declaration diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2457e0a777e4..b9fb20b68971 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1361,9 +1361,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } }); } - ItemKind::Const(box ConstItem { defaultness, ident, rhs, .. }) => { + ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => { self.check_defaultness(item.span, *defaultness); - if rhs.is_none() { + if !rhs_kind.has_expr() { self.dcx().emit_err(errors::ConstWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1715,11 +1715,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let AssocCtxt::Impl { .. } = ctxt { match &item.kind { - AssocItemKind::Const(box ConstItem { rhs: None, .. }) => { - self.dcx().emit_err(errors::AssocConstWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); + AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => { + if !rhs_kind.has_expr() { + self.dcx().emit_err(errors::AssocConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } AssocItemKind::Fn(box Fn { body, .. }) => { if body.is_none() && !self.is_sdylib_interface { diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 22adaae8c6f2..dd260aede489 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -7,64 +7,72 @@ use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(ast_passes_visibility_not_permitted, code = E0449)] +#[diag("visibility qualifiers are not permitted here", code = E0449)] pub(crate) struct VisibilityNotPermitted { #[primary_span] pub span: Span, #[subdiagnostic] pub note: VisibilityNotPermittedNote, - #[suggestion( - ast_passes_remove_qualifier_sugg, - code = "", - applicability = "machine-applicable" - )] + #[suggestion("remove the qualifier", code = "", applicability = "machine-applicable")] pub remove_qualifier_sugg: Span, } #[derive(Subdiagnostic)] pub(crate) enum VisibilityNotPermittedNote { - #[note(ast_passes_enum_variant)] + #[note("enum variants and their fields always share the visibility of the enum they are in")] EnumVariant, - #[note(ast_passes_trait_impl)] + #[note("trait items always share the visibility of their trait")] TraitImpl, - #[note(ast_passes_individual_impl_items)] + #[note("place qualifiers on individual impl items instead")] IndividualImplItems, - #[note(ast_passes_individual_foreign_items)] + #[note("place qualifiers on individual foreign items instead")] IndividualForeignItems, } #[derive(Diagnostic)] -#[diag(ast_passes_impl_fn_const)] +#[diag("redundant `const` fn marker in const impl")] pub(crate) struct ImplFnConst { #[primary_span] - #[suggestion(ast_passes_label, code = "", applicability = "machine-applicable")] + #[suggestion("remove the `const`", code = "", applicability = "machine-applicable")] pub span: Span, - #[label(ast_passes_parent_constness)] + #[label("this declares all associated functions implicitly const")] pub parent_constness: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_trait_fn_const, code = E0379)] +#[diag("functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be declared const", code = E0379)] pub(crate) struct TraitFnConst { #[primary_span] - #[label] + #[label( + "functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be const" + )] pub span: Span, pub in_impl: bool, - #[label(ast_passes_const_context_label)] + #[label("this declares all associated functions implicitly const")] pub const_context_label: Option, - #[suggestion(ast_passes_remove_const_sugg, code = "")] + #[suggestion( + "remove the `const`{$requires_multiple_changes -> + [true] {\" ...\"} + *[false] {\"\"} + }", + code = "" + )] pub remove_const_sugg: (Span, Applicability), pub requires_multiple_changes: bool, #[suggestion( - ast_passes_make_impl_const_sugg, + "... and declare the impl to be const instead", code = "const ", applicability = "maybe-incorrect" )] pub make_impl_const_sugg: Option, #[suggestion( - ast_passes_make_trait_const_sugg, + "... and declare the trait to be const instead", code = "const ", applicability = "maybe-incorrect" )] @@ -72,31 +80,37 @@ pub(crate) struct TraitFnConst { } #[derive(Diagnostic)] -#[diag(ast_passes_async_fn_in_const_trait_or_trait_impl)] +#[diag( + "async functions are not allowed in `const` {$context -> + [trait_impl] trait impls + [impl] impls + *[trait] traits + }" +)] pub(crate) struct AsyncFnInConstTraitOrTraitImpl { #[primary_span] pub async_keyword: Span, pub context: &'static str, - #[label] + #[label("associated functions of `const` cannot be declared `async`")] pub const_keyword: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_bound)] +#[diag("bounds cannot be used in this context")] pub(crate) struct ForbiddenBound { #[primary_span] pub spans: Vec, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_const_param)] +#[diag("late-bound const parameters cannot be used currently")] pub(crate) struct ForbiddenConstParam { #[primary_span] pub const_param_spans: Vec, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_too_many)] +#[diag("function can not have more than {$max_num_args} arguments")] pub(crate) struct FnParamTooMany { #[primary_span] pub span: Span, @@ -104,105 +118,135 @@ pub(crate) struct FnParamTooMany { } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_c_var_args_not_last)] +#[diag("`...` must be the last argument of a C-variadic function")] pub(crate) struct FnParamCVarArgsNotLast { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_doc_comment)] +#[diag("documentation comments cannot be applied to function parameters")] pub(crate) struct FnParamDocComment { #[primary_span] - #[label] + #[label("doc comments are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_forbidden_attr)] +#[diag( + "allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters" +)] pub(crate) struct FnParamForbiddenAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_forbidden_self)] -#[note] +#[diag("`self` parameter is only allowed in associated functions")] +#[note("associated functions are those in `impl` or `trait` definitions")] pub(crate) struct FnParamForbiddenSelf { #[primary_span] - #[label] + #[label("not semantically valid as function parameter")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_default)] +#[diag("`default` is only allowed on items in trait impls")] pub(crate) struct ForbiddenDefault { #[primary_span] pub span: Span, - #[label] + #[label("`default` because of this")] pub def_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_const_without_body)] +#[diag("associated constant in `impl` without body")] pub(crate) struct AssocConstWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the constant", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_fn_without_body)] +#[diag("associated function in `impl` without body")] pub(crate) struct AssocFnWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " {{ }}", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the function", + code = " {{ }}", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_type_without_body)] +#[diag("associated type in `impl` without body")] pub(crate) struct AssocTypeWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the type", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_without_body)] +#[diag("free constant item without body")] pub(crate) struct ConstWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the constant", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_static_without_body)] +#[diag("free static item without body")] pub(crate) struct StaticWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the static", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_ty_alias_without_body)] +#[diag("free type alias without body")] pub(crate) struct TyAliasWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the type", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_without_body)] +#[diag("free function without a body")] pub(crate) struct FnWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " {{ }}", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the function", + code = " {{ }}", + applicability = "has-placeholders" + )] pub replace_span: Span, #[subdiagnostic] pub extern_block_suggestion: Option, @@ -210,14 +254,20 @@ pub(crate) struct FnWithoutBody { #[derive(Subdiagnostic)] pub(crate) enum ExternBlockSuggestion { - #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "if you meant to declare an externally defined function, use an `extern` block", + applicability = "maybe-incorrect" + )] Implicit { #[suggestion_part(code = "extern {{")] start_span: Span, #[suggestion_part(code = " }}")] end_span: Span, }, - #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "if you meant to declare an externally defined function, use an `extern` block", + applicability = "maybe-incorrect" + )] Explicit { #[suggestion_part(code = "extern \"{abi}\" {{")] start_span: Span, @@ -228,37 +278,44 @@ pub(crate) enum ExternBlockSuggestion { } #[derive(Diagnostic)] -#[diag(ast_passes_extern_invalid_safety)] +#[diag("items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers")] pub(crate) struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, - #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add `unsafe` to this `extern` block", + code = "unsafe ", + applicability = "machine-applicable", + style = "verbose" + )] pub block: Option, } #[derive(Diagnostic)] -#[diag(ast_passes_item_invalid_safety)] +#[diag( + "items outside of `unsafe extern {\"{ }\"}` cannot be declared with `safe` safety qualifier" +)] pub(crate) struct InvalidSafetyOnItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_ptr_invalid_safety)] +#[diag("function pointers cannot be declared with `safe` safety qualifier")] pub(crate) struct InvalidSafetyOnFnPtr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_static)] +#[diag("static items cannot be declared with `unsafe` safety qualifier outside of `extern` block")] pub(crate) struct UnsafeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_bound_in_context)] +#[diag("bounds on `type`s in {$ctx} have no effect")] pub(crate) struct BoundInContext<'a> { #[primary_span] pub span: Span, @@ -266,83 +323,93 @@ pub(crate) struct BoundInContext<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_extern_types_cannot)] -#[note(ast_passes_extern_keyword_link)] +#[diag("`type`s inside `extern` blocks cannot have {$descr}")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct ExternTypesCannotHave<'a> { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove the {$remove_descr}", code = "", applicability = "maybe-incorrect")] pub span: Span, pub descr: &'a str, pub remove_descr: &'a str, - #[label] + #[label("`extern` block begins here")] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_body_in_extern)] -#[note(ast_passes_extern_keyword_link)] +#[diag("incorrect `{$kind}` inside `extern` block")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct BodyInExtern<'a> { #[primary_span] - #[label(ast_passes_cannot_have)] + #[label("cannot have a body")] pub span: Span, - #[label(ast_passes_invalid)] + #[label("the invalid body")] pub body: Span, - #[label(ast_passes_existing)] + #[label( + "`extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body" + )] pub block: Span, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_body_extern)] -#[help] -#[note(ast_passes_extern_keyword_link)] +#[diag("incorrect function inside `extern` block")] +#[help( + "you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block" +)] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct FnBodyInExtern { #[primary_span] - #[label(ast_passes_cannot_have)] + #[label("cannot have a body")] pub span: Span, - #[suggestion(code = ";", applicability = "maybe-incorrect")] + #[suggestion("remove the invalid body", code = ";", applicability = "maybe-incorrect")] pub body: Span, - #[label] + #[label( + "`extern` blocks define existing foreign functions and functions inside of them cannot have a body" + )] pub block: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_fn_qualifiers)] +#[diag("functions in `extern` blocks cannot have `{$kw}` qualifier")] pub(crate) struct FnQualifierInExtern { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove the `{$kw}` qualifier", code = "", applicability = "maybe-incorrect")] pub span: Span, - #[label] + #[label("in this `extern` block")] pub block: Span, pub kw: &'static str, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_item_ascii)] -#[note] +#[diag("items in `extern` blocks cannot use non-ascii identifiers")] +#[note( + "this limitation may be lifted in the future; see issue #83942 for more information" +)] pub(crate) struct ExternItemAscii { #[primary_span] pub span: Span, - #[label] + #[label("in this `extern` block")] pub block: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_no_extern)] -#[help] +#[diag("`...` is not supported for non-extern functions")] +#[help( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct CVariadicNoExtern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_must_be_unsafe)] +#[diag("functions with a C variable argument list must be unsafe")] pub(crate) struct CVariadicMustBeUnsafe { #[primary_span] pub span: Span, #[suggestion( - ast_passes_suggestion, + "add the `unsafe` keyword to this definition", applicability = "maybe-incorrect", code = "unsafe ", style = "verbose" @@ -351,46 +418,48 @@ pub(crate) struct CVariadicMustBeUnsafe { } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_bad_extern)] -#[help] +#[diag("`...` is not supported for `extern \"{$abi}\"` functions")] +#[help( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct CVariadicBadExtern { #[primary_span] pub span: Span, pub abi: &'static str, - #[label] + #[label("`extern \"{$abi}\"` because of this")] pub extern_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_bad_naked_extern)] -#[help] +#[diag("`...` is not supported for `extern \"{$abi}\"` naked functions")] +#[help("C-variadic function must have a compatible calling convention")] pub(crate) struct CVariadicBadNakedExtern { #[primary_span] pub span: Span, pub abi: &'static str, - #[label] + #[label("`extern \"{$abi}\"` because of this")] pub extern_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_item_underscore)] +#[diag("`{$kind}` items in this context need a name")] pub(crate) struct ItemUnderscore<'a> { #[primary_span] - #[label] + #[label("`_` is not a valid name for this `{$kind}` item")] pub span: Span, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(ast_passes_nomangle_ascii, code = E0754)] +#[diag("`#[no_mangle]` requires ASCII identifier", code = E0754)] pub(crate) struct NoMangleAscii { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_module_nonascii, code = E0754)] -#[help] +#[diag("trying to load file for module `{$name}` with non-ascii identifier name", code = E0754)] +#[help("consider using the `#[path]` attribute to specify filesystem path")] pub(crate) struct ModuleNonAscii { #[primary_span] pub span: Span, @@ -398,55 +467,91 @@ pub(crate) struct ModuleNonAscii { } #[derive(Diagnostic)] -#[diag(ast_passes_auto_generic, code = E0567)] +#[diag("auto traits cannot have generic parameters", code = E0567)] pub(crate) struct AutoTraitGeneric { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the parameters", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub span: Span, - #[label] + #[label("auto trait cannot have generic parameters")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_auto_super_lifetime, code = E0568)] +#[diag("auto traits cannot have super traits or lifetime bounds", code = E0568)] pub(crate) struct AutoTraitBounds { #[primary_span] pub span: Vec, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the super traits or lifetime bounds", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub removal: Span, - #[label] + #[label("auto traits cannot have super traits or lifetime bounds")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_auto_items, code = E0380)] +#[diag("auto traits cannot have associated items", code = E0380)] pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the associated items", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub total: Span, - #[label] + #[label("auto traits cannot have associated items")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_auto_trait)] -#[help] +#[diag("auto traits cannot be const")] +#[help("remove the `const` keyword")] pub(crate) struct ConstAutoTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_generic_before_constraints)] +#[diag("generic arguments must come before the first constraint")] pub(crate) struct ArgsBeforeConstraint { #[primary_span] pub arg_spans: Vec, - #[label(ast_passes_constraints)] + #[label( + "{$constraint_len -> + [one] constraint + *[other] constraints + }" + )] pub constraints: Span, - #[label(ast_passes_args)] + #[label( + "generic {$args_len -> + [one] argument + *[other] arguments + }" + )] pub args: Span, - #[suggestion(code = "{suggestion}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "move the {$constraint_len -> + [one] constraint + *[other] constraints + } after the generic {$args_len -> + [one] argument + *[other] arguments + }", + code = "{suggestion}", + applicability = "machine-applicable", + style = "verbose" + )] pub data: Span, pub suggestion: String, pub constraint_len: usize, @@ -467,43 +572,47 @@ impl Subdiagnostic for EmptyLabelManySpans { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)] +#[diag("patterns aren't allowed in function pointer types", code = E0561)] pub(crate) struct PatternFnPointer { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_trait_object_single_bound, code = E0226)] +#[diag("only a single explicit lifetime bound is permitted", code = E0226)] pub(crate) struct TraitObjectBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_nested_impl_trait, code = E0666)] +#[diag("nested `impl Trait` is not allowed", code = E0666)] pub(crate) struct NestedImplTrait { #[primary_span] pub span: Span, - #[label(ast_passes_outer)] + #[label("outer `impl Trait`")] pub outer: Span, - #[label(ast_passes_inner)] + #[label("nested `impl Trait` here")] pub inner: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_at_least_one_trait)] +#[diag("at least one trait must be specified")] pub(crate) struct AtLeastOneTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_out_of_order_params)] +#[diag("{$param_ord} parameters must be declared prior to {$max_param} parameters")] pub(crate) struct OutOfOrderParams<'a> { #[primary_span] pub spans: Vec, - #[suggestion(code = "{ordered_params}", applicability = "machine-applicable")] + #[suggestion( + "reorder the parameters: lifetimes, then consts and types", + code = "{ordered_params}", + applicability = "machine-applicable" + )] pub sugg_span: Span, pub param_ord: &'a ParamKindOrd, pub max_param: &'a ParamKindOrd, @@ -511,26 +620,26 @@ pub(crate) struct OutOfOrderParams<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_obsolete_auto)] -#[help] +#[diag("`impl Trait for .. {\"{}\"}` is an obsolete syntax")] +#[help("use `auto trait Trait {\"{}\"}` instead")] pub(crate) struct ObsoleteAuto { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_negative_impl, code = E0198)] +#[diag("negative impls cannot be unsafe", code = E0198)] pub(crate) struct UnsafeNegativeImpl { #[primary_span] pub span: Span, - #[label(ast_passes_negative)] + #[label("negative because of this")] pub negative: Span, - #[label(ast_passes_unsafe)] + #[label("unsafe because of this")] pub r#unsafe: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_item)] +#[diag("{$kind} cannot be declared unsafe")] pub(crate) struct UnsafeItem { #[primary_span] pub span: Span, @@ -538,39 +647,43 @@ pub(crate) struct UnsafeItem { } #[derive(Diagnostic)] -#[diag(ast_passes_missing_unsafe_on_extern)] +#[diag("extern blocks must be unsafe")] pub(crate) struct MissingUnsafeOnExtern { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(ast_passes_missing_unsafe_on_extern_lint)] +#[diag("extern blocks should be unsafe")] pub(crate) struct MissingUnsafeOnExternLint { - #[suggestion(code = "unsafe ", applicability = "machine-applicable")] + #[suggestion( + "needs `unsafe` before the extern keyword", + code = "unsafe ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fieldless_union)] +#[diag("unions cannot have zero fields")] pub(crate) struct FieldlessUnion { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_where_clause_after_type_alias)] -#[note] +#[diag("where clauses are not allowed after the type for type aliases")] +#[note("see issue #112792 for more information")] pub(crate) struct WhereClauseAfterTypeAlias { #[primary_span] pub span: Span, - #[help] + #[help("add `#![feature(lazy_type_alias)]` to the crate attributes to enable")] pub help: bool, } #[derive(Diagnostic)] -#[diag(ast_passes_where_clause_before_type_alias)] -#[note] +#[diag("where clauses are not allowed before the type for type aliases")] +#[note("see issue #89122 for more information")] pub(crate) struct WhereClauseBeforeTypeAlias { #[primary_span] pub span: Span, @@ -580,13 +693,13 @@ pub(crate) struct WhereClauseBeforeTypeAlias { #[derive(Subdiagnostic)] pub(crate) enum WhereClauseBeforeTypeAliasSugg { - #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] + #[suggestion("remove this `where`", applicability = "machine-applicable", code = "")] Remove { #[primary_span] span: Span, }, #[multipart_suggestion( - ast_passes_move_suggestion, + "move it to the end of the type declaration", applicability = "machine-applicable", style = "verbose" )] @@ -600,21 +713,21 @@ pub(crate) enum WhereClauseBeforeTypeAliasSugg { } #[derive(Diagnostic)] -#[diag(ast_passes_generic_default_trailing)] +#[diag("generic parameters with a default must be trailing")] pub(crate) struct GenericDefaultTrailing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_nested_lifetimes, code = E0316)] +#[diag("nested quantification of lifetimes", code = E0316)] pub(crate) struct NestedLifetimes { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_bound_trait_object)] +#[diag("const trait bounds are not allowed in trait object types")] pub(crate) struct ConstBoundTraitObject { #[primary_span] pub span: Span, @@ -623,7 +736,7 @@ pub(crate) struct ConstBoundTraitObject { // FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic. // FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here). #[derive(Diagnostic)] -#[diag(ast_passes_tilde_const_disallowed)] +#[diag("`[const]` is not allowed here")] pub(crate) struct TildeConstDisallowed { #[primary_span] pub span: Span, @@ -633,108 +746,108 @@ pub(crate) struct TildeConstDisallowed { #[derive(Subdiagnostic, Copy, Clone)] pub(crate) enum TildeConstReason { - #[note(ast_passes_closure)] + #[note("closures cannot have `[const]` trait bounds")] Closure, - #[note(ast_passes_function)] + #[note("this function is not `const`, so it cannot have `[const]` trait bounds")] Function { #[primary_span] ident: Span, }, - #[note(ast_passes_trait)] + #[note("this trait is not `const`, so it cannot have `[const]` trait bounds")] Trait { #[primary_span] span: Span, }, - #[note(ast_passes_trait_impl)] + #[note("this impl is not `const`, so it cannot have `[const]` trait bounds")] TraitImpl { #[primary_span] span: Span, }, - #[note(ast_passes_impl)] + #[note("inherent impls cannot have `[const]` trait bounds")] Impl { #[primary_span] span: Span, }, - #[note(ast_passes_trait_assoc_ty)] + #[note("associated types in non-`const` traits cannot have `[const]` trait bounds")] TraitAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_trait_impl_assoc_ty)] + #[note("associated types in non-const impls cannot have `[const]` trait bounds")] TraitImplAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_inherent_assoc_ty)] + #[note("inherent associated types cannot have `[const]` trait bounds")] InherentAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_struct)] + #[note("structs cannot have `[const]` trait bounds")] Struct { #[primary_span] span: Span, }, - #[note(ast_passes_enum)] + #[note("enums cannot have `[const]` trait bounds")] Enum { #[primary_span] span: Span, }, - #[note(ast_passes_union)] + #[note("unions cannot have `[const]` trait bounds")] Union { #[primary_span] span: Span, }, - #[note(ast_passes_anon_const)] + #[note("anonymous constants cannot have `[const]` trait bounds")] AnonConst { #[primary_span] span: Span, }, - #[note(ast_passes_object)] + #[note("trait objects cannot have `[const]` trait bounds")] TraitObject, - #[note(ast_passes_item)] + #[note("this item cannot have `[const]` trait bounds")] Item, } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_coroutine)] +#[diag("functions cannot be both `const` and `{$coroutine_kind}`")] pub(crate) struct ConstAndCoroutine { #[primary_span] pub spans: Vec, - #[label(ast_passes_const)] + #[label("`const` because of this")] pub const_span: Span, - #[label(ast_passes_coroutine)] + #[label("`{$coroutine_kind}` because of this")] pub coroutine_span: Span, - #[label] + #[label("{\"\"}")] pub span: Span, pub coroutine_kind: &'static str, } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_c_variadic)] +#[diag("functions cannot be both `const` and C-variadic")] pub(crate) struct ConstAndCVariadic { #[primary_span] pub spans: Vec, - #[label(ast_passes_const)] + #[label("`const` because of this")] pub const_span: Span, - #[label(ast_passes_variadic)] + #[label("C-variadic because of this")] pub variadic_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_coroutine_and_c_variadic)] +#[diag("functions cannot be both `{$coroutine_kind}` and C-variadic")] pub(crate) struct CoroutineAndCVariadic { #[primary_span] pub spans: Vec, pub coroutine_kind: &'static str, - #[label(ast_passes_const)] + #[label("`{$coroutine_kind}` because of this")] pub coroutine_span: Span, - #[label(ast_passes_variadic)] + #[label("C-variadic because of this")] pub variadic_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_not_supported)] +#[diag("the `{$target}` target does not support c-variadic functions")] pub(crate) struct CVariadicNotSupported<'a> { #[primary_span] pub variadic_span: Span, @@ -742,29 +855,29 @@ pub(crate) struct CVariadicNotSupported<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_foreign, code = E0130)] +#[diag("patterns aren't allowed in foreign function declarations", code = E0130)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInForeign { #[primary_span] - #[label] + #[label("pattern not allowed in foreign function")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_bodiless, code = E0642)] +#[diag("patterns aren't allowed in functions without bodies", code = E0642)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInBodiless { #[primary_span] - #[label] + #[label("pattern not allowed in function without body")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_equality_in_where)] -#[note] +#[diag("equality constraints are not yet supported in `where` clauses")] +#[note("see issue #20041 for more information")] pub(crate) struct EqualityInWhere { #[primary_span] - #[label] + #[label("not supported")] pub span: Span, #[subdiagnostic] pub assoc: Option, @@ -774,7 +887,7 @@ pub(crate) struct EqualityInWhere { #[derive(Subdiagnostic)] #[suggestion( - ast_passes_suggestion, + "if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax", code = "{param}: {path}", style = "verbose", applicability = "maybe-incorrect" @@ -788,7 +901,10 @@ pub(crate) struct AssociatedSuggestion { } #[derive(Subdiagnostic)] -#[multipart_suggestion(ast_passes_suggestion_path, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax", + applicability = "maybe-incorrect" +)] pub(crate) struct AssociatedSuggestion2 { #[suggestion_part(code = "{args}")] pub span: Span, @@ -800,33 +916,29 @@ pub(crate) struct AssociatedSuggestion2 { } #[derive(Diagnostic)] -#[diag(ast_passes_feature_on_non_nightly, code = E0554)] +#[diag("`#![feature]` may not be used on the {$channel} release channel", code = E0554)] pub(crate) struct FeatureOnNonNightly { #[primary_span] pub span: Span, pub channel: &'static str, #[subdiagnostic] pub stable_features: Vec, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the attribute", code = "", applicability = "machine-applicable")] pub sugg: Option, } +#[derive(Subdiagnostic)] +#[help( + "the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable" +)] pub(crate) struct StableFeature { pub name: Symbol, pub since: Symbol, } -impl Subdiagnostic for StableFeature { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.arg("name", self.name); - diag.arg("since", self.since); - diag.help(fluent::ast_passes_stable_since); - } -} - #[derive(Diagnostic)] -#[diag(ast_passes_incompatible_features)] -#[help] +#[diag("`{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed")] +#[help("remove one of these features")] pub(crate) struct IncompatibleFeatures { #[primary_span] pub spans: Vec, @@ -835,28 +947,38 @@ pub(crate) struct IncompatibleFeatures { } #[derive(Diagnostic)] -#[diag(ast_passes_negative_bound_not_supported)] +#[diag("`{$parent}` requires {$missing} to be enabled")] +#[help("enable all of these features")] +pub(crate) struct MissingDependentFeatures { + #[primary_span] + pub parent_span: Span, + pub parent: Symbol, + pub missing: String, +} + +#[derive(Diagnostic)] +#[diag("negative bounds are not supported")] pub(crate) struct NegativeBoundUnsupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_constraint_on_negative_bound)] +#[diag("associated type constraints not allowed on negative bounds")] pub(crate) struct ConstraintOnNegativeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_negative_bound_with_parenthetical_notation)] +#[diag("parenthetical notation may not be used for negative bounds")] pub(crate) struct NegativeBoundWithParentheticalNotation { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_match_arm_with_no_body)] +#[diag("`match` arm with no body")] pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, @@ -864,6 +986,7 @@ pub(crate) struct MatchArmWithNoBody { // any logic looking at the arm being replaced if there was a comma already or not for the // resulting code to be correct. #[suggestion( + "add a body after the pattern", code = " => {{ todo!() }}", applicability = "has-placeholders", style = "verbose" @@ -872,7 +995,7 @@ pub(crate) struct MatchArmWithNoBody { } #[derive(Diagnostic)] -#[diag(ast_passes_precise_capturing_not_allowed_here)] +#[diag("`use<...>` precise capturing syntax not allowed in {$loc}")] pub(crate) struct PreciseCapturingNotAllowedHere { #[primary_span] pub span: Span, @@ -880,39 +1003,43 @@ pub(crate) struct PreciseCapturingNotAllowedHere { } #[derive(Diagnostic)] -#[diag(ast_passes_precise_capturing_duplicated)] +#[diag("duplicate `use<...>` precise capturing syntax")] pub(crate) struct DuplicatePreciseCapturing { #[primary_span] pub bound1: Span, - #[label] + #[label("second `use<...>` here")] pub bound2: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_without_abi)] -#[help] +#[diag("`extern` declarations without an explicit ABI are disallowed")] +#[help("prior to Rust 2024, a default ABI was inferred")] pub(crate) struct MissingAbi { #[primary_span] - #[suggestion(code = "extern \"\"", applicability = "has-placeholders")] + #[suggestion("specify an ABI", code = "extern \"\"", applicability = "has-placeholders")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(ast_passes_extern_without_abi_sugg)] +#[diag("`extern` declarations without an explicit ABI are deprecated")] pub(crate) struct MissingAbiSugg { - #[suggestion(code = "extern {default_abi}", applicability = "machine-applicable")] + #[suggestion( + "explicitly specify the {$default_abi} ABI", + code = "extern {default_abi}", + applicability = "machine-applicable" + )] pub span: Span, pub default_abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_safe_foreign_function)] +#[diag("foreign functions with the \"custom\" ABI cannot be safe")] pub(crate) struct AbiCustomSafeForeignFunction { #[primary_span] pub span: Span, #[suggestion( - ast_passes_suggestion, + "remove the `safe` keyword from this definition", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -921,14 +1048,14 @@ pub(crate) struct AbiCustomSafeForeignFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_safe_function)] +#[diag("functions with the \"custom\" ABI must be unsafe")] pub(crate) struct AbiCustomSafeFunction { #[primary_span] pub span: Span, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "add the `unsafe` keyword to this definition", applicability = "maybe-incorrect", code = "unsafe ", style = "verbose" @@ -937,14 +1064,14 @@ pub(crate) struct AbiCustomSafeFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_cannot_be_coroutine)] +#[diag("functions with the {$abi} ABI cannot be `{$coroutine_kind_str}`")] pub(crate) struct AbiCannotBeCoroutine { #[primary_span] pub span: Span, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "remove the `{$coroutine_kind_str}` keyword from this definition", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -954,15 +1081,15 @@ pub(crate) struct AbiCannotBeCoroutine { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_must_not_have_parameters_or_return_type)] -#[note] +#[diag("invalid signature for `extern {$abi}` function")] +#[note("functions with the {$abi} ABI cannot have any parameters or return type")] pub(crate) struct AbiMustNotHaveParametersOrReturnType { #[primary_span] pub spans: Vec, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "remove the parameters and return type", applicability = "maybe-incorrect", code = "{padding}fn {symbol}()", style = "verbose" @@ -973,18 +1100,20 @@ pub(crate) struct AbiMustNotHaveParametersOrReturnType { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_must_not_have_return_type)] -#[note] +#[diag("invalid signature for `extern {$abi}` function")] +#[note("functions with the {$abi} ABI cannot have a return type")] pub(crate) struct AbiMustNotHaveReturnType { #[primary_span] - #[help] + #[help("remove the return type")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(ast_passes_abi_x86_interrupt)] -#[note] +#[diag("invalid signature for `extern \"x86-interrupt\"` function")] +#[note( + "functions with the \"x86-interrupt\" ABI must be have either 1 or 2 parameters (but found {$param_count})" +)] pub(crate) struct AbiX86Interrupt { #[primary_span] pub spans: Vec, @@ -992,7 +1121,7 @@ pub(crate) struct AbiX86Interrupt { } #[derive(Diagnostic)] -#[diag(ast_passes_scalable_vector_not_tuple_struct)] +#[diag("scalable vectors must be tuple structs")] pub(crate) struct ScalableVectorNotTupleStruct { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6376cab364db..4523b4c14163 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,5 +1,6 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{self as ast, AttrVec, NodeId, PatKind, attr, token}; +use rustc_errors::msg; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features}; use rustc_session::Session; use rustc_session::parse::{feature_err, feature_warn}; @@ -124,7 +125,7 @@ impl<'a> PostExpansionVisitor<'a> { &self, non_lifetime_binders, non_lt_param_spans, - crate::fluent_generated::ast_passes_forbidden_non_lifetime_param + msg!("only lifetime parameters can be used in this context") ); // FIXME(non_lifetime_binders): Const bound params are pretty broken. @@ -248,6 +249,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { self.check_impl_trait(ty, false) } + ast::ItemKind::Const(box ast::ConstItem { + rhs_kind: ast::ConstItemRhsKind::TypeConst { .. }, + .. + }) => { + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(min_generic_const_args)] + gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable"); + } _ => {} } @@ -329,15 +338,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_expr(&mut self, e: &'a ast::Expr) { match e.kind { ast::ExprKind::TryBlock(_, None) => { + // `try { ... }` is old and is only gated post-expansion here. gate!(&self, try_blocks, e.span, "`try` expression is experimental"); } ast::ExprKind::TryBlock(_, Some(_)) => { - gate!( - &self, - try_blocks_heterogeneous, - e.span, - "`try bikeshed` expression is experimental" - ); + // `try_blocks_heterogeneous` is new, and gated pre-expansion instead. } ast::ExprKind::Lit(token::Lit { kind: token::LitKind::Float | token::LitKind::Integer, @@ -421,6 +426,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } false } + ast::AssocItemKind::Const(box ast::ConstItem { + rhs_kind: ast::ConstItemRhsKind::TypeConst { .. }, + .. + }) => { + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(min_generic_const_args)] + gate!( + &self, + min_generic_const_args, + i.span, + "associated `type const` are unstable" + ); + false + } _ => false, }; if let ast::Defaultness::Default(_) = i.kind.defaultness() { @@ -440,6 +459,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { maybe_stage_features(sess, features, krate); check_incompatible_features(sess, features); + check_dependent_features(sess, features); check_new_solver_banned_features(sess, features); let mut visitor = PostExpansionVisitor { sess, features }; @@ -498,6 +518,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { half_open_range_patterns_in_slices, "half-open range patterns in slices are unstable" ); + gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental"); gate_all!(yeet_expr, "`do yeet` expression is experimental"); gate_all!(const_closures, "const closures are experimental"); gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); @@ -526,6 +547,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } } } + // `mgca_type_const_syntax` is part of `min_generic_const_args` so either + // or both are enabled we don't need to emit a feature error. + if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) { + for span in spans { + if visitor.features.min_generic_const_args() + || visitor.features.mgca_type_const_syntax() + || span.allows_unstable(sym::min_generic_const_args) + || span.allows_unstable(sym::mgca_type_const_syntax) + { + continue; + } + feature_err( + &visitor.sess, + sym::min_generic_const_args, + *span, + "`type const` syntax is experimental", + ) + .emit(); + } + } + gate_all!(global_registration, "global registration is experimental"); gate_all!(return_type_notation, "return type notation is experimental"); gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); @@ -648,6 +690,27 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } } +fn check_dependent_features(sess: &Session, features: &Features) { + for &(parent, children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + { + if children.iter().any(|f| !features.enabled(*f)) { + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = children + .iter() + .filter(|f| !features.enabled(**f)) + .map(|s| format!("`{}`", s.as_str())) + .intersperse(String::from(", ")) + .collect(); + sess.dcx().emit_err(errors::MissingDependentFeatures { parent_span, parent, missing }); + } + } +} + fn check_new_solver_banned_features(sess: &Session, features: &Features) { if !sess.opts.unstable_opts.next_solver.globally { return; diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 06795a6be81e..7793f786cefe 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -5,11 +5,10 @@ // tidy-alphabetical-start #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] // tidy-alphabetical-end pub mod ast_validation; mod errors; pub mod feature_gate; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e50e31c226fd..c8874ed99dca 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1961,7 +1961,8 @@ impl<'a> State<'a> { } fn print_lifetime(&mut self, lifetime: ast::Lifetime) { - self.print_name(lifetime.ident.name) + self.word(lifetime.ident.name.to_string()); + self.ann_post(lifetime.ident) } fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 68054b06e39f..c7f110a2e003 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -221,7 +221,7 @@ impl<'a> State<'a> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { self.print_item_const( @@ -229,7 +229,7 @@ impl<'a> State<'a> { None, generics, ty, - rhs.as_ref().map(|ct| ct.expr()), + rhs_kind.expr(), &item.vis, ast::Safety::Default, *defaultness, @@ -573,7 +573,7 @@ impl<'a> State<'a> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { self.print_item_const( @@ -581,7 +581,7 @@ impl<'a> State<'a> { None, generics, ty, - rhs.as_ref().map(|ct| ct.expr()), + rhs_kind.expr(), vis, ast::Safety::Default, *defaultness, diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 79193f394fe4..0a11a2da0dcf 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -8,9 +8,9 @@ edition = "2024" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +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_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl deleted file mode 100644 index 3e4c1a9dfad8..000000000000 --- a/compiler/rustc_attr_parsing/messages.ftl +++ /dev/null @@ -1,246 +0,0 @@ -attr_parsing_as_needed_compatibility = - linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds - -attr_parsing_bundle_needs_static = - linking modifier `bundle` is only compatible with `static` linking kind - -attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters - -attr_parsing_deprecated_item_suggestion = - suggestions on deprecated items are unstable - .help = add `#![feature(deprecated_suggestion)]` to the crate root - .note = see #94785 for more details - -attr_parsing_doc_alias_bad_char = - {$char_} character isn't allowed in {$attr_str} - -attr_parsing_doc_alias_empty = - {$attr_str} attribute cannot have empty value - -attr_parsing_doc_alias_malformed = - doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]` - -attr_parsing_doc_alias_start_end = - {$attr_str} cannot start or end with ' ' - -attr_parsing_doc_attr_not_crate_level = - `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute - -attr_parsing_doc_attribute_not_attribute = - nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]` - .help = only existing builtin attributes are allowed in core/std - -attr_parsing_doc_keyword_not_keyword = - nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]` - .help = only existing keywords are allowed in core/std - -attr_parsing_empty_confusables = - expected at least one confusable name - -attr_parsing_empty_link_name = - link name must not be empty - .label = empty link name - -attr_parsing_expected_single_version_literal = - expected single version literal - -attr_parsing_expected_version_literal = - expected a version literal - -attr_parsing_expects_feature_list = - `{$name}` expects a list of feature names - -attr_parsing_expects_features = - `{$name}` expects feature names - -attr_parsing_import_name_type_raw = - import name type can only be used with link kind `raw-dylib` - -attr_parsing_import_name_type_x86 = - import name type is only supported on x86 - -attr_parsing_incompatible_wasm_link = - `wasm_import_module` is incompatible with other arguments in `#[link]` attributes - -attr_parsing_incorrect_repr_format_align_one_arg = - incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - -attr_parsing_incorrect_repr_format_expect_literal_integer = - incorrect `repr(align)` attribute format: `align` expects a literal integer as argument - -attr_parsing_incorrect_repr_format_generic = - incorrect `repr({$repr_arg})` attribute format - .suggestion = use parentheses instead - -attr_parsing_incorrect_repr_format_packed_expect_integer = - incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument - -attr_parsing_incorrect_repr_format_packed_one_or_zero_arg = - incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - -attr_parsing_invalid_alignment_value = - invalid alignment value: {$error_part} - -attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute - .label = this is not an unsafe attribute - .suggestion = remove the `unsafe(...)` - .note = extraneous unsafe is not allowed in attributes - -attr_parsing_invalid_issue_string = - `issue` must be a non-zero numeric string or "none" - .must_not_be_zero = `issue` must not be "0", use "none" instead - .empty = cannot parse integer from empty string - .invalid_digit = invalid digit found in string - .pos_overflow = number too large to fit in target type - .neg_overflow = number too small to fit in target type - -attr_parsing_invalid_link_modifier = - invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - -attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} - .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign - .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - .label = {$descr}s are not allowed here - -attr_parsing_invalid_predicate = - invalid predicate `{$predicate}` - -attr_parsing_invalid_repr_align_need_arg = - invalid `repr(align)` attribute: `align` needs an argument - .suggestion = supply an argument here - -attr_parsing_invalid_repr_generic = - invalid `repr({$repr_arg})` attribute: {$error_part} - -attr_parsing_invalid_repr_hint_no_paren = - invalid representation hint: `{$name}` does not take a parenthesized argument list - -attr_parsing_invalid_repr_hint_no_value = - invalid representation hint: `{$name}` does not take a value - -attr_parsing_invalid_since = - 'since' must be a Rust version number, such as "1.31.0" - -attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target} - .help = `#[{$name}]` can {$only}be applied to {$applied} - .suggestion = remove the attribute - -attr_parsing_limit_invalid = - `limit` must be a non-negative integer - .label = {$error_str} -attr_parsing_link_arg_unstable = - link kind `link-arg` is unstable - -attr_parsing_link_cfg_unstable = - link cfg is unstable - -attr_parsing_link_framework_apple = - link kind `framework` is only supported on Apple targets - -attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}` - .note = the value may not exceed `u16::MAX` - -attr_parsing_link_requires_name = - `#[link]` attribute requires a `name = "string"` argument - .label = missing `name` argument - -attr_parsing_meta_bad_delim = wrong meta list delimiters -attr_parsing_meta_bad_delim_suggestion = the delimiters should be `(` and `)` - -attr_parsing_missing_feature = - missing 'feature' - -attr_parsing_missing_issue = - missing 'issue' - -attr_parsing_missing_note = - missing 'note' - -attr_parsing_missing_since = - missing 'since' - -attr_parsing_multiple_modifiers = - multiple `{$modifier}` modifiers in a single `modifiers` argument - -attr_parsing_multiple_stability_levels = - multiple stability levels - -attr_parsing_naked_functions_incompatible_attribute = - attribute incompatible with `#[unsafe(naked)]` - .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` - .naked_attribute = function marked with `#[unsafe(naked)]` here - -attr_parsing_non_ident_feature = - 'feature' is not an identifier - -attr_parsing_null_on_export = `export_name` may not contain null characters - -attr_parsing_null_on_link_section = `link_section` may not contain null characters - -attr_parsing_null_on_objc_class = `objc::class!` may not contain null characters - -attr_parsing_null_on_objc_selector = `objc::selector!` may not contain null characters - -attr_parsing_objc_class_expected_string_literal = `objc::class!` expected a string literal - -attr_parsing_objc_selector_expected_string_literal = `objc::selector!` expected a string literal - -attr_parsing_raw_dylib_elf_unstable = - link kind `raw-dylib` is unstable on ELF platforms - -attr_parsing_raw_dylib_no_nul = - link name must not contain NUL characters if link kind is `raw-dylib` - -attr_parsing_raw_dylib_only_windows = - link kind `raw-dylib` is only supported on Windows targets - -attr_parsing_repr_ident = - meta item in `repr` must be an identifier - -attr_parsing_rustc_allowed_unstable_pairing = - `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute - -attr_parsing_rustc_promotable_pairing = - `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute - -attr_parsing_rustc_scalable_vector_count_out_of_range = element count in `rustc_scalable_vector` is too large: `{$n}` - .note = the value may not exceed `u16::MAX` - -attr_parsing_soft_no_args = - `soft` should not have any arguments - -attr_parsing_stability_outside_std = stability attributes may not be used outside of the standard library - -attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes - .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - -attr_parsing_unknown_version_literal = - unknown version literal format, assuming it refers to a future version - -attr_parsing_unrecognized_repr_hint = - unrecognized representation hint - .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - .note = for more information, visit - -attr_parsing_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -attr_parsing_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -attr_parsing_unstable_cfg_target_compact = - compact `cfg(target(..))` is experimental and subject to change - -attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable - .help = if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]` - -attr_parsing_unsupported_instruction_set = target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]` - -attr_parsing_unsupported_literal_suggestion = - consider removing the prefix - -attr_parsing_unused_multiple = - multiple `{$name}` attributes - .suggestion = remove this attribute - .note = attribute also specified here - -attr_parsing_whole_archive_needs_static = - linking modifier `whole-archive` is only compatible with `static` linking kind diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 7323db06a8f1..4f1a8cd8b403 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -29,7 +29,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { pub(crate) struct UnstableFeatureBoundParser; impl CombineAttributeParser for UnstableFeatureBoundParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound]; + const PATH: &[rustc_span::Symbol] = &[sym::unstable_feature_bound]; type Item = (Symbol, Span); const CONVERT: ConvertFn = |items, _| AttributeKind::UnstableFeatureBound(items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -57,7 +57,7 @@ impl CombineAttributeParser for AllowConstFnUnstableParser { const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable]; type Item = Symbol; const CONVERT: ConvertFn = - |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span); + |items, first_span| AttributeKind::RustcAllowConstFnUnstable(items, first_span); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 3a540d80998d..d2f743f6c5d8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -3,14 +3,14 @@ use std::convert::identity; use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token}; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, PResult, msg}; use rustc_feature::{ AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template, }; use rustc_hir::attrs::CfgEntry; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, RustcVersion, Target}; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::{exp, parse_in}; use rustc_session::Session; use rustc_session::config::ExpectedValues; @@ -25,7 +25,7 @@ use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, ParsedDescription, }; -use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics}; +use crate::{AttributeParser, parse_version, session_diagnostics}; pub const CFG_TEMPLATE: AttributeTemplate = template!( List: &["predicate"], @@ -141,7 +141,7 @@ fn parse_cfg_entry_target( cx.sess(), sym::cfg_target_compact, meta_span, - fluent_generated::attr_parsing_unstable_cfg_target_compact, + msg!("compact `cfg(target(..))` is experimental and subject to change"), ) .emit(); } @@ -360,8 +360,10 @@ fn parse_cfg_attr_internal<'a>( ) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> { // Parse cfg predicate let pred_start = parser.token.span; - let meta = - MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?; + let meta = MetaItemOrLitParser::parse_single( + parser, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + )?; let pred_span = pred_start.with_hi(parser.token.span.hi()); let cfg_predicate = AttributeParser::parse_single_args( @@ -376,7 +378,7 @@ fn parse_cfg_attr_internal<'a>( CRATE_NODE_ID, Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &CFG_ATTR_TEMPLATE, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index ca844758daaa..b6cb5b4504ee 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -1,22 +1,35 @@ use rustc_ast::token::Token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrStyle, NodeId, token}; +use rustc_data_structures::fx::FxHashMap; use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; -use rustc_span::{ErrorGuaranteed, Span, sym}; +use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES; +use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use crate::parser::MetaItemOrLitParser; use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry}; +#[derive(Clone)] pub enum CfgSelectPredicate { Cfg(CfgEntry), Wildcard(Token), } +impl CfgSelectPredicate { + fn span(&self) -> Span { + match self { + CfgSelectPredicate::Cfg(cfg_entry) => cfg_entry.span(), + CfgSelectPredicate::Wildcard(token) => token.span, + } + } +} + #[derive(Default)] pub struct CfgSelectBranches { /// All the conditional branches. @@ -78,9 +91,11 @@ pub fn parse_cfg_select( } } } else { - let meta = - MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true }) - .map_err(|diag| diag.emit())?; + let meta = MetaItemOrLitParser::parse_single( + p, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + ) + .map_err(|diag| diag.emit())?; let cfg_span = meta.span(); let cfg = AttributeParser::parse_single_args( sess, @@ -95,7 +110,7 @@ pub fn parse_cfg_select( // Doesn't matter what the target actually is here. Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &AttributeTemplate::default(), @@ -113,5 +128,102 @@ pub fn parse_cfg_select( } } + if let Some(features) = features + && features.enabled(sym::cfg_select) + { + let it = branches + .reachable + .iter() + .map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone())) + .chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t))) + .chain( + branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)), + ); + + lint_unreachable(p, it, lint_node_id); + } + Ok(branches) } + +fn lint_unreachable( + p: &mut Parser<'_>, + predicates: impl Iterator, + lint_node_id: NodeId, +) { + // Symbols that have a known value. + let mut known = FxHashMap::::default(); + let mut wildcard_span = None; + let mut it = predicates; + + let branch_is_unreachable = |predicate: CfgSelectPredicate, wildcard_span| { + let span = predicate.span(); + p.psess.buffer_lint( + UNREACHABLE_CFG_SELECT_PREDICATES, + span, + lint_node_id, + BuiltinLintDiag::UnreachableCfg { span, wildcard_span }, + ); + }; + + for predicate in &mut it { + let CfgSelectPredicate::Cfg(ref cfg_entry) = predicate else { + wildcard_span = Some(predicate.span()); + break; + }; + + match cfg_entry { + CfgEntry::Bool(true, _) => { + wildcard_span = Some(predicate.span()); + break; + } + CfgEntry::Bool(false, _) => continue, + CfgEntry::NameValue { name, value, .. } => match value { + None => { + // `name` will be false in all subsequent branches. + let current = known.insert(*name, false); + + match current { + None => continue, + Some(false) => { + branch_is_unreachable(predicate, None); + break; + } + Some(true) => { + // this branch will be taken, so all subsequent branches are unreachable. + break; + } + } + } + Some(_) => { /* for now we don't bother solving these */ } + }, + CfgEntry::Not(inner, _) => match &**inner { + CfgEntry::NameValue { name, value: None, .. } => { + // `name` will be true in all subsequent branches. + let current = known.insert(*name, true); + + match current { + None => continue, + Some(true) => { + branch_is_unreachable(predicate, None); + break; + } + Some(false) => { + // this branch will be taken, so all subsequent branches are unreachable. + break; + } + } + } + _ => { /* for now we don't bother solving these */ } + }, + CfgEntry::All(_, _) | CfgEntry::Any(_, _) => { + /* for now we don't bother solving these */ + } + CfgEntry::Version(..) => { /* don't bother solving these */ } + } + } + + for predicate in it { + branch_is_unreachable(predicate, wildcard_span) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 063fa12d3896..485307622291 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -181,7 +181,7 @@ impl SingleAttributeParser for ObjcClassParser { cx.emit_err(NullOnObjcClass { span: nv.value_span }); return None; } - Some(AttributeKind::ObjcClass { classname, span: cx.attr_span }) + Some(AttributeKind::RustcObjcClass { classname, span: cx.attr_span }) } } @@ -213,7 +213,7 @@ impl SingleAttributeParser for ObjcSelectorParser { cx.emit_err(NullOnObjcSelector { span: nv.value_span }); return None; } - Some(AttributeKind::ObjcSelector { methname, span: cx.attr_span }) + Some(AttributeKind::RustcObjcSelector { methname, span: cx.attr_span }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 0b7ac989346a..1897fed1e250 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -43,7 +43,7 @@ impl AttributeParser for ConfusablesParser { return None; } - Some(AttributeKind::Confusables { + Some(AttributeKind::RustcConfusables { symbols: self.confusables, first_span: self.first_span.unwrap(), }) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index a367e699fcb9..bdfe7bfb8f1f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -274,3 +274,21 @@ impl NoArgsAttributeParser for NoBuiltinsParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } + +pub(crate) struct RustcPreserveUbChecksParser; + +impl NoArgsAttributeParser for RustcPreserveUbChecksParser { + const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; +} + +pub(crate) struct RustcNoImplicitBoundsParser; + +impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { + const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index e01377d247bb..c055c2936e95 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,4 +1,5 @@ use rustc_hir::attrs::{DeprecatedSince, Deprecation}; +use rustc_hir::{RustcVersion, VERSION_PLACEHOLDER}; use super::prelude::*; use super::util::parse_version; @@ -143,6 +144,8 @@ impl SingleAttributeParser for DeprecationParser { DeprecatedSince::Future } else if !is_rustc { DeprecatedSince::NonStandard(since) + } else if since.as_str() == VERSION_PLACEHOLDER { + DeprecatedSince::RustcVersion(RustcVersion::CURRENT) } else if let Some(version) = parse_version(since) { DeprecatedSince::RustcVersion(version) } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index a287c0c5a930..f8968639f98c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -70,6 +70,42 @@ fn check_attr_crate_level(cx: &mut AcceptContext<'_, '_, S>, span: Spa true } +// FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`. +fn expected_name_value( + cx: &mut AcceptContext<'_, '_, S>, + span: Span, + _name: Option, +) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::ExpectedNameValue, + span, + ); +} + +// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead. +fn expected_no_args(cx: &mut AcceptContext<'_, '_, S>, span: Span) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::ExpectedNoArgs, + span, + ); +} + +// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead. +// cx.expected_string_literal(span, _actual_literal); +fn expected_string_literal( + cx: &mut AcceptContext<'_, '_, S>, + span: Span, + _actual_literal: Option<&MetaItemLit>, +) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + span, + ); +} + fn parse_keyword_and_attribute( cx: &mut AcceptContext<'_, '_, S>, path: &OwnedPathParser, @@ -78,12 +114,12 @@ fn parse_keyword_and_attribute( attr_name: Symbol, ) { let Some(nv) = args.name_value() else { - cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); + expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym()); return; }; let Some(value) = nv.value_as_str() else { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); return; }; @@ -127,12 +163,21 @@ impl DocParser { match path.word_sym() { Some(sym::no_crate_inject) => { if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } - if self.attribute.no_crate_inject.is_some() { - cx.duplicate_key(path.span(), sym::no_crate_inject); + if let Some(used_span) = self.attribute.no_crate_inject { + let unused_span = path.span(); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + }, + unused_span, + ); return; } @@ -144,7 +189,14 @@ impl DocParser { } Some(sym::attr) => { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span, args); + // FIXME: remove this method once merged and uncomment the line below instead. + // cx.expected_list(cx.attr_span, args); + let span = cx.attr_span; + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + span, + ); return; }; @@ -246,7 +298,7 @@ impl DocParser { inline: DocInline, ) { if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } @@ -328,7 +380,14 @@ impl DocParser { match sub_item.args() { a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { let Some(name) = sub_item.path().word_sym() else { - cx.expected_identifier(sub_item.path().span()); + // FIXME: remove this method once merged and uncomment the line + // below instead. + // cx.expected_identifier(sub_item.path().span()); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + sub_item.path().span(), + ); continue; }; if let Ok(CfgEntry::NameValue { name, value, .. }) = @@ -391,7 +450,7 @@ impl DocParser { macro_rules! no_args { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } @@ -410,7 +469,7 @@ impl DocParser { macro_rules! no_args_and_not_crate_level { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } let span = path.span(); @@ -423,7 +482,7 @@ impl DocParser { macro_rules! no_args_and_crate_level { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } let span = path.span(); @@ -436,12 +495,12 @@ impl DocParser { macro_rules! string_arg_and_crate_level { ($ident: ident) => {{ let Some(nv) = args.name_value() else { - cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); + expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym()); return; }; let Some(s) = nv.value_as_str() else { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); return; }; @@ -512,7 +571,14 @@ impl DocParser { self.parse_single_test_doc_attr_item(cx, mip); } MetaItemOrLitParser::Lit(lit) => { - cx.unexpected_literal(lit.span); + // FIXME: remove this method once merged and uncomment the line + // below instead. + // cx.unexpected_literal(lit.span); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + lit.span, + ); } } } @@ -582,7 +648,7 @@ impl DocParser { let suggestions = cx.suggestions(); let span = cx.attr_span; cx.emit_lint( - rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT, + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None }, span, ); @@ -595,14 +661,14 @@ impl DocParser { self.parse_single_doc_attr_item(cx, mip); } MetaItemOrLitParser::Lit(lit) => { - cx.expected_name_value(lit.span, None); + expected_name_value(cx, lit.span, None); } } } } ArgParser::NameValue(nv) => { if nv.value_as_str().is_none() { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); } else { unreachable!( "Should have been handled at the same time as sugar-syntaxed doc comments" diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index 0a7d95f31799..9f97af48afa0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -16,6 +16,6 @@ impl SingleAttributeParser for DummyParser { const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser) -> Option { - Some(AttributeKind::Dummy) + Some(AttributeKind::RustcDummy) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index f6aab9ea0ee2..767200bfa9bf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -10,7 +10,7 @@ use super::prelude::*; pub(crate) struct InlineParser; impl SingleAttributeParser for InlineParser { - const PATH: &'static [Symbol] = &[sym::inline]; + const PATH: &[Symbol] = &[sym::inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -67,7 +67,7 @@ impl SingleAttributeParser for InlineParser { pub(crate) struct RustcForceInlineParser; impl SingleAttributeParser for RustcForceInlineParser { - const PATH: &'static [Symbol] = &[sym::rustc_force_inline]; + const PATH: &[Symbol] = &[sym::rustc_force_inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index a636b449ca56..21c05611ce29 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,3 +1,4 @@ +use rustc_errors::msg; use rustc_feature::Features; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_hir::attrs::*; @@ -10,12 +11,11 @@ use rustc_target::spec::{Arch, BinaryFormat}; use super::prelude::*; use super::util::parse_single_integer; use crate::attributes::cfg::parse_cfg_entry; -use crate::fluent_generated; use crate::session_diagnostics::{ - AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86, - IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange, - LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, - WholeArchiveNeedsStatic, + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, + ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, + LinkFrameworkApple, LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, + NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, WholeArchiveNeedsStatic, }; pub(crate) struct LinkNameParser; @@ -165,6 +165,14 @@ impl CombineAttributeParser for LinkParser { cx.emit_err(BundleNeedsStatic { span }); } + (sym::export_symbols, Some(NativeLibKind::Static { export_symbols, .. })) => { + assign_modifier(export_symbols) + } + + (sym::export_symbols, _) => { + cx.emit_err(ExportSymbolsNeedsStatic { span }); + } + (sym::verbatim, _) => assign_modifier(&mut verbatim), ( @@ -190,6 +198,7 @@ impl CombineAttributeParser for LinkParser { span, &[ sym::bundle, + sym::export_symbols, sym::verbatim, sym::whole_dash_archive, sym::as_dash_needed, @@ -285,7 +294,9 @@ impl LinkParser { }; let link_kind = match link_kind { - kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None }, + kw::Static => { + NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None } + } sym::dylib => NativeLibKind::Dylib { as_needed: None }, sym::framework => { if !sess.target.is_like_darwin { @@ -305,7 +316,7 @@ impl LinkParser { sess, sym::raw_dylib_elf, nv.value_span, - fluent_generated::attr_parsing_raw_dylib_elf_unstable, + msg!("link kind `raw-dylib` is unstable on ELF platforms"), ) .emit(); } else { @@ -320,7 +331,7 @@ impl LinkParser { sess, sym::link_arg_attribute, nv.value_span, - fluent_generated::attr_parsing_link_arg_unstable, + msg!("link kind `link-arg` is unstable"), ) .emit(); } @@ -385,13 +396,7 @@ impl LinkParser { return true; }; if !features.link_cfg() { - feature_err( - sess, - sym::link_cfg, - item.span(), - fluent_generated::attr_parsing_link_cfg_unstable, - ) - .emit(); + feature_err(sess, sym::link_cfg, item.span(), msg!("link cfg is unstable")).emit(); } *cfg = parse_cfg_entry(cx, link_cfg).ok(); true @@ -529,7 +534,7 @@ impl NoArgsAttributeParser for StdInternalSymbolParser { Allow(Target::Static), Allow(Target::ForeignStatic), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStdInternalSymbol; } pub(crate) struct LinkOrdinalParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 8ca5f0f7228e..60e83a6083ed 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -11,7 +11,7 @@ impl NoArgsAttributeParser for AsPtrParser { Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAsPtr; } pub(crate) struct PubTransparentParser; @@ -23,7 +23,7 @@ impl NoArgsAttributeParser for PubTransparentParser { Allow(Target::Enum), Allow(Target::Union), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent; } pub(crate) struct PassByValueParser; @@ -35,7 +35,7 @@ impl NoArgsAttributeParser for PassByValueParser { Allow(Target::Enum), Allow(Target::TyAlias), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassByValue; } pub(crate) struct RustcShouldNotBeCalledOnConstItems; diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index d37915b1b80b..00d40687fc85 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -206,3 +206,12 @@ impl SingleAttributeParser for CollapseDebugInfoParser { Some(AttributeKind::CollapseDebugInfo(info)) } } + +pub(crate) struct RustcProcMacroDeclsParser; + +impl NoArgsAttributeParser for RustcProcMacroDeclsParser { + const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index 3674aa7124ab..f9ace7e25d1b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -1,3 +1,6 @@ +use rustc_hir::lints::AttributeLintKind; +use rustc_session::lint::builtin::AMBIGUOUS_DERIVE_HELPERS; + use super::prelude::*; const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets = @@ -126,6 +129,13 @@ fn parse_derive_like( cx.expected_identifier(ident.span); return None; } + if rustc_feature::is_builtin_attr_name(ident.name) { + cx.emit_lint( + AMBIGUOUS_DERIVE_HELPERS, + AttributeLintKind::AmbiguousDeriveHelpers, + ident.span, + ); + } attributes.push(ident.name); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 34d4957edc70..fb0b8df65284 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -272,7 +272,7 @@ fn parse_alignment(node: &LitKind) -> Result { pub(crate) struct AlignParser(Option<(Align, Span)>); impl AlignParser { - const PATH: &'static [Symbol] = &[sym::rustc_align]; + const PATH: &[Symbol] = &[sym::rustc_align]; const TEMPLATE: AttributeTemplate = template!(List: &[""]); fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { @@ -329,7 +329,7 @@ impl AttributeParser for AlignParser { pub(crate) struct AlignStaticParser(AlignParser); impl AlignStaticParser { - const PATH: &'static [Symbol] = &[sym::rustc_align_static]; + const PATH: &[Symbol] = &[sym::rustc_align_static]; const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE; fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 53120dece916..71a8fb0dd47d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -7,36 +7,36 @@ use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; use crate::context::Stage; use crate::target_checking::AllowedTargets; -pub(crate) struct RustcDumpUserArgs; +pub(crate) struct RustcDumpUserArgsParser; -impl NoArgsAttributeParser for RustcDumpUserArgs { +impl NoArgsAttributeParser for RustcDumpUserArgsParser { const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; } -pub(crate) struct RustcDumpDefParents; +pub(crate) struct RustcDumpDefParentsParser; -impl NoArgsAttributeParser for RustcDumpDefParents { +impl NoArgsAttributeParser for RustcDumpDefParentsParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; } -pub(crate) struct RustcDumpItemBounds; +pub(crate) struct RustcDumpItemBoundsParser; -impl NoArgsAttributeParser for RustcDumpItemBounds { +impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } -pub(crate) struct RustcDumpPredicates; +pub(crate) struct RustcDumpPredicatesParser; -impl NoArgsAttributeParser for RustcDumpPredicates { +impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -49,9 +49,9 @@ impl NoArgsAttributeParser for RustcDumpPredicates { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates; } -pub(crate) struct RustcDumpVtable; +pub(crate) struct RustcDumpVtableParser; -impl NoArgsAttributeParser for RustcDumpVtable { +impl NoArgsAttributeParser for RustcDumpVtableParser { const PATH: &[Symbol] = &[sym::rustc_dump_vtable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 365cd55bdc38..2c94a708a90c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,14 +1,25 @@ +use std::path::PathBuf; + use rustc_ast::{LitIntType, LitKind, MetaItemLit}; +use rustc_hir::LangItem; +use rustc_hir::attrs::{ + BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior, + DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType, + RustcMirKind, +}; use rustc_session::errors; +use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; -use crate::session_diagnostics::RustcScalableVectorCountOutOfRange; +use crate::session_diagnostics::{ + AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem, +}; pub(crate) struct RustcMainParser; impl NoArgsAttributeParser for RustcMainParser { - const PATH: &'static [Symbol] = &[sym::rustc_main]; + const PATH: &[Symbol] = &[sym::rustc_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain; @@ -93,7 +104,7 @@ impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser { pub(crate) struct RustcLayoutScalarValidRangeStartParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeStartParser { - const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; + const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -108,7 +119,7 @@ impl SingleAttributeParser for RustcLayoutScalarValidRangeStartPars pub(crate) struct RustcLayoutScalarValidRangeEndParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeEndParser { - const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; + const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -197,6 +208,325 @@ impl NoArgsAttributeParser for RustcLintOptTyParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; } +fn parse_cgu_fields( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + accepts_kind: bool, +) -> Option<(Symbol, Symbol, Option)> { + let Some(args) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let mut cfg = None::<(Symbol, Span)>; + let mut module = None::<(Symbol, Span)>; + let mut kind = None::<(Symbol, Span)>; + + for arg in args.mixed() { + let Some(arg) = arg.meta_item() else { + cx.expected_name_value(args.span, None); + continue; + }; + + let res = match arg.ident().map(|i| i.name) { + Some(sym::cfg) => &mut cfg, + Some(sym::module) => &mut module, + Some(sym::kind) if accepts_kind => &mut kind, + _ => { + cx.expected_specific_argument( + arg.path().span(), + if accepts_kind { + &[sym::cfg, sym::module, sym::kind] + } else { + &[sym::cfg, sym::module] + }, + ); + continue; + } + }; + + let Some(i) = arg.args().name_value() else { + cx.expected_name_value(arg.span(), None); + continue; + }; + + let Some(str) = i.value_as_str() else { + cx.expected_string_literal(i.value_span, Some(i.value_as_lit())); + continue; + }; + + if res.is_some() { + cx.duplicate_key(arg.span(), arg.ident().unwrap().name); + continue; + } + + *res = Some((str, i.value_span)); + } + + let Some((cfg, _)) = cfg else { + cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::cfg }); + return None; + }; + let Some((module, _)) = module else { + cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::module }); + return None; + }; + let kind = if let Some((kind, span)) = kind { + Some(match kind { + sym::no => CguKind::No, + sym::pre_dash_lto => CguKind::PreDashLto, + sym::post_dash_lto => CguKind::PostDashLto, + sym::any => CguKind::Any, + _ => { + cx.expected_specific_argument_strings( + span, + &[sym::no, sym::pre_dash_lto, sym::post_dash_lto, sym::any], + ); + return None; + } + }) + } else { + // return None so that an unwrap for the attributes that need it is ok. + if accepts_kind { + cx.emit_err(CguFieldsMissing { + span: args.span, + name: &cx.attr_path, + field: sym::kind, + }); + return None; + }; + + None + }; + + Some((cfg, module, kind)) +} + +#[derive(Default)] +pub(crate) struct RustcCguTestAttributeParser { + items: ThinVec<(Span, CguFields)>, +} + +impl AttributeParser for RustcCguTestAttributeParser { + const ATTRIBUTES: AcceptMapping = &[ + ( + &[sym::rustc_partition_reused], + template!(List: &[r#"cfg = "...", module = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { + (cx.attr_span, CguFields::PartitionReused { cfg, module }) + })); + }, + ), + ( + &[sym::rustc_partition_codegened], + template!(List: &[r#"cfg = "...", module = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { + (cx.attr_span, CguFields::PartitionCodegened { cfg, module }) + })); + }, + ), + ( + &[sym::rustc_expected_cgu_reuse], + template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| { + // unwrap ok because if not given, we return None in `parse_cgu_fields`. + (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() }) + })); + }, + ), + ]; + + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + Some(AttributeKind::RustcCguTestAttr(self.items)) + } +} + +pub(crate) struct RustcDeprecatedSafe2024Parser; + +impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { + const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(args) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let Some(single) = args.single() else { + cx.expected_single_argument(args.span); + return None; + }; + + let Some(arg) = single.meta_item() else { + cx.expected_name_value(args.span, None); + return None; + }; + + let Some(args) = arg.word_is(sym::audit_that) else { + cx.expected_specific_argument(arg.span(), &[sym::audit_that]); + return None; + }; + + let Some(nv) = args.name_value() else { + cx.expected_name_value(arg.span(), Some(sym::audit_that)); + return None; + }; + + let Some(suggestion) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion }) + } +} + +pub(crate) struct RustcConversionSuggestionParser; + +impl NoArgsAttributeParser for RustcConversionSuggestionParser { + const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion; +} + +pub(crate) struct RustcCaptureAnalysisParser; + +impl NoArgsAttributeParser for RustcCaptureAnalysisParser { + const PATH: &[Symbol] = &[sym::rustc_capture_analysis]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; +} + +pub(crate) struct RustcNeverTypeOptionsParser; + +impl SingleAttributeParser for RustcNeverTypeOptionsParser { + const PATH: &[Symbol] = &[sym::rustc_never_type_options]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(List: &[ + r#"fallback = "unit", "never", "no""#, + r#"diverging_block_default = "unit", "never""#, + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let mut fallback = None::; + let mut diverging_block_default = None::; + + for arg in list.mixed() { + let Some(meta) = arg.meta_item() else { + cx.expected_name_value(arg.span(), None); + continue; + }; + + let res = match meta.ident().map(|i| i.name) { + Some(sym::fallback) => &mut fallback, + Some(sym::diverging_block_default) => &mut diverging_block_default, + _ => { + cx.expected_specific_argument( + meta.path().span(), + &[sym::fallback, sym::diverging_block_default], + ); + continue; + } + }; + + let Some(nv) = meta.args().name_value() else { + cx.expected_name_value(meta.span(), None); + continue; + }; + + let Some(field) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + continue; + }; + + if res.is_some() { + cx.duplicate_key(meta.span(), meta.ident().unwrap().name); + continue; + } + + *res = Some(Ident { name: field, span: nv.value_span }); + } + + let fallback = match fallback { + None => None, + Some(Ident { name: sym::unit, .. }) => Some(DivergingFallbackBehavior::ToUnit), + Some(Ident { name: sym::never, .. }) => Some(DivergingFallbackBehavior::ToNever), + Some(Ident { name: sym::no, .. }) => Some(DivergingFallbackBehavior::NoFallback), + Some(Ident { span, .. }) => { + cx.expected_specific_argument_strings(span, &[sym::unit, sym::never, sym::no]); + return None; + } + }; + + let diverging_block_default = match diverging_block_default { + None => None, + Some(Ident { name: sym::unit, .. }) => Some(DivergingBlockBehavior::Unit), + Some(Ident { name: sym::never, .. }) => Some(DivergingBlockBehavior::Never), + Some(Ident { span, .. }) => { + cx.expected_specific_argument_strings(span, &[sym::unit, sym::no]); + return None; + } + }; + + Some(AttributeKind::RustcNeverTypeOptions { fallback, diverging_block_default }) + } +} + +pub(crate) struct RustcTrivialFieldReadsParser; + +impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { + const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; +} + +pub(crate) struct RustcNoMirInlineParser; + +impl NoArgsAttributeParser for RustcNoMirInlineParser { + const PATH: &[Symbol] = &[sym::rustc_no_mir_inline]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { @@ -212,6 +542,22 @@ impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability; } +pub(crate) struct RustcRegionsParser; + +impl NoArgsAttributeParser for RustcRegionsParser { + const PATH: &[Symbol] = &[sym::rustc_regions]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions; +} + pub(crate) struct RustcLintUntrackedQueryInformationParser; impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { @@ -230,21 +576,11 @@ impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationPa pub(crate) struct RustcObjectLifetimeDefaultParser; -impl SingleAttributeParser for RustcObjectLifetimeDefaultParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; +impl NoArgsAttributeParser for RustcObjectLifetimeDefaultParser { + const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - return None; - } - - Some(AttributeKind::RustcObjectLifetimeDefault) - } + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcObjectLifetimeDefault; } pub(crate) struct RustcSimdMonomorphizeLaneLimitParser; @@ -268,7 +604,7 @@ impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser pub(crate) struct RustcScalableVectorParser; impl SingleAttributeParser for RustcScalableVectorParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector]; + const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -291,6 +627,32 @@ impl SingleAttributeParser for RustcScalableVectorParser { } } +pub(crate) struct LangParser; + +impl SingleAttributeParser for LangParser { + const PATH: &[Symbol] = &[sym::lang]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + let Some(lang_item) = LangItem::from_name(name) else { + cx.emit_err(UnknownLangItem { span: cx.attr_span, name }); + return None; + }; + Some(AttributeKind::Lang(lang_item, cx.attr_span)) + } +} + pub(crate) struct RustcHasIncoherentInherentImplsParser; impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser { @@ -306,6 +668,23 @@ impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParse const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls; } +pub(crate) struct PanicHandlerParser; + +impl NoArgsAttributeParser for PanicHandlerParser { + const PATH: &[Symbol] = &[sym::panic_handler]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes` + const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::Lang(LangItem::PanicImpl, span); +} + +pub(crate) struct RustcHiddenTypeOfOpaquesParser; + +impl NoArgsAttributeParser for RustcHiddenTypeOfOpaquesParser { + const PATH: &[Symbol] = &[sym::rustc_hidden_type_of_opaques]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHiddenTypeOfOpaques; +} pub(crate) struct RustcNounwindParser; impl NoArgsAttributeParser for RustcNounwindParser { @@ -329,3 +708,590 @@ impl NoArgsAttributeParser for RustcOffloadKernelParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel; } + +pub(crate) struct RustcLayoutParser; + +impl CombineAttributeParser for RustcLayoutParser { + const PATH: &[Symbol] = &[sym::rustc_layout]; + + type Item = RustcLayoutType; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcLayout(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::TyAlias), + ]); + + const TEMPLATE: AttributeTemplate = + template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]); + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let ArgParser::List(items) = args else { + cx.expected_list(cx.attr_span, args); + return vec![]; + }; + + let mut result = Vec::new(); + for item in items.mixed() { + let Some(arg) = item.meta_item() else { + cx.unexpected_literal(item.span()); + continue; + }; + let Some(ident) = arg.ident() else { + cx.expected_identifier(arg.span()); + return vec![]; + }; + let ty = match ident.name { + sym::abi => RustcLayoutType::Abi, + sym::align => RustcLayoutType::Align, + sym::size => RustcLayoutType::Size, + sym::homogeneous_aggregate => RustcLayoutType::HomogenousAggregate, + sym::debug => RustcLayoutType::Debug, + _ => { + cx.expected_specific_argument( + ident.span, + &[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug], + ); + continue; + } + }; + result.push(ty); + } + result + } +} + +pub(crate) struct RustcMirParser; + +impl CombineAttributeParser for RustcMirParser { + const PATH: &[Symbol] = &[sym::rustc_mir]; + + type Item = RustcMirKind; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcMir(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + ]); + + const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return ThinVec::new(); + }; + + list.mixed() + .filter_map(|arg| arg.meta_item()) + .filter_map(|mi| { + if let Some(ident) = mi.ident() { + match ident.name { + sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit), + sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit), + sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness), + sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow), + sym::borrowck_graphviz_postflow => { + let Some(nv) = mi.args().name_value() else { + cx.expected_name_value( + mi.span(), + Some(sym::borrowck_graphviz_postflow), + ); + return None; + }; + let Some(path) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, None); + return None; + }; + let path = PathBuf::from(path.to_string()); + if path.file_name().is_some() { + Some(RustcMirKind::BorrowckGraphvizPostflow { path }) + } else { + cx.expected_filename_literal(nv.value_span); + None + } + } + sym::borrowck_graphviz_format => { + let Some(nv) = mi.args().name_value() else { + cx.expected_name_value( + mi.span(), + Some(sym::borrowck_graphviz_format), + ); + return None; + }; + let Some(format) = nv.value_as_ident() else { + cx.expected_identifier(nv.value_span); + return None; + }; + match format.name { + sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat { + format: BorrowckGraphvizFormatKind::TwoPhase, + }), + _ => { + cx.expected_specific_argument(format.span, &[sym::two_phase]); + None + } + } + } + _ => None, + } + } else { + None + } + }) + .collect() + } +} + +pub(crate) struct RustcNonConstTraitMethodParser; + +impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { + const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::Trait { body: false })), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod; +} + +pub(crate) struct RustcCleanParser; + +impl CombineAttributeParser for RustcCleanParser { + const PATH: &[Symbol] = &[sym::rustc_clean]; + + type Item = RustcCleanAttribute; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcClean(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = + template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + let mut except = None; + let mut loaded_from_disk = None; + let mut cfg = None; + + for item in list.mixed() { + let Some((value, name)) = + item.meta_item().and_then(|m| Option::zip(m.args().name_value(), m.ident())) + else { + cx.expected_name_value(item.span(), None); + continue; + }; + let value_span = value.value_span; + let Some(value) = value.value_as_str() else { + cx.expected_string_literal(value_span, None); + continue; + }; + match name.name { + sym::cfg if cfg.is_some() => { + cx.duplicate_key(item.span(), sym::cfg); + } + + sym::cfg => { + cfg = Some(value); + } + sym::except if except.is_some() => { + cx.duplicate_key(item.span(), sym::except); + } + sym::except => { + let entries = + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); + except = Some(RustcCleanQueries { entries, span: value_span }); + } + sym::loaded_from_disk if loaded_from_disk.is_some() => { + cx.duplicate_key(item.span(), sym::loaded_from_disk); + } + sym::loaded_from_disk => { + let entries = + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); + loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span }); + } + _ => { + cx.expected_specific_argument( + name.span, + &[sym::cfg, sym::except, sym::loaded_from_disk], + ); + } + } + } + let Some(cfg) = cfg else { + cx.expected_specific_argument(list.span, &[sym::cfg]); + return None; + }; + + Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk }) + } +} + +pub(crate) struct RustcIfThisChangedParser; + +impl SingleAttributeParser for RustcIfThisChangedParser { + const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; + + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } + match args { + ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)), + ArgParser::List(list) => { + let Some(item) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { + cx.expected_identifier(item.span()); + return None; + }; + Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name))) + } + ArgParser::NameValue(_) => { + cx.expected_list_or_no_args(cx.inner_span); + None + } + } + } +} + +pub(crate) struct RustcThenThisWouldNeedParser; + +impl CombineAttributeParser for RustcThenThisWouldNeedParser { + const PATH: &[Symbol] = &[sym::rustc_then_this_would_need]; + type Item = Ident; + + const CONVERT: ConvertFn = + |items, span| AttributeKind::RustcThenThisWouldNeed(span, items); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } + let Some(item) = args.list().and_then(|l| l.single()) else { + cx.expected_single_argument(cx.inner_span); + return None; + }; + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { + cx.expected_identifier(item.span()); + return None; + }; + Some(ident) + } +} + +pub(crate) struct RustcInsignificantDtorParser; + +impl NoArgsAttributeParser for RustcInsignificantDtorParser { + const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::ForeignTy), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor; +} + +pub(crate) struct RustcEffectiveVisibilityParser; + +impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { + const PATH: &[Symbol] = &[sym::rustc_effective_visibility]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Use), + Allow(Target::Static), + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Mod), + Allow(Target::ForeignMod), + Allow(Target::TyAlias), + Allow(Target::Enum), + Allow(Target::Variant), + Allow(Target::Struct), + Allow(Target::Field), + Allow(Target::Union), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::AssocConst), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::AssocTy), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), + Allow(Target::MacroDef), + Allow(Target::PatField), + Allow(Target::Crate), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; +} + +pub(crate) struct RustcDiagnosticItemParser; + +impl SingleAttributeParser for RustcDiagnosticItemParser { + const PATH: &[Symbol] = &[sym::rustc_diagnostic_item]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Trait), + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::MacroDef), + Allow(Target::TyAlias), + Allow(Target::AssocTy), + Allow(Target::AssocConst), + Allow(Target::Fn), + Allow(Target::Const), + Allow(Target::Mod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Crate), + ]); + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(value) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + Some(AttributeKind::RustcDiagnosticItem(value)) + } +} + +pub(crate) struct RustcSymbolName; + +impl SingleAttributeParser for RustcSymbolName { + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::Impl { of_trait: false }), + ]); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const PATH: &[Symbol] = &[sym::rustc_symbol_name]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(Word); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + Some(AttributeKind::RustcSymbolName(cx.attr_span)) + } +} + +pub(crate) struct RustcDefPath; + +impl SingleAttributeParser for RustcDefPath { + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::Impl { of_trait: false }), + ]); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const PATH: &[Symbol] = &[sym::rustc_def_path]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(Word); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + Some(AttributeKind::RustcDefPath(cx.attr_span)) + } +} + +pub(crate) struct RustcIntrinsicParser; + +impl NoArgsAttributeParser for RustcIntrinsicParser { + const PATH: &[Symbol] = &[sym::rustc_intrinsic]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; +} + +pub(crate) struct RustcIntrinsicConstStableIndirectParser; + +impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser { + const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; +} + +pub(crate) struct RustcStrictCoherenceParser; + +impl NoArgsAttributeParser for RustcStrictCoherenceParser { + const PATH: &[Symbol] = &[sym::rustc_strict_coherence]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Trait), + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::ForeignTy), + ]); + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence; +} + +pub(crate) struct RustcReservationImplParser; + +impl SingleAttributeParser for RustcReservationImplParser { + const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); + + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(args.span().unwrap_or(cx.attr_span), None); + return None; + }; + + let Some(value_str) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::RustcReservationImpl(cx.attr_span, value_str)) + } +} + +pub(crate) struct PreludeImportParser; + +impl NoArgsAttributeParser for PreludeImportParser { + const PATH: &[Symbol] = &[sym::prelude_import]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 8d27e2e276dd..a2be2d42b3e1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -173,7 +173,7 @@ impl AttributeParser for BodyStabilityParser { fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { let (stability, span) = self.stability?; - Some(AttributeKind::BodyStability { stability, span }) + Some(AttributeKind::RustcBodyStability { stability, span }) } } @@ -185,7 +185,7 @@ impl NoArgsAttributeParser for ConstStabilityIndirectParser { Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), ]); - const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect; + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStabilityIndirect; } #[derive(Default)] @@ -244,7 +244,20 @@ impl AttributeParser for ConstStabilityParser { this.promotable = true; }), ]; - const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Use), // FIXME I don't think this does anything? + Allow(Target::Const), + Allow(Target::AssocConst), + Allow(Target::Trait), + Allow(Target::Static), + Allow(Target::Crate), + ]); fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option { if self.promotable { @@ -258,7 +271,7 @@ impl AttributeParser for ConstStabilityParser { let (stability, span) = self.stability?; - Some(AttributeKind::ConstStability { stability, span }) + Some(AttributeKind::RustcConstStability { stability, span }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index ec7cdd3624dc..ac1d360c6280 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -1,3 +1,4 @@ +use rustc_hir::attrs::RustcAbiAttrKind; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use super::prelude::*; @@ -113,3 +114,179 @@ impl NoArgsAttributeParser for RustcVarianceOfOpaquesParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVarianceOfOpaques; } + +pub(crate) struct ReexportTestHarnessMainParser; + +impl SingleAttributeParser for ReexportTestHarnessMainParser { + const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value( + args.span().unwrap_or(cx.inner_span), + Some(sym::reexport_test_harness_main), + ); + return None; + }; + + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::ReexportTestHarnessMain(name)) + } +} + +pub(crate) struct RustcAbiParser; + +impl SingleAttributeParser for RustcAbiParser { + const PATH: &[Symbol] = &[sym::rustc_abi]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::TyAlias), + Allow(Target::Fn), + Allow(Target::ForeignFn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(args) = args.list() else { + cx.expected_specific_argument_and_list(cx.attr_span, &[sym::assert_eq, sym::debug]); + return None; + }; + + let Some(arg) = args.single() else { + cx.expected_single_argument(cx.attr_span); + return None; + }; + + let fail_incorrect_argument = + |span| cx.expected_specific_argument(span, &[sym::assert_eq, sym::debug]); + + let Some(arg) = arg.meta_item() else { + fail_incorrect_argument(args.span); + return None; + }; + + let kind: RustcAbiAttrKind = match arg.path().word_sym() { + Some(sym::assert_eq) => RustcAbiAttrKind::AssertEq, + Some(sym::debug) => RustcAbiAttrKind::Debug, + None | Some(_) => { + fail_incorrect_argument(arg.span()); + return None; + } + }; + + Some(AttributeKind::RustcAbi { attr_span: cx.attr_span, kind }) + } +} + +pub(crate) struct RustcDelayedBugFromInsideQueryParser; + +impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser { + const PATH: &[Symbol] = &[sym::rustc_delayed_bug_from_inside_query]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; +} + +pub(crate) struct RustcEvaluateWhereClausesParser; + +impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { + const PATH: &[Symbol] = &[sym::rustc_evaluate_where_clauses]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses; +} + +pub(crate) struct RustcOutlivesParser; + +impl NoArgsAttributeParser for RustcOutlivesParser { + const PATH: &[Symbol] = &[sym::rustc_outlives]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::TyAlias), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOutlives; +} + +pub(crate) struct TestRunnerParser; + +impl SingleAttributeParser for TestRunnerParser { + const PATH: &[Symbol] = &[sym::test_runner]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const TEMPLATE: AttributeTemplate = template!(List: &["path"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let Some(single) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + + let Some(meta) = single.meta_item() else { + cx.unexpected_literal(single.span()); + return None; + }; + + Some(AttributeKind::TestRunner(meta.path().0.clone())) + } +} + +pub(crate) struct RustcTestMarkerParser; + +impl SingleAttributeParser for RustcTestMarkerParser { + const PATH: &[Symbol] = &[sym::rustc_test_marker]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Static), + ]); + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "test_path"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(name_value) = args.name_value() else { + cx.expected_name_value(cx.attr_span, Some(sym::rustc_test_marker)); + return None; + }; + + let Some(value_str) = name_value.value_as_str() else { + cx.expected_string_literal(name_value.value_span, None); + return None; + }; + + if value_str.as_str().trim().is_empty() { + cx.expected_non_empty_string_literal(name_value.value_span); + return None; + } + + Some(AttributeKind::RustcTestMarker(value_str)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index c0db5b4d442a..ceaa43948d67 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -50,7 +50,11 @@ impl SingleAttributeParser for SkipDuringMethodDispatchParser { cx.duplicate_key(arg.span(), key); } } - Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span }) + Some(AttributeKind::RustcSkipDuringMethodDispatch { + array, + boxed_slice, + span: cx.attr_span, + }) } } @@ -59,16 +63,7 @@ impl NoArgsAttributeParser for ParenSugarParser { const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar; -} - -pub(crate) struct TypeConstParser; -impl NoArgsAttributeParser for TypeConstParser { - const PATH: &[Symbol] = &[sym::type_const]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar; } // Markers @@ -91,7 +86,7 @@ impl NoArgsAttributeParser for DenyExplicitImplParser { const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl; } pub(crate) struct DynIncompatibleTraitParser; @@ -99,7 +94,7 @@ impl NoArgsAttributeParser for DynIncompatibleTraitParser { const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait; } // Specialization @@ -109,7 +104,7 @@ impl NoArgsAttributeParser for SpecializationTraitParser { const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait; } pub(crate) struct UnsafeSpecializationMarkerParser; @@ -117,7 +112,7 @@ impl NoArgsAttributeParser for UnsafeSpecializationMarkerParser { const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcUnsafeSpecializationMarker; } // Coherence @@ -127,7 +122,7 @@ impl NoArgsAttributeParser for CoinductiveParser { const PATH: &[Symbol] = &[sym::rustc_coinductive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive; } pub(crate) struct AllowIncoherentImplParser; @@ -136,7 +131,7 @@ impl NoArgsAttributeParser for AllowIncoherentImplParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl; } pub(crate) struct FundamentalParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 5b8b3cd151eb..7fa4487b7c69 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -32,6 +32,6 @@ impl SingleAttributeParser for TransparencyParser { } None => None, } - .map(AttributeKind::MacroTransparency) + .map(AttributeKind::RustcMacroTransparency) } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 20bdfa45a013..17a92641f10f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; +use std::collections::btree_map::Entry; use std::ops::{Deref, DerefMut}; use std::sync::LazyLock; @@ -10,93 +11,48 @@ use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, HirId}; +use rustc_parse::parser::Recovery; use rustc_session::Session; use rustc_session::lint::{Lint, LintId}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use crate::AttributeParser; -use crate::attributes::allow_unstable::{ - AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, -}; -use crate::attributes::body::CoroutineParser; -use crate::attributes::cfi_encoding::CfiEncodingParser; -use crate::attributes::codegen_attrs::{ - ColdParser, CoverageParser, EiiForeignItemParser, ExportNameParser, ForceTargetFeatureParser, - NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, - PatchableFunctionEntryParser, RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, - TargetFeatureParser, ThreadLocalParser, TrackCallerParser, UsedParser, -}; -use crate::attributes::confusables::ConfusablesParser; -use crate::attributes::crate_level::{ - CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, - NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser, - PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, - RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, -}; -use crate::attributes::debugger::DebuggerViualizerParser; -use crate::attributes::deprecation::DeprecationParser; -use crate::attributes::do_not_recommend::DoNotRecommendParser; -use crate::attributes::doc::DocParser; -use crate::attributes::dummy::DummyParser; -use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; -use crate::attributes::instruction_set::InstructionSetParser; -use crate::attributes::link_attrs::{ - CompilerBuiltinsParser, ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, - LinkOrdinalParser, LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, - StdInternalSymbolParser, -}; -use crate::attributes::lint_helpers::{ - AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, - RustcShouldNotBeCalledOnConstItems, -}; -use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{ - AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser, - MacroUseParser, -}; -use crate::attributes::must_not_suspend::MustNotSuspendParser; -use crate::attributes::must_use::MustUseParser; -use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; -use crate::attributes::no_link::NoLinkParser; -use crate::attributes::non_exhaustive::NonExhaustiveParser; +// Glob imports to avoid big, bitrotty import lists +use crate::attributes::allow_unstable::*; +use crate::attributes::body::*; +use crate::attributes::cfi_encoding::*; +use crate::attributes::codegen_attrs::*; +use crate::attributes::confusables::*; +use crate::attributes::crate_level::*; +use crate::attributes::debugger::*; +use crate::attributes::deprecation::*; +use crate::attributes::do_not_recommend::*; +use crate::attributes::doc::*; +use crate::attributes::dummy::*; +use crate::attributes::inline::*; +use crate::attributes::instruction_set::*; +use crate::attributes::link_attrs::*; +use crate::attributes::lint_helpers::*; +use crate::attributes::loop_match::*; +use crate::attributes::macro_attrs::*; +use crate::attributes::must_not_suspend::*; +use crate::attributes::must_use::*; +use crate::attributes::no_implicit_prelude::*; +use crate::attributes::no_link::*; +use crate::attributes::non_exhaustive::*; use crate::attributes::path::PathParser as PathAttributeParser; -use crate::attributes::pin_v2::PinV2Parser; -use crate::attributes::proc_macro_attrs::{ - ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser, -}; -use crate::attributes::prototype::CustomMirParser; -use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; -use crate::attributes::rustc_allocator::{ - RustcAllocatorParser, RustcAllocatorZeroedParser, RustcAllocatorZeroedVariantParser, - RustcDeallocatorParser, RustcReallocatorParser, -}; -use crate::attributes::rustc_dump::{ - RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs, - RustcDumpVtable, -}; -use crate::attributes::rustc_internal::{ - RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser, - RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, - RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, - RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser, - RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser, - RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, - RustcSimdMonomorphizeLaneLimitParser, -}; -use crate::attributes::semantics::MayDangleParser; -use crate::attributes::stability::{ - BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, -}; -use crate::attributes::test_attrs::{ - IgnoreParser, RustcVarianceOfOpaquesParser, RustcVarianceParser, ShouldPanicParser, -}; -use crate::attributes::traits::{ - AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser, - DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser, - SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, - UnsafeSpecializationMarkerParser, -}; -use crate::attributes::transparency::TransparencyParser; +use crate::attributes::pin_v2::*; +use crate::attributes::proc_macro_attrs::*; +use crate::attributes::prototype::*; +use crate::attributes::repr::*; +use crate::attributes::rustc_allocator::*; +use crate::attributes::rustc_dump::*; +use crate::attributes::rustc_internal::*; +use crate::attributes::semantics::*; +use crate::attributes::stability::*; +use crate::attributes::test_attrs::*; +use crate::attributes::traits::*; +use crate::attributes::transparency::*; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, RefPathParser}; use crate::session_diagnostics::{ @@ -106,7 +62,7 @@ use crate::target_checking::AllowedTargets; type GroupType = LazyLock>; pub(super) struct GroupTypeInner { - pub(super) accepters: BTreeMap<&'static [Symbol], Vec>>, + pub(super) accepters: BTreeMap<&'static [Symbol], GroupTypeInnerAccept>, } pub(super) struct GroupTypeInnerAccept { @@ -146,7 +102,7 @@ macro_rules! attribute_parsers { @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?]; ) => { pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| { - let mut accepters = BTreeMap::<_, Vec>>::new(); + let mut accepters = BTreeMap::<_, GroupTypeInnerAccept<$stage>>::new(); $( { thread_local! { @@ -154,19 +110,24 @@ macro_rules! attribute_parsers { }; for (path, template, accept_fn) in <$names>::ATTRIBUTES { - accepters.entry(*path).or_default().push(GroupTypeInnerAccept { - template: *template, - accept_fn: Box::new(|cx, args| { - STATE_OBJECT.with_borrow_mut(|s| { - accept_fn(s, cx, args) - }) - }), - allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, - finalizer: Box::new(|cx| { - let state = STATE_OBJECT.take(); - state.finalize(cx) - }), - }); + match accepters.entry(*path) { + Entry::Vacant(e) => { + e.insert(GroupTypeInnerAccept { + template: *template, + accept_fn: Box::new(|cx, args| { + STATE_OBJECT.with_borrow_mut(|s| { + accept_fn(s, cx, args) + }) + }), + allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, + finalizer: Box::new(|cx| { + let state = STATE_OBJECT.take(); + state.finalize(cx) + }) + }); + } + Entry::Occupied(_) => panic!("Attribute {path:?} has multiple accepters"), + } } } )* @@ -186,6 +147,7 @@ attribute_parsers!( DocParser, MacroUseParser, NakedParser, + RustcCguTestAttributeParser, StabilityParser, UsedParser, // tidy-alphabetical-end @@ -198,6 +160,10 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, + Combine, + Combine, + Combine, Combine, Combine, // tidy-alphabetical-end @@ -215,6 +181,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -231,20 +198,30 @@ attribute_parsers!( Single, Single, Single, + Single, + Single, Single, Single, + Single, + Single, + Single, Single, + Single, Single, Single, Single, Single, Single, - Single, + Single, + Single, Single, Single, + Single, + Single, Single, Single, Single, + Single, Single, Single, Single, @@ -279,43 +256,63 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, Single>, Single>, + Single>, Single>, Single>, Single>, Single>, Single>, Single>, + Single>, Single>, + Single>, Single>, - Single>, - Single>, - Single>, - Single>, - Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, Single>, + Single>, + Single>, + Single>, + Single>, Single>, Single>, Single>, Single>, Single>, Single>, + Single>, + Single>, + Single>, Single>, + Single>, Single>, + Single>, Single>, + Single>, + Single>, Single>, + Single>, Single>, + Single>, + Single>, Single>, Single>, Single>, Single>, Single>, Single>, - Single>, Single>, // tidy-alphabetical-end ]; @@ -381,7 +378,7 @@ impl Stage for Late { } fn should_emit(&self) -> ShouldEmit { - ShouldEmit::ErrorsAndLints { recover: true } + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed } } } @@ -510,6 +507,11 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { ) } + /// Error that a filename string literal was expected. + pub(crate) fn expected_filename_literal(&self, span: Span) { + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedFilenameLiteral); + } + pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral) } @@ -768,10 +770,10 @@ pub enum ShouldEmit { ErrorsAndLints { /// Whether [`ArgParser`] will attempt to recover from errors. /// - /// If true, it will attempt to recover from bad input (like an invalid literal). Setting - /// this to false will instead return early, and not raise errors except at the top level - /// (in [`ArgParser::from_attr_args`]). - recover: bool, + /// Whether it is allowed to recover from bad input (like an invalid literal). Setting + /// this to `Forbidden` will instead return early, and not raise errors except at the top + /// level (in [`ArgParser::from_attr_args`]). + recovery: Recovery, }, /// The operation will *not* emit errors and lints. /// diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index bac4936c20d2..f75f63a0e811 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -327,7 +327,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let parts = n.item.path.segments.iter().map(|seg| seg.ident.name).collect::>(); - if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) { + if let Some(accept) = S::parsers().accepters.get(parts.as_slice()) { let Some(args) = ArgParser::from_attr_args( args, &parts, @@ -368,28 +368,26 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { continue; } - for accept in accepts { - let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { - shared: SharedContext { - cx: self, - target_span, - target, - emit_lint: &mut emit_lint, - }, - attr_span, - inner_span: lower_span(n.item.span()), - attr_style: attr.style, - parsed_description: ParsedDescription::Attribute, - template: &accept.template, - attr_path: attr_path.clone(), - }; + let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { + shared: SharedContext { + cx: self, + target_span, + target, + emit_lint: &mut emit_lint, + }, + attr_span, + inner_span: lower_span(n.item.span()), + attr_style: attr.style, + parsed_description: ParsedDescription::Attribute, + template: &accept.template, + attr_path: attr_path.clone(), + }; - (accept.accept_fn)(&mut cx, &args); - finalizers.push(&accept.finalizer); + (accept.accept_fn)(&mut cx, &args); + finalizers.push(&accept.finalizer); - if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) { - Self::check_target(&accept.allowed_targets, target, &mut cx); - } + if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) { + Self::check_target(&accept.allowed_targets, target, &mut cx); } } else { // If we're here, we must be compiling a tool attribute... Or someone diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 349e6c234520..fe050250e354 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -113,5 +113,3 @@ pub use attributes::util::{is_builtin_attr, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; pub use session_diagnostics::ParsedDescription; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7f3c6d28005f..973635f432e8 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr}; use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; @@ -121,7 +121,7 @@ impl ArgParser { &args.tokens, args.dspan.entire(), psess, - ShouldEmit::ErrorsAndLints { recover: false }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }, ) { Ok(p) => return Some(ArgParser::List(p)), Err(e) => { @@ -373,7 +373,10 @@ fn expr_to_lit<'sess>( } Err(err) => { let err = create_lit_error(psess, err, token_lit, expr.span); - if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { Err(err) } else { let lit = MetaItemLit { @@ -431,7 +434,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if !lit.kind.is_unsuffixed() { // Emit error and continue, we can still parse the attribute as if the suffix isn't there let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }); - if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + self.should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { return Err(err); } else { self.should_emit.emit_err(err) @@ -569,6 +575,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { should_emit: ShouldEmit, ) -> PResult<'sess, MetaItemListParser> { let mut parser = Parser::new(psess, tokens, None); + if let ShouldEmit::ErrorsAndLints { recovery } = should_emit { + parser = parser.recovery(recovery); + } + let mut this = MetaItemListParserContext { parser: &mut parser, should_emit }; // Presumably, the majority of the time there will only be one attr. diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index f9748542beb9..e98969dda300 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -11,10 +11,8 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use rustc_target::spec::TargetTuple; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_predicate, code = E0537)] +#[diag("invalid predicate `{$predicate}`", code = E0537)] pub(crate) struct InvalidPredicate { #[primary_span] pub span: Span, @@ -23,7 +21,7 @@ pub(crate) struct InvalidPredicate { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_empty)] +#[diag("{$attr_str} attribute cannot have empty value")] pub(crate) struct DocAliasEmpty<'a> { #[primary_span] pub span: Span, @@ -31,7 +29,7 @@ pub(crate) struct DocAliasEmpty<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_bad_char)] +#[diag("{$char_} character isn't allowed in {$attr_str}")] pub(crate) struct DocAliasBadChar<'a> { #[primary_span] pub span: Span, @@ -40,7 +38,7 @@ pub(crate) struct DocAliasBadChar<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_start_end)] +#[diag("{$attr_str} cannot start or end with ' '")] pub(crate) struct DocAliasStartEnd<'a> { #[primary_span] pub span: Span, @@ -48,7 +46,16 @@ pub(crate) struct DocAliasStartEnd<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_attr_not_crate_level)] +#[diag("`#[{$name})]` is missing a `{$field}` argument")] +pub(crate) struct CguFieldsMissing<'a> { + #[primary_span] + pub span: Span, + pub name: &'a AttrPath, + pub field: Symbol, +} + +#[derive(Diagnostic)] +#[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")] pub(crate) struct DocAttrNotCrateLevel { #[primary_span] pub span: Span, @@ -56,8 +63,8 @@ pub(crate) struct DocAttrNotCrateLevel { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_keyword_not_keyword)] -#[help] +#[diag("nonexistent keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`")] +#[help("only existing keywords are allowed in core/std")] pub(crate) struct DocKeywordNotKeyword { #[primary_span] pub span: Span, @@ -65,8 +72,8 @@ pub(crate) struct DocKeywordNotKeyword { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_attribute_not_attribute)] -#[help] +#[diag("nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = \"...\")]`")] +#[help("only existing builtin attributes are allowed in core/std")] pub(crate) struct DocAttributeNotAttribute { #[primary_span] pub span: Span, @@ -74,28 +81,28 @@ pub(crate) struct DocAttributeNotAttribute { } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_since, code = E0542)] +#[diag("missing 'since'", code = E0542)] pub(crate) struct MissingSince { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_note, code = E0543)] +#[diag("missing 'note'", code = E0543)] pub(crate) struct MissingNote { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_multiple_stability_levels, code = E0544)] +#[diag("multiple stability levels", code = E0544)] pub(crate) struct MultipleStabilityLevels { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_issue_string, code = E0545)] +#[diag("`issue` must be a non-zero numeric string or \"none\"", code = E0545)] pub(crate) struct InvalidIssueString { #[primary_span] pub span: Span, @@ -108,31 +115,31 @@ pub(crate) struct InvalidIssueString { // translatable. #[derive(Subdiagnostic)] pub(crate) enum InvalidIssueStringCause { - #[label(attr_parsing_must_not_be_zero)] + #[label("`issue` must not be \"0\", use \"none\" instead")] MustNotBeZero { #[primary_span] span: Span, }, - #[label(attr_parsing_empty)] + #[label("cannot parse integer from empty string")] Empty { #[primary_span] span: Span, }, - #[label(attr_parsing_invalid_digit)] + #[label("invalid digit found in string")] InvalidDigit { #[primary_span] span: Span, }, - #[label(attr_parsing_pos_overflow)] + #[label("number too large to fit in target type")] PosOverflow { #[primary_span] span: Span, }, - #[label(attr_parsing_neg_overflow)] + #[label("number too small to fit in target type")] NegOverflow { #[primary_span] span: Span, @@ -153,21 +160,21 @@ impl InvalidIssueStringCause { } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_feature, code = E0546)] +#[diag("missing 'feature'", code = E0546)] pub(crate) struct MissingFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_non_ident_feature, code = E0546)] +#[diag("'feature' is not an identifier", code = E0546)] pub(crate) struct NonIdentFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_issue, code = E0547)] +#[diag("missing 'issue'", code = E0547)] pub(crate) struct MissingIssue { #[primary_span] pub span: Span, @@ -176,20 +183,20 @@ pub(crate) struct MissingIssue { // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)] +#[diag("incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all", code = E0552)] pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_packed_expect_integer, code = E0552)] +#[diag("incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument", code = E0552)] pub(crate) struct IncorrectReprFormatPackedExpectInteger { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_hint_no_paren, code = E0552)] +#[diag("invalid representation hint: `{$name}` does not take a parenthesized argument list", code = E0552)] pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, @@ -198,7 +205,7 @@ pub(crate) struct InvalidReprHintNoParen { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_hint_no_value, code = E0552)] +#[diag("invalid representation hint: `{$name}` does not take a value", code = E0552)] pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, @@ -207,15 +214,19 @@ pub(crate) struct InvalidReprHintNoValue { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)] +#[diag("invalid `repr(align)` attribute: `align` needs an argument", code = E0589)] pub(crate) struct InvalidReprAlignNeedArg { #[primary_span] - #[suggestion(code = "align(...)", applicability = "has-placeholders")] + #[suggestion( + "supply an argument here", + code = "align(...)", + applicability = "has-placeholders" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_generic, code = E0589)] +#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)] pub(crate) struct InvalidReprGeneric<'a> { #[primary_span] pub span: Span, @@ -225,21 +236,21 @@ pub(crate) struct InvalidReprGeneric<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_align_one_arg, code = E0693)] +#[diag("incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses", code = E0693)] pub(crate) struct IncorrectReprFormatAlignOneArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_expect_literal_integer, code = E0693)] +#[diag("incorrect `repr(align)` attribute format: `align` expects a literal integer as argument", code = E0693)] pub(crate) struct IncorrectReprFormatExpectInteger { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)] +#[diag("incorrect `repr({$repr_arg})` attribute format", code = E0693)] pub(crate) struct IncorrectReprFormatGeneric { #[primary_span] pub span: Span, @@ -253,7 +264,7 @@ pub(crate) struct IncorrectReprFormatGeneric { #[derive(Subdiagnostic)] pub(crate) enum IncorrectReprFormatGenericCause { #[suggestion( - attr_parsing_suggestion, + "use parentheses instead", code = "{name}({value})", applicability = "machine-applicable" )] @@ -269,7 +280,7 @@ pub(crate) enum IncorrectReprFormatGenericCause { }, #[suggestion( - attr_parsing_suggestion, + "use parentheses instead", code = "{name}({value})", applicability = "machine-applicable" )] @@ -298,48 +309,48 @@ impl IncorrectReprFormatGenericCause { } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_promotable_pairing, code = E0717)] +#[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] pub(crate) struct RustcPromotablePairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_allowed_unstable_pairing, code = E0789)] +#[diag("`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute", code = E0789)] pub(crate) struct RustcAllowedUnstablePairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_deprecated_item_suggestion)] +#[diag("suggestions on deprecated items are unstable")] pub(crate) struct DeprecatedItemSuggestion { #[primary_span] pub span: Span, - #[help] + #[help("add `#![feature(deprecated_suggestion)]` to the crate root")] pub is_nightly: bool, - #[note] + #[note("see #94785 for more details")] pub details: (), } #[derive(Diagnostic)] -#[diag(attr_parsing_expected_single_version_literal)] +#[diag("expected single version literal")] pub(crate) struct ExpectedSingleVersionLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_expected_version_literal)] +#[diag("expected a version literal")] pub(crate) struct ExpectedVersionLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_expects_feature_list)] +#[diag("`{$name}` expects a list of feature names")] pub(crate) struct ExpectsFeatureList { #[primary_span] pub span: Span, @@ -348,7 +359,7 @@ pub(crate) struct ExpectsFeatureList { } #[derive(Diagnostic)] -#[diag(attr_parsing_expects_features)] +#[diag("`{$name}` expects feature names")] pub(crate) struct ExpectsFeatures { #[primary_span] pub span: Span, @@ -357,21 +368,21 @@ pub(crate) struct ExpectsFeatures { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_since)] +#[diag("'since' must be a Rust version number, such as \"1.31.0\"")] pub(crate) struct InvalidSince { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_soft_no_args)] +#[diag("`soft` should not have any arguments")] pub(crate) struct SoftNoArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unknown_version_literal)] +#[diag("unknown version literal format, assuming it refers to a future version")] pub(crate) struct UnknownVersionLiteral { #[primary_span] pub span: Span, @@ -379,78 +390,83 @@ pub(crate) struct UnknownVersionLiteral { // FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated. #[derive(Diagnostic)] -#[diag(attr_parsing_unused_multiple)] +#[diag("multiple `{$name}` attributes")] pub(crate) struct UnusedMultiple { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, pub name: Symbol, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_export, code = E0648)] +#[diag("`export_name` may not contain null characters", code = E0648)] pub(crate) struct NullOnExport { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_link_section, code = E0648)] +#[diag("`link_section` may not contain null characters", code = E0648)] pub(crate) struct NullOnLinkSection { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_objc_class)] +#[diag("`objc::class!` may not contain null characters")] pub(crate) struct NullOnObjcClass { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_objc_selector)] +#[diag("`objc::selector!` may not contain null characters")] pub(crate) struct NullOnObjcSelector { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_objc_class_expected_string_literal)] +#[diag("`objc::class!` expected a string literal")] pub(crate) struct ObjcClassExpectedStringLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_objc_selector_expected_string_literal)] +#[diag("`objc::selector!` expected a string literal")] pub(crate) struct ObjcSelectorExpectedStringLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_stability_outside_std, code = E0734)] +#[diag("stability attributes may not be used outside of the standard library", code = E0734)] pub(crate) struct StabilityOutsideStd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_empty_confusables)] +#[diag("expected at least one confusable name")] pub(crate) struct EmptyConfusables { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[help] -#[diag(attr_parsing_invalid_target)] +#[help("`#[{$name}]` can {$only}be applied to {$applied}")] +#[diag("`#[{$name}]` attribute cannot be used on {$target}")] pub(crate) struct InvalidTarget { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub span: Span, pub name: AttrPath, pub target: &'static str, @@ -459,7 +475,7 @@ pub(crate) struct InvalidTarget { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_alignment_value, code = E0589)] +#[diag("invalid alignment value: {$error_part}", code = E0589)] pub(crate) struct InvalidAlignmentValue { #[primary_span] pub span: Span, @@ -467,43 +483,49 @@ pub(crate) struct InvalidAlignmentValue { } #[derive(Diagnostic)] -#[diag(attr_parsing_repr_ident, code = E0565)] +#[diag("meta item in `repr` must be an identifier", code = E0565)] pub(crate) struct ReprIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unrecognized_repr_hint, code = E0552)] -#[help] -#[note] +#[diag("unrecognized representation hint", code = E0552)] +#[help( + "valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`" +)] +#[note( + "for more information, visit " +)] pub(crate) struct UnrecognizedReprHint { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)] -#[help] +#[diag("item annotated with `#[unstable_feature_bound]` should not be stable")] +#[help( + "if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`" +)] pub(crate) struct UnstableFeatureBoundIncompatibleStability { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)] +#[diag("attribute incompatible with `#[unsafe(naked)]`", code = E0736)] pub(crate) struct NakedFunctionIncompatibleAttribute { #[primary_span] - #[label] + #[label("the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`")] pub span: Span, - #[label(attr_parsing_naked_attribute)] + #[label("function marked with `#[unsafe(naked)]` here")] pub naked_span: Span, pub attr: String, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_ordinal_out_of_range)] -#[note] +#[diag("ordinal value in `link_ordinal` is too large: `{$ordinal}`")] +#[note("the value may not exceed `u16::MAX`")] pub(crate) struct LinkOrdinalOutOfRange { #[primary_span] pub span: Span, @@ -511,19 +533,28 @@ pub(crate) struct LinkOrdinalOutOfRange { } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_scalable_vector_count_out_of_range)] -#[note] +#[diag("element count in `rustc_scalable_vector` is too large: `{$n}`")] +#[note("the value may not exceed `u16::MAX`")] pub(crate) struct RustcScalableVectorCountOutOfRange { #[primary_span] pub span: Span, pub n: u128, } +#[derive(Diagnostic)] +#[diag("attribute requires {$opt} to be enabled")] +pub(crate) struct AttributeRequiresOpt { + #[primary_span] + pub span: Span, + pub opt: &'static str, +} + pub(crate) enum AttributeParseErrorReason<'a> { ExpectedNoArgs, ExpectedStringLiteral { byte_string: Option, }, + ExpectedFilenameLiteral, ExpectedIntegerLiteral, ExpectedIntegerLiteralInRange { lower_bound: isize, @@ -586,7 +617,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { if let Some(start_point_span) = byte_string { diag.span_suggestion( start_point_span, - fluent::attr_parsing_unsupported_literal_suggestion, + "consider removing the prefix", "", Applicability::MaybeIncorrect, ); @@ -597,6 +628,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_label(self.span, "expected a string literal here"); } } + AttributeParseErrorReason::ExpectedFilenameLiteral => { + diag.span_label(self.span, "expected a filename string literal here"); + } AttributeParseErrorReason::ExpectedIntegerLiteral => { diag.span_label(self.span, "expected an integer literal here"); } @@ -751,30 +785,27 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_attr_unsafe)] -#[note] +#[diag("`{$name}` is not an unsafe attribute")] +#[note("extraneous unsafe is not allowed in attributes")] pub(crate) struct InvalidAttrUnsafe { #[primary_span] - #[label] + #[label("this is not an unsafe attribute")] pub span: Span, pub name: AttrPath, } #[derive(Diagnostic)] -#[diag(attr_parsing_unsafe_attr_outside_unsafe)] +#[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafe { #[primary_span] - #[label] + #[label("usage of unsafe attribute")] pub span: Span, #[subdiagnostic] pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - attr_parsing_unsafe_attr_outside_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -783,7 +814,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { } #[derive(Diagnostic)] -#[diag(attr_parsing_meta_bad_delim)] +#[diag("wrong meta list delimiters")] pub(crate) struct MetaBadDelim { #[primary_span] pub span: Span, @@ -793,7 +824,7 @@ pub(crate) struct MetaBadDelim { #[derive(Subdiagnostic)] #[multipart_suggestion( - attr_parsing_meta_bad_delim_suggestion, + "the delimiters should be `(` and `)`", applicability = "machine-applicable" )] pub(crate) struct MetaBadDelimSugg { @@ -804,7 +835,7 @@ pub(crate) struct MetaBadDelimSugg { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_meta_item)] +#[diag("expected a literal (`1u8`, `1.0f32`, `\"string\"`, etc.) here, found {$descr}")] pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, @@ -813,12 +844,15 @@ pub(crate) struct InvalidMetaItem { pub quote_ident_sugg: Option, #[subdiagnostic] pub remove_neg_sugg: Option, - #[label] + #[label("{$descr}s are not allowed here")] pub label: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(attr_parsing_quote_ident_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the identifier with quotation marks to make it into a string literal", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[suggestion_part(code = "\"")] pub before: Span, @@ -827,73 +861,80 @@ pub(crate) struct InvalidMetaItemQuoteIdentSugg { } #[derive(Subdiagnostic)] -#[multipart_suggestion(attr_parsing_remove_neg_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "negative numbers are not literals, try removing the `-` sign", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemRemoveNegSugg { #[suggestion_part(code = "")] pub negative_sign: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_suffixed_literal_in_attribute)] -#[help] +#[diag("suffixed literals are not allowed in attributes")] +#[help( + "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" +)] pub(crate) struct SuffixedLiteralInAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_empty_link_name, code = E0454)] +#[diag("link name must not be empty", code = E0454)] pub(crate) struct EmptyLinkName { #[primary_span] - #[label] + #[label("empty link name")] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_framework_apple, code = E0455)] +#[diag("link kind `framework` is only supported on Apple targets", code = E0455)] pub(crate) struct LinkFrameworkApple { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incompatible_wasm_link)] +#[diag("`wasm_import_module` is incompatible with other arguments in `#[link]` attributes")] pub(crate) struct IncompatibleWasmLink { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_requires_name, code = E0459)] +#[diag("`#[link]` attribute requires a `name = \"string\"` argument", code = E0459)] pub(crate) struct LinkRequiresName { #[primary_span] - #[label] + #[label("missing `name` argument")] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_raw_dylib_no_nul)] +#[diag("link name must not contain NUL characters if link kind is `raw-dylib`")] pub(crate) struct RawDylibNoNul { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)] +#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)] pub(crate) struct RawDylibOnlyWindows { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_link_modifier)] +#[diag( + "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols" +)] pub(crate) struct InvalidLinkModifier { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_multiple_modifiers)] +#[diag("multiple `{$modifier}` modifiers in a single `modifiers` argument")] pub(crate) struct MultipleModifiers { #[primary_span] pub span: Span, @@ -901,52 +942,61 @@ pub(crate) struct MultipleModifiers { } #[derive(Diagnostic)] -#[diag(attr_parsing_import_name_type_x86)] +#[diag("import name type is only supported on x86")] pub(crate) struct ImportNameTypeX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_bundle_needs_static)] +#[diag("linking modifier `bundle` is only compatible with `static` linking kind")] pub(crate) struct BundleNeedsStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_whole_archive_needs_static)] +#[diag("linking modifier `export-symbols` is only compatible with `static` linking kind")] +pub(crate) struct ExportSymbolsNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")] pub(crate) struct WholeArchiveNeedsStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_as_needed_compatibility)] +#[diag( + "linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds" +)] pub(crate) struct AsNeededCompatibility { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_import_name_type_raw)] +#[diag("import name type can only be used with link kind `raw-dylib`")] pub(crate) struct ImportNameTypeRaw { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_limit_invalid)] +#[diag("`limit` must be a non-negative integer")] pub(crate) struct LimitInvalid<'a> { #[primary_span] pub span: Span, - #[label] + #[label("{$error_str}")] pub value_span: Span, pub error_str: &'a str, } #[derive(Diagnostic)] -#[diag(attr_parsing_cfg_attr_bad_delim)] +#[diag("wrong `cfg_attr` delimiters")] pub(crate) struct CfgAttrBadDelim { #[primary_span] pub span: Span, @@ -955,14 +1005,25 @@ pub(crate) struct CfgAttrBadDelim { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_malformed)] +#[diag( + "doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of strings `#[doc(alias(\"a\", \"b\"))]`" +)] pub(crate) struct DocAliasMalformed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unsupported_instruction_set)] +#[diag("definition of an unknown lang item: `{$name}`", code = E0522)] +pub(crate) struct UnknownLangItem { + #[primary_span] + #[label("definition of unknown lang item `{$name}`")] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")] pub(crate) struct UnsupportedInstructionSet<'a> { #[primary_span] pub span: Span, diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 79aa06e9475c..fb005477f0fa 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -205,7 +205,7 @@ pub(crate) fn allowed_targets_applied( ]; const IMPL_LIKE: &[Target] = &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }]; - const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum]; + const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum, Target::Union]; let mut added_fake_targets = Vec::new(); filter_targets( diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 9e7d55180a23..55a09dbf1d72 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -11,7 +11,6 @@ polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl deleted file mode 100644 index f59e106c7ac3..000000000000 --- a/compiler/rustc_borrowck/messages.ftl +++ /dev/null @@ -1,296 +0,0 @@ -borrowck_assign_due_to_use_closure = - assignment occurs due to use in closure - -borrowck_assign_due_to_use_coroutine = - assign occurs due to use in coroutine - -borrowck_assign_part_due_to_use_closure = - assignment to part occurs due to use in closure - -borrowck_assign_part_due_to_use_coroutine = - assign to part occurs due to use in coroutine - -borrowck_borrow_due_to_use_closure = - borrow occurs due to use in closure - -borrowck_borrow_due_to_use_coroutine = - borrow occurs due to use in coroutine - -borrowck_calling_operator_moves = - calling this operator moves the value - -borrowck_calling_operator_moves_lhs = - calling this operator moves the left-hand side - -borrowck_cannot_move_when_borrowed = - cannot move out of {$place -> - [value] value - *[other] {$place} - } because it is borrowed - .label = borrow of {$borrow_place -> - [value] value - *[other] {$borrow_place} - } occurs here - .move_label = move out of {$value_place -> - [value] value - *[other] {$value_place} - } occurs here - -borrowck_capture_immute = - capture is immutable because of use here - -borrowck_capture_move = - capture is moved because of use here - -borrowck_capture_mut = - capture is mutable because of use here - -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure - -borrowck_closure_invoked_twice = - closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment - -borrowck_closure_moved_twice = - closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment - -borrowck_consider_borrow_type_contents = - help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - -borrowck_could_not_normalize = - could not normalize `{$value}` - -borrowck_could_not_prove = - could not prove `{$predicate}` - -borrowck_dereference_suggestion = - dereference the return value - -borrowck_func_take_self_moved_place = - `{$func}` takes ownership of the receiver `self`, which moves {$place_name} - -borrowck_generic_does_not_live_long_enough = - `{$kind}` does not live long enough - -borrowck_higher_ranked_lifetime_error = - higher-ranked lifetime error - -borrowck_higher_ranked_subtype_error = - higher-ranked subtype error - -borrowck_implicit_static = - this has an implicit `'static` lifetime requirement - -borrowck_implicit_static_introduced = - calling this method introduces the `impl`'s `'static` requirement - -borrowck_implicit_static_relax = - consider relaxing the implicit `'static` requirement - -borrowck_lifetime_constraints_error = - lifetime may not live long enough - -borrowck_limitations_implies_static = - due to a current limitation of the type system, this implies a `'static` lifetime - -borrowck_move_closure_suggestion = - consider adding 'move' keyword before the nested closure - -borrowck_move_out_place_here = - {$place} is moved here - -borrowck_move_unsized = - cannot move a value of type `{$ty}` - .label = the size of `{$ty}` cannot be statically determined - -borrowck_moved_a_fn_once_in_call = - this value implements `FnOnce`, which causes it to be moved when called - -borrowck_moved_a_fn_once_in_call_call = - `FnOnce` closures can only be called once - -borrowck_moved_a_fn_once_in_call_def = - `{$ty}` is made to be an `FnOnce` closure here - -borrowck_moved_due_to_await = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] await, in previous iteration of loop - *[false] await - } - -borrowck_moved_due_to_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_implicit_into_iter_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this implicit call to {$is_loop_message -> - [true] `.into_iter()`, in previous iteration of loop - *[false] `.into_iter()` - } - -borrowck_moved_due_to_method_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this method {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_usage_in_operator = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to usage in {$is_loop_message -> - [true] operator, in previous iteration of loop - *[false] operator - } - -borrowck_opaque_type_lifetime_mismatch = - opaque type used twice with different lifetimes - .label = lifetime `{$arg}` used here - .prev_lifetime_label = lifetime `{$prev}` previously used here - .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - -borrowck_partial_var_move_by_use_in_closure = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in closure - -borrowck_partial_var_move_by_use_in_coroutine = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in coroutine - -borrowck_restrict_to_static = - consider restricting the type parameter to the `'static` lifetime - -borrowck_returned_async_block_escaped = - returns an `async` block that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_closure_escaped = - returns a closure that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_lifetime_short = - {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}` - -borrowck_returned_lifetime_wrong = - {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}` - -borrowck_returned_ref_escaped = - returns a reference to a captured variable which escapes the closure body - -borrowck_simd_intrinsic_arg_const = - {$arg -> - [1] 1st - [2] 2nd - [3] 3rd - *[other] {$arg}th - } argument of `{$intrinsic}` is required to be a `const` item - -borrowck_suggest_create_fresh_reborrow = - consider reborrowing the `Pin` instead of moving it - -borrowck_suggest_iterate_over_slice = - consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop - -borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024 - .label = this temporary value will be dropped at the end of the block - .note = consider using a `let` binding to ensure the value will live long enough - -borrowck_ty_no_impl_copy = - {$is_partial_move -> - [true] partial move - *[false] move - } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait - -borrowck_use_due_to_use_closure = - use occurs due to use in closure - -borrowck_use_due_to_use_coroutine = - use occurs due to use in coroutine - -borrowck_used_impl_require_static = - the used `impl` has a `'static` requirement - -borrowck_value_capture_here = - value captured {$is_within -> - [true] here by coroutine - *[false] here - } - -borrowck_value_moved_here = - value {$is_partial -> - [true] partially moved - *[false] moved - } {$is_move_msg -> - [true] into closure here - *[false] here - }{$is_loop_message -> - [true] , in previous iteration of loop - *[false] {""} - } - -borrowck_var_borrow_by_use_in_closure = - borrow occurs due to use in closure - -borrowck_var_borrow_by_use_in_coroutine = - borrow occurs due to use in coroutine - -borrowck_var_borrow_by_use_place_in_closure = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in closure - -borrowck_var_borrow_by_use_place_in_coroutine = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in coroutine - -borrowck_var_cannot_escape_closure = - captured variable cannot escape `FnMut` closure body - .note = `FnMut` closures only have access to their captured variables while they are executing... - .cannot_escape = ...therefore, they cannot allow references to captured variables to escape - -borrowck_var_does_not_need_mut = - variable does not need to be mutable - .suggestion = remove this `mut` - -borrowck_var_first_borrow_by_use_place_in_closure = - first borrow occurs due to use of {$place} in closure - -borrowck_var_first_borrow_by_use_place_in_coroutine = - first borrow occurs due to use of {$place} in coroutine - -borrowck_var_here_captured = variable captured here - -borrowck_var_here_defined = variable defined here - -borrowck_var_move_by_use_in_closure = - move occurs due to use in closure - -borrowck_var_move_by_use_in_coroutine = - move occurs due to use in coroutine - -borrowck_var_mutable_borrow_by_use_place_in_closure = - mutable borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_closure = - second borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_coroutine = - second borrow occurs due to use of {$place} in coroutine diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 254d28d243ff..a927c30fae32 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -24,7 +24,6 @@ use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_ use tracing::{debug, instrument}; use crate::MirBorrowckCtxt; -use crate::region_infer::values::RegionElement; use crate::session_diagnostics::{ HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError, }; @@ -49,11 +48,12 @@ impl<'tcx> UniverseInfo<'tcx> { UniverseInfo::RelateTys { expected, found } } + /// Report an error where an element erroneously made its way into `placeholder`. pub(crate) fn report_erroneous_element( &self, mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion<'tcx>, - error_element: RegionElement<'tcx>, + error_element: Option>, cause: ObligationCause<'tcx>, ) { match *self { @@ -146,14 +146,14 @@ pub(crate) trait TypeOpInfo<'tcx> { ) -> Option>; /// Constraints require that `error_element` appear in the - /// values of `placeholder`, but this cannot be proven to + /// values of `placeholder`, but this cannot be proven to /// hold. Report an error. #[instrument(level = "debug", skip(self, mbcx))] fn report_erroneous_element( &self, mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion<'tcx>, - error_element: RegionElement<'tcx>, + error_element: Option>, cause: ObligationCause<'tcx>, ) { let tcx = mbcx.infcx.tcx; @@ -169,22 +169,20 @@ pub(crate) trait TypeOpInfo<'tcx> { let placeholder_region = ty::Region::new_placeholder( tcx, - ty::Placeholder::new(adjusted_universe.into(), placeholder.bound), + ty::PlaceholderRegion::new(adjusted_universe.into(), placeholder.bound), ); - let error_region = - if let RegionElement::PlaceholderRegion(error_placeholder) = error_element { - let adjusted_universe = - error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32()); - adjusted_universe.map(|adjusted| { - ty::Region::new_placeholder( - tcx, - ty::Placeholder::new(adjusted.into(), error_placeholder.bound), - ) - }) - } else { - None - }; + // FIXME: one day this should just be error_element, + // and this method shouldn't do anything. + let error_region = error_element.and_then(|e| { + let adjusted_universe = e.universe.as_u32().checked_sub(base_universe.as_u32()); + adjusted_universe.map(|adjusted| { + ty::Region::new_placeholder( + tcx, + ty::PlaceholderRegion::new(adjusted.into(), e.bound), + ) + }) + }); debug!(?placeholder_region); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index caf6a86af098..1582833bf15d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning_inner(err, ty, expr); } } else if let ty::Adt(def, args) = ty.kind() - && def.did().as_local().is_some() + && let Some(local_did) = def.did().as_local() && def.variants().iter().all(|variant| { variant .fields @@ -1266,12 +1266,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { { let ty_span = self.infcx.tcx.def_span(def.did()); let mut span: MultiSpan = ty_span.into(); - span.push_span_label(ty_span, "consider implementing `Clone` for this type"); - span.push_span_label(expr.span, "you could clone this value"); - err.span_note( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), + let mut derive_clone = false; + self.infcx.tcx.for_each_relevant_impl( + self.infcx.tcx.lang_items().clone_trait().unwrap(), + ty, + |def_id| { + if self.infcx.tcx.is_automatically_derived(def_id) { + derive_clone = true; + span.push_span_label( + self.infcx.tcx.def_span(def_id), + "derived `Clone` adds implicit bounds on type parameters", + ); + if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) { + for param in generics.params { + if let hir::GenericParamKind::Type { .. } = param.kind { + span.push_span_label( + param.span, + format!( + "introduces an implicit `{}: Clone` bound", + param.name.ident() + ), + ); + } + } + } + } + }, ); + let msg = if !derive_clone { + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); + format!("if `{ty}` implemented `Clone`, you could clone the value") + } else { + format!("if all bounds were met, you could clone the value") + }; + span.push_span_label(expr.span, "you could clone this value"); + err.span_note(span, msg); + if derive_clone { + err.help("consider manually implementing `Clone` to avoid undesired bounds"); + } } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) @@ -2309,12 +2347,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { tcx: TyCtxt<'hir>, issue_span: Span, expr_span: Span, - body_expr: Option<&'hir hir::Expr<'hir>>, - loop_bind: Option<&'hir Ident>, - loop_span: Option, - head_span: Option, - pat_span: Option, - head: Option<&'hir hir::Expr<'hir>>, + body_expr: Option<&'hir hir::Expr<'hir>> = None, + loop_bind: Option<&'hir Ident> = None, + loop_span: Option = None, + head_span: Option = None, + pat_span: Option = None, + head: Option<&'hir hir::Expr<'hir>> = None, } impl<'hir> Visitor<'hir> for ExprFinder<'hir> { fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { @@ -2380,17 +2418,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { hir::intravisit::walk_expr(self, ex); } } - let mut finder = ExprFinder { - tcx, - expr_span: span, - issue_span, - loop_bind: None, - body_expr: None, - head_span: None, - loop_span: None, - pat_span: None, - head: None, - }; + let mut finder = ExprFinder { tcx, expr_span: span, issue_span, .. }; finder.visit_expr(tcx.hir_body(body_id).value); if let Some(body_expr) = finder.body_expr @@ -2625,13 +2653,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { struct ExpressionFinder<'tcx> { capture_span: Span, - closure_change_spans: Vec, - closure_arg_span: Option, - in_closure: bool, - suggest_arg: String, + closure_change_spans: Vec = vec![], + closure_arg_span: Option = None, + in_closure: bool = false, + suggest_arg: String = String::new(), tcx: TyCtxt<'tcx>, - closure_local_id: Option, - closure_call_changes: Vec<(Span, String)>, + closure_local_id: Option = None, + closure_call_changes: Vec<(Span, String)> = vec![], } impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { @@ -2712,16 +2740,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }) = self.infcx.tcx.hir_node(self.mir_hir_id()) && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id) { - let mut finder = ExpressionFinder { - capture_span: *capture_kind_span, - closure_change_spans: vec![], - closure_arg_span: None, - in_closure: false, - suggest_arg: String::new(), - closure_local_id: None, - closure_call_changes: vec![], - tcx: self.infcx.tcx, - }; + let mut finder = + ExpressionFinder { capture_span: *capture_kind_span, tcx: self.infcx.tcx, .. }; finder.visit_expr(expr); if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index bbd0a8ae0710..bc2e99b9ceb5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -649,8 +649,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // We want to focus on relevant live locals in diagnostics, so when polonius is enabled, we // ensure that we don't emit live boring locals as explanations. let is_local_boring = |local| { - if let Some(polonius_diagnostics) = self.polonius_diagnostics { - polonius_diagnostics.boring_nll_locals.contains(&local) + if let Some(polonius_context) = self.polonius_context { + polonius_context.boring_nll_locals.contains(&local) } else { assert!(!tcx.sess.opts.unstable_opts.polonius.is_next_enabled()); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c15e7041c94d..7c895ff63e07 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; +use rustc_errors::{Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, listify, msg}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ self as hir, CoroutineKind, GenericBound, LangItem, WhereBoundPredicate, WherePredicateKind, @@ -35,7 +35,6 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; use crate::constraints::OutlivesConstraint; -use crate::fluent_generated as fluent; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, @@ -700,7 +699,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(pred.span, fluent::borrowck_limitations_implies_static); + diag.span_note(pred.span, LIMITATION_NOTE); return; } for bound in bounds.iter() { @@ -711,7 +710,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(bound.span, fluent::borrowck_limitations_implies_static); + diag.span_note(bound.span, LIMITATION_NOTE); return; } } @@ -1312,7 +1311,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut span: MultiSpan = spans.clone().into(); err.arg("ty", param_ty.to_string()); let msg = err.dcx.eagerly_translate_to_string( - fluent::borrowck_moved_a_fn_once_in_call_def, + msg!("`{$ty}` is made to be an `FnOnce` closure here"), err.args.iter(), ); err.remove_arg("ty"); @@ -1321,9 +1320,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } span.push_span_label( fn_call_span, - fluent::borrowck_moved_a_fn_once_in_call, + msg!("this value implements `FnOnce`, which causes it to be moved when called"), ); - err.span_note(span, fluent::borrowck_moved_a_fn_once_in_call_call); + err.span_note(span, msg!("`FnOnce` closures can only be called once")); } else { err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } @@ -1568,3 +1567,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.local_name(index).is_none_or(|name| name.as_str().starts_with('_')) } } + +const LIMITATION_NOTE: DiagMessage = + msg!("due to a current limitation of the type system, this implies a `'static` lifetime"); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index f83931d37599..986ade57fb31 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,3 +1,4 @@ +use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; @@ -7,7 +8,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; use rustc_span::def_id::DefId; -use rustc_span::{BytePos, DUMMY_SP, ExpnKind, MacroKind, Span}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use rustc_trait_selection::infer::InferCtxtExt; use tracing::debug; @@ -472,49 +473,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if def_id.as_local() == Some(self.mir_def_id()) && let Some(upvar_field) = upvar_field => { - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind = match closure_kind_ty.to_opt_closure_kind() { - Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, - Some(ty::ClosureKind::FnOnce) => { - bug!("closure kind does not match first argument type") - } - None => bug!("closure kind not inferred by borrowck"), - }; - let capture_description = - format!("captured variable in an `{closure_kind}` closure"); - - let upvar = &self.upvars[upvar_field.index()]; - let upvar_hir_id = upvar.get_root_variable(); - let upvar_name = upvar.to_string(tcx); - let upvar_span = tcx.hir_span(upvar_hir_id); - - let place_name = self.describe_any_place(move_place.as_ref()); - - let place_description = - if self.is_upvar_field_projection(move_place.as_ref()).is_some() { - format!("{place_name}, a {capture_description}") - } else { - format!("{place_name}, as `{upvar_name}` is a {capture_description}") - }; - - debug!( - "report: closure_kind_ty={:?} closure_kind={:?} place_description={:?}", - closure_kind_ty, closure_kind, place_description, - ); - - let closure_span = tcx.def_span(def_id); - - self.cannot_move_out_of(span, &place_description) - .with_span_label(upvar_span, "captured outer variable") - .with_span_label( - closure_span, - format!("captured by this `{closure_kind}` closure"), - ) - .with_span_help( - self.get_closure_bound_clause_span(*def_id), - "`Fn` and `FnMut` closures require captured values to be able to be \ - consumed multiple times, but `FnOnce` closures may consume them only once", - ) + self.report_closure_move_error( + span, + move_place, + *def_id, + closure_args.as_closure().kind_ty(), + upvar_field, + ty::Asyncness::No, + ) + } + ty::CoroutineClosure(def_id, closure_args) + if def_id.as_local() == Some(self.mir_def_id()) + && let Some(upvar_field) = upvar_field + && self + .get_closure_bound_clause_span(*def_id, ty::Asyncness::Yes) + .is_some() => + { + self.report_closure_move_error( + span, + move_place, + *def_id, + closure_args.as_coroutine_closure().kind_ty(), + upvar_field, + ty::Asyncness::Yes, + ) } _ => { let source = self.borrowed_content_source(deref_base); @@ -563,45 +545,134 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { err } - fn get_closure_bound_clause_span(&self, def_id: DefId) -> Span { + fn report_closure_move_error( + &self, + span: Span, + move_place: Place<'tcx>, + def_id: DefId, + closure_kind_ty: Ty<'tcx>, + upvar_field: FieldIdx, + asyncness: ty::Asyncness, + ) -> Diag<'infcx> { + let tcx = self.infcx.tcx; + + let closure_kind = match closure_kind_ty.to_opt_closure_kind() { + Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, + Some(ty::ClosureKind::FnOnce) => { + bug!("closure kind does not match first argument type") + } + None => bug!("closure kind not inferred by borrowck"), + }; + + let async_prefix = if asyncness.is_async() { "Async" } else { "" }; + let capture_description = + format!("captured variable in an `{async_prefix}{closure_kind}` closure"); + + let upvar = &self.upvars[upvar_field.index()]; + let upvar_hir_id = upvar.get_root_variable(); + let upvar_name = upvar.to_string(tcx); + let upvar_span = tcx.hir_span(upvar_hir_id); + + let place_name = self.describe_any_place(move_place.as_ref()); + + let place_description = if self.is_upvar_field_projection(move_place.as_ref()).is_some() { + format!("{place_name}, a {capture_description}") + } else { + format!("{place_name}, as `{upvar_name}` is a {capture_description}") + }; + + debug!(?closure_kind_ty, ?closure_kind, ?place_description); + + let closure_span = tcx.def_span(def_id); + + let help_msg = format!( + "`{async_prefix}Fn` and `{async_prefix}FnMut` closures require captured values to \ + be able to be consumed multiple times, but `{async_prefix}FnOnce` closures may \ + consume them only once" + ); + + let mut err = self + .cannot_move_out_of(span, &place_description) + .with_span_label(upvar_span, "captured outer variable") + .with_span_label( + closure_span, + format!("captured by this `{async_prefix}{closure_kind}` closure"), + ); + + if let Some(bound_span) = self.get_closure_bound_clause_span(def_id, asyncness) { + err.span_help(bound_span, help_msg); + } else if !asyncness.is_async() { + // For sync closures, always emit the help message even without a span. + // For async closures, we only enter this branch if we found a valid span + // (due to the match guard), so no fallback is needed. + err.help(help_msg); + } + + err + } + + fn get_closure_bound_clause_span( + &self, + def_id: DefId, + asyncness: ty::Asyncness, + ) -> Option { let tcx = self.infcx.tcx; let typeck_result = tcx.typeck(self.mir_def_id()); // Check whether the closure is an argument to a call, if so, // get the instantiated where-bounds of that call. let closure_hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return DUMMY_SP }; + let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return None }; let predicates = match parent.kind { hir::ExprKind::Call(callee, _) => { - let Some(ty) = typeck_result.node_type_opt(callee.hir_id) else { return DUMMY_SP }; - let ty::FnDef(fn_def_id, args) = ty.kind() else { return DUMMY_SP }; + let ty = typeck_result.node_type_opt(callee.hir_id)?; + let ty::FnDef(fn_def_id, args) = ty.kind() else { return None }; tcx.predicates_of(fn_def_id).instantiate(tcx, args) } hir::ExprKind::MethodCall(..) => { - let Some((_, method)) = typeck_result.type_dependent_def(parent.hir_id) else { - return DUMMY_SP; - }; + let (_, method) = typeck_result.type_dependent_def(parent.hir_id)?; let args = typeck_result.node_args(parent.hir_id); tcx.predicates_of(method).instantiate(tcx, args) } - _ => return DUMMY_SP, + _ => return None, }; - // Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`. + // Check whether one of the where-bounds requires the closure to impl `Fn[Mut]` + // or `AsyncFn[Mut]`. for (pred, span) in predicates.predicates.iter().zip(predicates.spans.iter()) { - if let Some(clause) = pred.as_trait_clause() - && let ty::Closure(clause_closure_def_id, _) = clause.self_ty().skip_binder().kind() - && *clause_closure_def_id == def_id - && (tcx.lang_items().fn_mut_trait() == Some(clause.def_id()) - || tcx.lang_items().fn_trait() == Some(clause.def_id())) - { - // Found `` - // We point at the `Fn()` or `FnMut()` bound that coerced the closure, which - // could be changed to `FnOnce()` to avoid the move error. - return *span; + let dominated_by_fn_trait = self + .closure_clause_kind(*pred, def_id, asyncness) + .is_some_and(|kind| matches!(kind, ty::ClosureKind::Fn | ty::ClosureKind::FnMut)); + if dominated_by_fn_trait { + // Found `` or + // ``. + // We point at the bound that coerced the closure, which could be changed + // to `FnOnce()` or `AsyncFnOnce()` to avoid the move error. + return Some(*span); } } - DUMMY_SP + None + } + + /// If `pred` is a trait clause binding the closure `def_id` to `Fn`/`FnMut`/`FnOnce` + /// (or their async equivalents based on `asyncness`), returns the corresponding + /// `ClosureKind`. Otherwise returns `None`. + fn closure_clause_kind( + &self, + pred: ty::Clause<'tcx>, + def_id: DefId, + asyncness: ty::Asyncness, + ) -> Option { + let tcx = self.infcx.tcx; + let clause = pred.as_trait_clause()?; + let kind = match asyncness { + ty::Asyncness::Yes => tcx.async_fn_trait_kind_from_def_id(clause.def_id()), + ty::Asyncness::No => tcx.fn_trait_kind_from_def_id(clause.def_id()), + }?; + match clause.self_ty().skip_binder().kind() { + ty::Closure(id, _) | ty::CoroutineClosure(id, _) if *id == def_id => Some(kind), + _ => None, + } } fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 4fb739403ced..96090e85e562 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -354,14 +354,71 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.infcx.tcx.sess.source_map().span_to_snippet(source_info.span) { if snippet.starts_with("&mut ") { - // We don't have access to the HIR to get accurate spans, but we can - // give a best effort structured suggestion. - err.span_suggestion_verbose( - source_info.span.with_hi(source_info.span.lo() + BytePos(5)), - "if there is only one mutable reborrow, remove the `&mut`", - "", - Applicability::MaybeIncorrect, - ); + // In calls, `&mut &mut T` may be deref-coerced to `&mut T`, and + // removing the extra `&mut` is the most direct suggestion. But for + // pattern-matching expressions (`match`, `if let`, `while let`), that + // can easily turn into a move, so prefer suggesting an explicit + // reborrow via `&mut *x` instead. + let mut in_pat_scrutinee = false; + let mut is_deref_coerced = false; + if let Some(expr) = self.find_expr(source_info.span) { + let tcx = self.infcx.tcx; + let span = expr.span.source_callsite(); + for (_, node) in tcx.hir_parent_iter(expr.hir_id) { + if let Node::Expr(parent_expr) = node { + match parent_expr.kind { + ExprKind::Match(scrutinee, ..) + if scrutinee + .span + .source_callsite() + .contains(span) => + { + in_pat_scrutinee = true; + break; + } + ExprKind::Let(let_expr) + if let_expr + .init + .span + .source_callsite() + .contains(span) => + { + in_pat_scrutinee = true; + break; + } + _ => {} + } + } + } + + let typeck = tcx.typeck(expr.hir_id.owner.def_id); + is_deref_coerced = + typeck.expr_adjustments(expr).iter().any(|adj| { + matches!(adj.kind, ty::adjustment::Adjust::Deref(_)) + }); + } + + if in_pat_scrutinee { + // Best-effort structured suggestion: insert `*` after `&mut `. + err.span_suggestion_verbose( + source_info + .span + .with_lo(source_info.span.lo() + BytePos(5)) + .shrink_to_lo(), + "to reborrow the mutable reference, add `*`", + "*", + Applicability::MaybeIncorrect, + ); + } else if is_deref_coerced { + // We don't have access to the HIR to get accurate spans, but we + // can give a best effort structured suggestion. + err.span_suggestion_verbose( + source_info.span.with_hi(source_info.span.lo() + BytePos(5)), + "if there is only one mutable reborrow, remove the `&mut`", + "", + Applicability::MaybeIncorrect, + ); + } } else { // This can occur with things like `(&mut self).foo()`. err.span_help(source_info.span, "try removing `&mut` here"); @@ -1695,7 +1752,7 @@ fn suggest_ampmut<'tcx>( && let Either::Left(rhs_stmt_new) = body.stmt_at(*assign) && let StatementKind::Assign(box (_, rvalue_new)) = &rhs_stmt_new.kind && let rhs_span_new = rhs_stmt_new.source_info.span - && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span) + && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span_new) { (rvalue, rhs_span, rhs_str) = (rvalue_new, rhs_span_new, rhs_str_new); } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 17f1988a17c4..35f6e26159dc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,7 +1,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; @@ -27,16 +27,15 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; -use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; +use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::nll::ConstraintDescription; -use crate::region_infer::values::RegionElement; use crate::region_infer::{BlameConstraint, TypeTest}; use crate::session_diagnostics::{ FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr, LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{MirBorrowckCtxt, borrowck_errors, fluent_generated as fluent}; +use crate::{MirBorrowckCtxt, borrowck_errors}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -104,15 +103,9 @@ pub(crate) enum RegionErrorKind<'tcx> { /// A generic bound failure for a type test (`T: 'a`). TypeTestError { type_test: TypeTest<'tcx> }, - /// Higher-ranked subtyping error. - BoundUniversalRegionError { - /// The placeholder free region. - longer_fr: RegionVid, - /// The region element that erroneously must be outlived by `longer_fr`. - error_element: RegionElement<'tcx>, - /// The placeholder region. - placeholder: ty::PlaceholderRegion<'tcx>, - }, + /// 'p outlives 'r, which does not hold. 'p is always a placeholder + /// and 'r is some other region. + PlaceholderOutlivesIllegalRegion { longer_fr: RegionVid, illegally_outlived_r: RegionVid }, /// Any other lifetime error. RegionError { @@ -265,7 +258,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; - diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); + diag.span_note(*trait_span, LIMITATION_NOTE); let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local()) else { return; @@ -298,7 +291,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - fluent::borrowck_restrict_to_static, + msg!("consider restricting the type parameter to the `'static` lifetime"), suggestions, Applicability::MaybeIncorrect, ); @@ -360,28 +353,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - RegionErrorKind::BoundUniversalRegionError { + RegionErrorKind::PlaceholderOutlivesIllegalRegion { longer_fr, - placeholder, - error_element, + illegally_outlived_r, } => { - let error_vid = self.regioncx.region_from_element(longer_fr, &error_element); - - // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let cause = self - .regioncx - .best_blame_constraint( - longer_fr, - NllRegionVariableOrigin::Placeholder(placeholder), - error_vid, - ) - .0 - .cause; - - let universe = placeholder.universe; - let universe_info = self.regioncx.universe_info(universe); - - universe_info.report_erroneous_element(self, placeholder, error_element, cause); + self.report_erroneous_rvid_reaches_placeholder(longer_fr, illegally_outlived_r) } RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { @@ -412,6 +388,43 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { outlives_suggestion.add_suggestion(self); } + /// Report that `longer_fr: error_vid`, which doesn't hold, + /// where `longer_fr` is a placeholder. + fn report_erroneous_rvid_reaches_placeholder( + &mut self, + longer_fr: RegionVid, + error_vid: RegionVid, + ) { + use NllRegionVariableOrigin::*; + + let origin_longer = self.regioncx.definitions[longer_fr].origin; + + let Placeholder(placeholder) = origin_longer else { + bug!("Expected {longer_fr:?} to come from placeholder!"); + }; + + // FIXME: Is throwing away the existential region really the best here? + let error_region = match self.regioncx.definitions[error_vid].origin { + FreeRegion | Existential { .. } => None, + Placeholder(other_placeholder) => Some(other_placeholder), + }; + + // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. + let cause = + self.regioncx.best_blame_constraint(longer_fr, origin_longer, error_vid).0.cause; + + // FIXME these methods should have better names, and also probably not be this generic. + // FIXME note that we *throw away* the error element here! We probably want to + // thread it through the computation further down and use it, but there currently isn't + // anything there to receive it. + self.regioncx.universe_info(placeholder.universe).report_erroneous_element( + self, + placeholder, + error_region, + cause, + ); + } + /// Report an error because the universal region `fr` was required to outlive /// `outlived_fr` but it is not known to do so. For example: /// @@ -872,6 +885,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { for alias_ty in alias_tys { if alias_ty.span.desugaring_kind().is_some() { // Skip `async` desugaring `impl Future`. + continue; } if let TyKind::TraitObject(_, lt) = alias_ty.kind { if lt.kind == hir::LifetimeKind::ImplicitObjectLifetimeDefault { @@ -966,12 +980,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label(*span, fluent::borrowck_implicit_static); - multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced); + multi_span.push_span_label( + *span, + msg!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + ident.span, + msg!("calling this method introduces the `impl`'s `'static` requirement"), + ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - fluent::borrowck_implicit_static_relax, + msg!("consider relaxing the implicit `'static` requirement"), " + '_", Applicability::MaybeIncorrect, ); @@ -1134,7 +1154,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(), - fluent::borrowck_dereference_suggestion, + msg!("dereference the return value"), "*".repeat(count), Applicability::MachineApplicable, ); @@ -1178,7 +1198,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - fluent::borrowck_move_closure_suggestion, + msg!("consider adding 'move' keyword before the nested closure"), "move ", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4a059481c326..2e6c1dceef98 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,8 +2,9 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] +#![feature(default_field_values)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(negative_impls)] @@ -62,10 +63,10 @@ use crate::diagnostics::{ use crate::path_utils::*; use crate::place_ext::PlaceExt; use crate::places_conflict::{PlaceConflictBias, places_conflict}; +use crate::polonius::PoloniusContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, }; -use crate::polonius::{PoloniusContext, PoloniusDiagnosticsContext}; use crate::prefixes::PrefixSet; use crate::region_infer::RegionInferenceContext; use crate::region_infer::opaque_types::DeferredOpaqueTypeError; @@ -98,8 +99,6 @@ mod used_muts; /// A public API provided for the Rust compiler consumers. pub mod consumers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Associate some local constants with the `'tcx` lifetime struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); @@ -122,6 +121,11 @@ fn mir_borrowck( let (input_body, _) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); + // We should eagerly check stalled coroutine obligations from HIR typeck. + // Not doing so leads to silent normalization failures later, which will + // fail to register opaque types in the next solver. + tcx.check_coroutine_obligations(def)?; + let input_body: &Body<'_> = &input_body.borrow(); if let Some(guar) = input_body.tainted_by_errors { debug!("Skipping borrowck because of tainted body"); @@ -420,7 +424,7 @@ fn borrowck_check_region_constraints<'tcx>( polonius_output, opt_closure_req, nll_errors, - polonius_diagnostics, + polonius_context, } = nll::compute_regions( root_cx, &infcx, @@ -444,7 +448,7 @@ fn borrowck_check_region_constraints<'tcx>( ®ioncx, &opt_closure_req, &borrow_set, - polonius_diagnostics.as_ref(), + polonius_context.as_ref(), ); // We also have a `#[rustc_regions]` annotation that causes us to dump @@ -486,7 +490,7 @@ fn borrowck_check_region_constraints<'tcx>( polonius_output: None, move_errors: Vec::new(), diags_buffer, - polonius_diagnostics: polonius_diagnostics.as_ref(), + polonius_context: polonius_context.as_ref(), }; struct MoveVisitor<'a, 'b, 'infcx, 'tcx> { ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, @@ -525,7 +529,7 @@ fn borrowck_check_region_constraints<'tcx>( move_errors: Vec::new(), diags_buffer, polonius_output: polonius_output.as_deref(), - polonius_diagnostics: polonius_diagnostics.as_ref(), + polonius_context: polonius_context.as_ref(), }; // Compute and report region errors, if any. @@ -775,7 +779,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option<&'a PoloniusOutput>, /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics. - polonius_diagnostics: Option<&'a PoloniusDiagnosticsContext>, + polonius_context: Option<&'a PoloniusContext>, } // Check that: @@ -1206,6 +1210,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { "access_place: suppressing error place_span=`{:?}` kind=`{:?}`", place_span, kind ); + + // If the place is being mutated, then mark it as such anyway in order to suppress the + // `unused_mut` lint, which is likely incorrect once the access place error has been + // resolved. + if rw == ReadOrWrite::Write(WriteKind::Mutate) + && let Ok(root_place) = + self.is_mutable(place_span.0.as_ref(), is_local_mutation_allowed) + { + self.add_used_mut(root_place, state); + } + return; } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 64e3b59acfff..acd01be47070 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -7,6 +7,8 @@ use std::str::FromStr; use polonius_engine::{Algorithm, AllFacts, Output}; use rustc_data_structures::frozen::Frozen; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; @@ -15,17 +17,16 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; -use rustc_span::sym; use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::RustcFacts; use crate::diagnostics::RegionErrors; use crate::handle_placeholders::compute_sccs_applying_placeholder_outlives_constraints; +use crate::polonius::PoloniusContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, }; -use crate::polonius::{PoloniusContext, PoloniusDiagnosticsContext}; use crate::region_infer::RegionInferenceContext; use crate::type_check::MirTypeckRegionConstraints; use crate::type_check::free_region_relations::UniversalRegionRelations; @@ -46,7 +47,7 @@ pub(crate) struct NllOutput<'tcx> { /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics, e.g. /// localized typeck and liveness constraints. - pub polonius_diagnostics: Option, + pub polonius_context: Option, } /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal @@ -121,7 +122,7 @@ pub(crate) fn compute_regions<'tcx>( universal_region_relations: Frozen>, constraints: MirTypeckRegionConstraints<'tcx>, mut polonius_facts: Option>, - polonius_context: Option, + mut polonius_context: Option, ) -> NllOutput<'tcx> { let polonius_output = root_cx.consumer.as_ref().map_or(false, |c| c.polonius_output()) || infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled(); @@ -153,9 +154,9 @@ pub(crate) fn compute_regions<'tcx>( // If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives constraints // and use them to compute loan liveness. - let polonius_diagnostics = polonius_context.map(|polonius_context| { - polonius_context.compute_loan_liveness(infcx.tcx, &mut regioncx, body, borrow_set) - }); + if let Some(polonius_context) = polonius_context.as_mut() { + polonius_context.compute_loan_liveness(&mut regioncx, body, borrow_set) + } // If requested: dump NLL facts, and run legacy polonius analysis. let polonius_output = polonius_facts.as_ref().and_then(|polonius_facts| { @@ -188,7 +189,7 @@ pub(crate) fn compute_regions<'tcx>( polonius_output, opt_closure_req: closure_region_requirements, nll_errors, - polonius_diagnostics, + polonius_context, } } @@ -230,13 +231,13 @@ pub(super) fn dump_nll_mir<'tcx>( dumper.dump_mir(body); // Also dump the region constraint graph as a graphviz file. - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("regioncx.all.dot", body)?; regioncx.dump_graphviz_raw_constraints(tcx, &mut file)?; }; // Also dump the region constraint SCC graph as a graphviz file. - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("regioncx.scc.dot", body)?; regioncx.dump_graphviz_scc_constraints(tcx, &mut file)?; }; @@ -295,7 +296,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); - if !tcx.has_attr(base_def_id, sym::rustc_regions) { + if !find_attr!(tcx.get_all_attrs(base_def_id), AttributeKind::RustcRegions) { return; } diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 525957578595..559b1bdc38d8 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,6 +1,19 @@ +use std::collections::BTreeMap; + +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_index::interval::SparseIntervalMatrix; +use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::RegionVid; use rustc_mir_dataflow::points::PointIndex; +use crate::BorrowSet; +use crate::constraints::OutlivesConstraint; +use crate::dataflow::BorrowIndex; +use crate::polonius::ConstraintDirection; +use crate::region_infer::values::LivenessValues; +use crate::type_check::Locations; +use crate::universal_regions::UniversalRegions; + /// A localized outlives constraint reifies the CFG location where the outlives constraint holds, /// within the origins themselves as if they were different from point to point: from `a: b` /// outlives constraints to `a@p: b@p`, where `p` is the point in the CFG. @@ -12,32 +25,300 @@ use rustc_mir_dataflow::points::PointIndex; /// of `q`. These depend on the liveness of the regions at these points, as well as their /// variance. /// -/// The `source` origin at `from` flows into the `target` origin at `to`. -/// /// This dual of NLL's [crate::constraints::OutlivesConstraint] therefore encodes the /// position-dependent outlives constraints used by Polonius, to model the flow-sensitive loan /// propagation via reachability within a graph of localized constraints. -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub(crate) struct LocalizedOutlivesConstraint { - pub source: RegionVid, - pub from: PointIndex, - pub target: RegionVid, - pub to: PointIndex, +/// +/// That `LocalizedConstraintGraph` can create these edges on-demand during traversal, and we +/// therefore model them as a pair of `LocalizedNode` vertices. +/// +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub(super) struct LocalizedNode { + pub region: RegionVid, + pub point: PointIndex, } -/// A container of [LocalizedOutlivesConstraint]s that can be turned into a traversable -/// `rustc_data_structures` graph. -#[derive(Clone, Default, Debug)] -pub(crate) struct LocalizedOutlivesConstraintSet { - pub outlives: Vec, +/// The localized constraint graph indexes the physical and logical edges to lazily compute a given +/// node's successors during traversal. +pub(super) struct LocalizedConstraintGraph { + /// The actual, physical, edges we have recorded for a given node. We localize them on-demand + /// when traversing from the node to the successor region. + edges: FxHashMap>, + + /// The logical edges representing the outlives constraints that hold at all points in the CFG, + /// which we don't localize to avoid creating a lot of unnecessary edges in the graph. Some CFGs + /// can be big, and we don't need to create such a physical edge for every point in the CFG. + logical_edges: FxHashMap>, } -impl LocalizedOutlivesConstraintSet { - pub(crate) fn push(&mut self, constraint: LocalizedOutlivesConstraint) { - if constraint.source == constraint.target && constraint.from == constraint.to { - // 'a@p: 'a@p is pretty uninteresting - return; - } - self.outlives.push(constraint); +/// The visitor interface when traversing a `LocalizedConstraintGraph`. +pub(super) trait LocalizedConstraintGraphVisitor { + /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't + /// visited before. + fn on_node_traversed(&mut self, _loan: BorrowIndex, _node: LocalizedNode) {} + + /// Callback called when discovering a new `successor` node for the `current_node`. + fn on_successor_discovered(&mut self, _current_node: LocalizedNode, _successor: LocalizedNode) { + } +} + +impl LocalizedConstraintGraph { + /// Traverses the constraints and returns the indexed graph of edges per node. + pub(super) fn new<'tcx>( + liveness: &LivenessValues, + outlives_constraints: impl Iterator>, + ) -> Self { + let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); + let mut logical_edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); + + for outlives_constraint in outlives_constraints { + match outlives_constraint.locations { + Locations::All(_) => { + logical_edges + .entry(outlives_constraint.sup) + .or_default() + .insert(outlives_constraint.sub); + } + + Locations::Single(location) => { + let node = LocalizedNode { + region: outlives_constraint.sup, + point: liveness.point_from_location(location), + }; + edges.entry(node).or_default().insert(outlives_constraint.sub); + } + } + } + + LocalizedConstraintGraph { edges, logical_edges } + } + + /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered + /// nodes and successors. + pub(super) fn traverse<'tcx>( + &self, + body: &Body<'tcx>, + liveness: &LivenessValues, + live_region_variances: &BTreeMap, + universal_regions: &UniversalRegions<'tcx>, + borrow_set: &BorrowSet<'tcx>, + visitor: &mut impl LocalizedConstraintGraphVisitor, + ) { + let live_regions = liveness.points(); + + let mut visited = FxHashSet::default(); + let mut stack = Vec::new(); + + // Compute reachability per loan by traversing each loan's subgraph starting from where it + // is introduced. + for (loan_idx, loan) in borrow_set.iter_enumerated() { + visited.clear(); + stack.clear(); + + let start_node = LocalizedNode { + region: loan.region, + point: liveness.point_from_location(loan.reserve_location), + }; + stack.push(start_node); + + while let Some(node) = stack.pop() { + if !visited.insert(node) { + continue; + } + + // We've reached a node we haven't visited before. + let location = liveness.location_from_point(node.point); + visitor.on_node_traversed(loan_idx, node); + + // When we find a _new_ successor, we'd like to + // - visit it eventually, + // - and let the generic visitor know about it. + let mut successor_found = |succ| { + if !visited.contains(&succ) { + stack.push(succ); + visitor.on_successor_discovered(node, succ); + } + }; + + // Then, we propagate the loan along the localized constraint graph. The outgoing + // edges are computed lazily, from: + // - the various physical edges present at this node, + // - the materialized logical edges that exist virtually at all points for this + // node's region, localized at this point. + + // Universal regions propagate loans along the CFG, i.e. forwards only. + let is_universal_region = universal_regions.is_universal_region(node.region); + + // The physical edges present at this node are: + // + // 1. the typeck edges that flow from region to region *at this point*. + for &succ in self.edges.get(&node).into_iter().flatten() { + let succ = LocalizedNode { region: succ, point: node.point }; + successor_found(succ); + } + + // 2a. the liveness edges that flow *forward*, from this node's point to its + // successors in the CFG. + if body[location.block].statements.get(location.statement_index).is_some() { + // Intra-block edges, straight line constraints from each point to its successor + // within the same block. + let next_point = node.point + 1; + if let Some(succ) = compute_forward_successor( + node.region, + next_point, + live_regions, + live_region_variances, + is_universal_region, + ) { + successor_found(succ); + } + } else { + // Inter-block edges, from the block's terminator to each successor block's + // entry point. + for successor_block in body[location.block].terminator().successors() { + let next_location = Location { block: successor_block, statement_index: 0 }; + let next_point = liveness.point_from_location(next_location); + if let Some(succ) = compute_forward_successor( + node.region, + next_point, + live_regions, + live_region_variances, + is_universal_region, + ) { + successor_found(succ); + } + } + } + + // 2b. the liveness edges that flow *backward*, from this node's point to its + // predecessors in the CFG. + if !is_universal_region { + if location.statement_index > 0 { + // Backward edges to the predecessor point in the same block. + let previous_point = PointIndex::from(node.point.as_usize() - 1); + if let Some(succ) = compute_backward_successor( + node.region, + node.point, + previous_point, + live_regions, + live_region_variances, + ) { + successor_found(succ); + } + } else { + // Backward edges from the block entry point to the terminator of the + // predecessor blocks. + let predecessors = body.basic_blocks.predecessors(); + for &pred_block in &predecessors[location.block] { + let previous_location = Location { + block: pred_block, + statement_index: body[pred_block].statements.len(), + }; + let previous_point = liveness.point_from_location(previous_location); + if let Some(succ) = compute_backward_successor( + node.region, + node.point, + previous_point, + live_regions, + live_region_variances, + ) { + successor_found(succ); + } + } + } + } + + // And finally, we have the logical edges, materialized at this point. + for &logical_succ in self.logical_edges.get(&node.region).into_iter().flatten() { + let succ = LocalizedNode { region: logical_succ, point: node.point }; + successor_found(succ); + } + } + } + } +} + +/// Returns the successor for the current region/point node when propagating a loan through forward +/// edges, if applicable, according to liveness and variance. +fn compute_forward_successor( + region: RegionVid, + next_point: PointIndex, + live_regions: &SparseIntervalMatrix, + live_region_variances: &BTreeMap, + is_universal_region: bool, +) -> Option { + // 1. Universal regions are semantically live at all points. + if is_universal_region { + let succ = LocalizedNode { region, point: next_point }; + return Some(succ); + } + + // 2. Otherwise, gather the edges due to explicit region liveness, when applicable. + if !live_regions.contains(region, next_point) { + return None; + } + + // Here, `region` could be live at the current point, and is live at the next point: add a + // constraint between them, according to variance. + + // Note: there currently are cases related to promoted and const generics, where we don't yet + // have variance information (possibly about temporary regions created when typeck sanitizes the + // promoteds). Until that is done, we conservatively fallback to maximizing reachability by + // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus + // propagate liveness when needed. + // + // FIXME: add the missing variance information and remove this fallback bidirectional edge. + let direction = + live_region_variances.get(®ion).unwrap_or(&ConstraintDirection::Bidirectional); + + match direction { + ConstraintDirection::Backward => { + // Contravariant cases: loans flow in the inverse direction, but we're only interested + // in forward successors and there are none here. + None + } + ConstraintDirection::Forward | ConstraintDirection::Bidirectional => { + // 1. For covariant cases: loans flow in the regular direction, from the current point + // to the next point. + // 2. For invariant cases, loans can flow in both directions, but here as well, we only + // want the forward path of the bidirectional edge. + Some(LocalizedNode { region, point: next_point }) + } + } +} + +/// Returns the successor for the current region/point node when propagating a loan through backward +/// edges, if applicable, according to liveness and variance. +fn compute_backward_successor( + region: RegionVid, + current_point: PointIndex, + previous_point: PointIndex, + live_regions: &SparseIntervalMatrix, + live_region_variances: &BTreeMap, +) -> Option { + // Liveness flows into the regions live at the next point. So, in a backwards view, we'll link + // the region from the current point, if it's live there, to the previous point. + if !live_regions.contains(region, current_point) { + return None; + } + + // FIXME: add the missing variance information and remove this fallback bidirectional edge. See + // the same comment in `compute_forward_successor`. + let direction = + live_region_variances.get(®ion).unwrap_or(&ConstraintDirection::Bidirectional); + + match direction { + ConstraintDirection::Forward => { + // Covariant cases: loans flow in the regular direction, but we're only interested in + // backward successors and there are none here. + None + } + ConstraintDirection::Backward | ConstraintDirection::Bidirectional => { + // 1. For contravariant cases: loans flow in the inverse direction, from the current + // point to the previous point. + // 2. For invariant cases, loans can flow in both directions, but here as well, we only + // want the backward path of the bidirectional edge. + Some(LocalizedNode { region, point: previous_point }) + } } } diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 62f9ae173474..af50f68640f8 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -10,9 +10,7 @@ use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; use crate::constraints::OutlivesConstraint; -use crate::polonius::{ - LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet, PoloniusDiagnosticsContext, -}; +use crate::polonius::{LocalizedConstraintGraphVisitor, LocalizedNode, PoloniusContext}; use crate::region_infer::values::LivenessValues; use crate::type_check::Locations; use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext}; @@ -24,7 +22,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, borrow_set: &BorrowSet<'tcx>, - polonius_diagnostics: Option<&PoloniusDiagnosticsContext>, + polonius_context: Option<&PoloniusContext>, ) { let tcx = infcx.tcx; if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { @@ -33,8 +31,22 @@ pub(crate) fn dump_polonius_mir<'tcx>( let Some(dumper) = MirDumper::new(tcx, "polonius", body) else { return }; - let polonius_diagnostics = - polonius_diagnostics.expect("missing diagnostics context with `-Zpolonius=next`"); + let polonius_context = + polonius_context.expect("missing polonius context with `-Zpolonius=next`"); + + // If we have a polonius graph to dump along the rest of the MIR and NLL info, we extract its + // constraints here. + let mut collector = LocalizedOutlivesConstraintCollector { constraints: Vec::new() }; + if let Some(graph) = &polonius_context.graph { + graph.traverse( + body, + regioncx.liveness_constraints(), + &polonius_context.live_region_variances, + regioncx.universal_regions(), + borrow_set, + &mut collector, + ); + } let extra_data = &|pass_where, out: &mut dyn io::Write| { emit_polonius_mir( @@ -42,7 +54,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( regioncx, closure_region_requirements, borrow_set, - &polonius_diagnostics.localized_outlives_constraints, + &collector.constraints, pass_where, out, ) @@ -58,19 +70,36 @@ pub(crate) fn dump_polonius_mir<'tcx>( let dumper = dumper.set_extra_data(extra_data).set_options(options); - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("html", body)?; - emit_polonius_dump( - &dumper, - body, - regioncx, - borrow_set, - &polonius_diagnostics.localized_outlives_constraints, - &mut file, - )?; + emit_polonius_dump(&dumper, body, regioncx, borrow_set, &collector.constraints, &mut file)?; }; } +/// The constraints we'll dump as text or a mermaid graph. +struct LocalizedOutlivesConstraint { + source: RegionVid, + from: PointIndex, + target: RegionVid, + to: PointIndex, +} + +/// Visitor to record constraints encountered when traversing the localized constraint graph. +struct LocalizedOutlivesConstraintCollector { + constraints: Vec, +} + +impl LocalizedConstraintGraphVisitor for LocalizedOutlivesConstraintCollector { + fn on_successor_discovered(&mut self, current_node: LocalizedNode, successor: LocalizedNode) { + self.constraints.push(LocalizedOutlivesConstraint { + source: current_node.region, + from: current_node.point, + target: successor.region, + to: successor.point, + }); + } +} + /// The polonius dump consists of: /// - the NLL MIR /// - the list of polonius localized constraints @@ -82,7 +111,7 @@ fn emit_polonius_dump<'tcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, borrow_set: &BorrowSet<'tcx>, - localized_outlives_constraints: &LocalizedOutlivesConstraintSet, + localized_outlives_constraints: &[LocalizedOutlivesConstraint], out: &mut dyn io::Write, ) -> io::Result<()> { // Prepare the HTML dump file prologue. @@ -193,7 +222,7 @@ fn emit_polonius_mir<'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, borrow_set: &BorrowSet<'tcx>, - localized_outlives_constraints: &LocalizedOutlivesConstraintSet, + localized_outlives_constraints: &[LocalizedOutlivesConstraint], pass_where: PassWhere, out: &mut dyn io::Write, ) -> io::Result<()> { @@ -212,10 +241,10 @@ fn emit_polonius_mir<'tcx>( // Add localized outlives constraints match pass_where { PassWhere::BeforeCFG => { - if localized_outlives_constraints.outlives.len() > 0 { + if localized_outlives_constraints.len() > 0 { writeln!(out, "| Localized constraints")?; - for constraint in &localized_outlives_constraints.outlives { + for constraint in localized_outlives_constraints { let LocalizedOutlivesConstraint { source, from, target, to } = constraint; let from = liveness.location_from_point(*from); let to = liveness.location_from_point(*to); @@ -399,7 +428,7 @@ fn emit_mermaid_nll_sccs<'tcx>( fn emit_mermaid_constraint_graph<'tcx>( borrow_set: &BorrowSet<'tcx>, liveness: &LivenessValues, - localized_outlives_constraints: &LocalizedOutlivesConstraintSet, + localized_outlives_constraints: &[LocalizedOutlivesConstraint], out: &mut dyn io::Write, ) -> io::Result { let location_name = |location: Location| { @@ -438,7 +467,7 @@ fn emit_mermaid_constraint_graph<'tcx>( // The regions subgraphs containing the region/point nodes. let mut points_per_region: FxIndexMap> = FxIndexMap::default(); - for constraint in &localized_outlives_constraints.outlives { + for constraint in localized_outlives_constraints { points_per_region.entry(constraint.source).or_default().insert(constraint.from); points_per_region.entry(constraint.target).or_default().insert(constraint.to); } @@ -451,7 +480,7 @@ fn emit_mermaid_constraint_graph<'tcx>( } // The constraint graph edges. - for constraint in &localized_outlives_constraints.outlives { + for constraint in localized_outlives_constraints { // FIXME: add killed loans and constraint kind as edge labels. writeln!( out, @@ -463,6 +492,6 @@ fn emit_mermaid_constraint_graph<'tcx>( // Return the number of edges: this is the biggest graph in the dump and its edge count will be // mermaid's max edge count to support. - let edge_count = borrow_set.len() + localized_outlives_constraints.outlives.len(); + let edge_count = borrow_set.len() + localized_outlives_constraints.len(); Ok(edge_count) } diff --git a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs index f1338b3bf1ee..b6f8b4a79f39 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs @@ -1,22 +1,15 @@ use std::collections::BTreeMap; use rustc_hir::def_id::DefId; -use rustc_index::bit_set::SparseBitMatrix; -use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::relate::{ self, Relate, RelateResult, TypeRelation, relate_args_with_variances, }; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeVisitable}; -use rustc_mir_dataflow::points::PointIndex; -use super::{ - ConstraintDirection, LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet, - PoloniusLivenessContext, -}; -use crate::region_infer::values::LivenessValues; +use super::{ConstraintDirection, PoloniusContext}; use crate::universal_regions::UniversalRegions; -impl PoloniusLivenessContext { +impl PoloniusContext { /// Record the variance of each region contained within the given value. pub(crate) fn record_live_region_variance<'tcx>( &mut self, @@ -34,165 +27,6 @@ impl PoloniusLivenessContext { } } -/// Propagate loans throughout the CFG: for each statement in the MIR, create localized outlives -/// constraints for loans that are propagated to the next statements. -pub(super) fn create_liveness_constraints<'tcx>( - body: &Body<'tcx>, - liveness: &LivenessValues, - live_regions: &SparseBitMatrix, - live_region_variances: &BTreeMap, - universal_regions: &UniversalRegions<'tcx>, - localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, -) { - for (block, bb) in body.basic_blocks.iter_enumerated() { - let statement_count = bb.statements.len(); - for statement_index in 0..=statement_count { - let current_location = Location { block, statement_index }; - let current_point = liveness.point_from_location(current_location); - - if statement_index < statement_count { - // Intra-block edges, straight line constraints from each point to its successor - // within the same block. - let next_location = Location { block, statement_index: statement_index + 1 }; - let next_point = liveness.point_from_location(next_location); - propagate_loans_between_points( - current_point, - next_point, - live_regions, - live_region_variances, - universal_regions, - localized_outlives_constraints, - ); - } else { - // Inter-block edges, from the block's terminator to each successor block's entry - // point. - for successor_block in bb.terminator().successors() { - let next_location = Location { block: successor_block, statement_index: 0 }; - let next_point = liveness.point_from_location(next_location); - propagate_loans_between_points( - current_point, - next_point, - live_regions, - live_region_variances, - universal_regions, - localized_outlives_constraints, - ); - } - } - } - } -} - -/// Propagate loans within a region between two points in the CFG, if that region is live at both -/// the source and target points. -fn propagate_loans_between_points( - current_point: PointIndex, - next_point: PointIndex, - live_regions: &SparseBitMatrix, - live_region_variances: &BTreeMap, - universal_regions: &UniversalRegions<'_>, - localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, -) { - // Universal regions are semantically live at all points. - // Note: we always have universal regions but they're not always (or often) involved in the - // subset graph. For now, we emit all their edges unconditionally, but some of these subgraphs - // will be disconnected from the rest of the graph and thus, unnecessary. - // - // FIXME: only emit the edges of universal regions that existential regions can reach. - for region in universal_regions.universal_regions_iter() { - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: region, - from: current_point, - target: region, - to: next_point, - }); - } - - let Some(next_live_regions) = live_regions.row(next_point) else { - // There are no constraints to add: there are no live regions at the next point. - return; - }; - - for region in next_live_regions.iter() { - // `region` could be live at the current point, and is live at the next point: add a - // constraint between them, according to variance. - if let Some(&direction) = live_region_variances.get(®ion) { - add_liveness_constraint( - region, - current_point, - next_point, - direction, - localized_outlives_constraints, - ); - } else { - // Note: there currently are cases related to promoted and const generics, where we - // don't yet have variance information (possibly about temporary regions created when - // typeck sanitizes the promoteds). Until that is done, we conservatively fallback to - // maximizing reachability by adding a bidirectional edge here. This will not limit - // traversal whatsoever, and thus propagate liveness when needed. - // - // FIXME: add the missing variance information and remove this fallback bidirectional - // edge. - let fallback = ConstraintDirection::Bidirectional; - add_liveness_constraint( - region, - current_point, - next_point, - fallback, - localized_outlives_constraints, - ); - } - } -} - -/// Adds `LocalizedOutlivesConstraint`s between two connected points, according to the given edge -/// direction. -fn add_liveness_constraint( - region: RegionVid, - current_point: PointIndex, - next_point: PointIndex, - direction: ConstraintDirection, - localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, -) { - match direction { - ConstraintDirection::Forward => { - // Covariant cases: loans flow in the regular direction, from the current point to the - // next point. - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: region, - from: current_point, - target: region, - to: next_point, - }); - } - ConstraintDirection::Backward => { - // Contravariant cases: loans flow in the inverse direction, from the next point to the - // current point. - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: region, - from: next_point, - target: region, - to: current_point, - }); - } - ConstraintDirection::Bidirectional => { - // For invariant cases, loans can flow in both directions: we add both edges. - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: region, - from: current_point, - target: region, - to: next_point, - }); - localized_outlives_constraints.push(LocalizedOutlivesConstraint { - source: region, - from: next_point, - target: region, - to: current_point, - }); - } - } -} - /// Extracts variances for regions contained within types. Follows the same structure as /// `rustc_infer`'s `Generalizer`: we try to relate a type with itself to track and extract the /// variances of regions. diff --git a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs deleted file mode 100644 index bdc3047e5ba0..000000000000 --- a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs +++ /dev/null @@ -1,160 +0,0 @@ -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_middle::ty::RegionVid; -use rustc_mir_dataflow::points::PointIndex; - -use super::{LiveLoans, LocalizedOutlivesConstraintSet}; -use crate::BorrowSet; -use crate::constraints::OutlivesConstraint; -use crate::region_infer::values::LivenessValues; -use crate::type_check::Locations; - -/// Compute loan reachability to approximately trace loan liveness throughout the CFG, by -/// traversing the full graph of constraints that combines: -/// - the localized constraints (the physical edges), -/// - with the constraints that hold at all points (the logical edges). -pub(super) fn compute_loan_liveness<'tcx>( - liveness: &LivenessValues, - outlives_constraints: impl Iterator>, - borrow_set: &BorrowSet<'tcx>, - localized_outlives_constraints: &LocalizedOutlivesConstraintSet, -) -> LiveLoans { - let mut live_loans = LiveLoans::new(borrow_set.len()); - - // Create the full graph with the physical edges we've localized earlier, and the logical edges - // of constraints that hold at all points. - let logical_constraints = - outlives_constraints.filter(|c| matches!(c.locations, Locations::All(_))); - let graph = LocalizedConstraintGraph::new(&localized_outlives_constraints, logical_constraints); - let mut visited = FxHashSet::default(); - let mut stack = Vec::new(); - - // Compute reachability per loan by traversing each loan's subgraph starting from where it is - // introduced. - for (loan_idx, loan) in borrow_set.iter_enumerated() { - visited.clear(); - stack.clear(); - - let start_node = LocalizedNode { - region: loan.region, - point: liveness.point_from_location(loan.reserve_location), - }; - stack.push(start_node); - - while let Some(node) = stack.pop() { - if !visited.insert(node) { - continue; - } - - // Record the loan as being live on entry to this point if it reaches a live region - // there. - // - // This is an approximation of liveness (which is the thing we want), in that we're - // using a single notion of reachability to represent what used to be _two_ different - // transitive closures. It didn't seem impactful when coming up with the single-graph - // and reachability through space (regions) + time (CFG) concepts, but in practice the - // combination of time-traveling with kills is more impactful than initially - // anticipated. - // - // Kills should prevent a loan from reaching its successor points in the CFG, but not - // while time-traveling: we're not actually at that CFG point, but looking for - // predecessor regions that contain the loan. One of the two TCs we had pushed the - // transitive subset edges to each point instead of having backward edges, and the - // problem didn't exist before. In the abstract, naive reachability is not enough to - // model this, we'd need a slightly different solution. For example, maybe with a - // two-step traversal: - // - at each point we first traverse the subgraph (and possibly time-travel) looking for - // exit nodes while ignoring kills, - // - and then when we're back at the current point, we continue normally. - // - // Another (less annoying) subtlety is that kills and the loan use-map are - // flow-insensitive. Kills can actually appear in places before a loan is introduced, or - // at a location that is actually unreachable in the CFG from the introduction point, - // and these can also be encountered during time-traveling. - // - // The simplest change that made sense to "fix" the issues above is taking into - // account kills that are: - // - reachable from the introduction point - // - encountered during forward traversal. Note that this is not transitive like the - // two-step traversal described above: only kills encountered on exit via a backward - // edge are ignored. - // - // This version of the analysis, however, is enough in practice to pass the tests that - // we care about and NLLs reject, without regressions on crater, and is an actionable - // subset of the full analysis. It also naturally points to areas of improvement that we - // wish to explore later, namely handling kills appropriately during traversal, instead - // of continuing traversal to all the reachable nodes. - // - // FIXME: analyze potential unsoundness, possibly in concert with a borrowck - // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples. - - if liveness.is_live_at(node.region, liveness.location_from_point(node.point)) { - live_loans.insert(node.point, loan_idx); - } - - for succ in graph.outgoing_edges(node) { - stack.push(succ); - } - } - } - - live_loans -} - -/// The localized constraint graph indexes the physical and logical edges to compute a given node's -/// successors during traversal. -struct LocalizedConstraintGraph { - /// The actual, physical, edges we have recorded for a given node. - edges: FxHashMap>, - - /// The logical edges representing the outlives constraints that hold at all points in the CFG, - /// which we don't localize to avoid creating a lot of unnecessary edges in the graph. Some CFGs - /// can be big, and we don't need to create such a physical edge for every point in the CFG. - logical_edges: FxHashMap>, -} - -/// A node in the graph to be traversed, one of the two vertices of a localized outlives constraint. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -struct LocalizedNode { - region: RegionVid, - point: PointIndex, -} - -impl LocalizedConstraintGraph { - /// Traverses the constraints and returns the indexed graph of edges per node. - fn new<'tcx>( - constraints: &LocalizedOutlivesConstraintSet, - logical_constraints: impl Iterator>, - ) -> Self { - let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); - for constraint in &constraints.outlives { - let source = LocalizedNode { region: constraint.source, point: constraint.from }; - let target = LocalizedNode { region: constraint.target, point: constraint.to }; - edges.entry(source).or_default().insert(target); - } - - let mut logical_edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); - for constraint in logical_constraints { - logical_edges.entry(constraint.sup).or_default().insert(constraint.sub); - } - - LocalizedConstraintGraph { edges, logical_edges } - } - - /// Returns the outgoing edges of a given node, not its transitive closure. - fn outgoing_edges(&self, node: LocalizedNode) -> impl Iterator { - // The outgoing edges are: - // - the physical edges present at this node, - // - the materialized logical edges that exist virtually at all points for this node's - // region, localized at this point. - let physical_edges = - self.edges.get(&node).into_iter().flat_map(|targets| targets.iter().copied()); - let materialized_edges = - self.logical_edges.get(&node.region).into_iter().flat_map(move |targets| { - targets - .iter() - .copied() - .map(move |target| LocalizedNode { point: node.point, region: target }) - }); - physical_edges.chain(materialized_edges) - } -} diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index a9092b1981e1..45108bfcb79b 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -32,47 +32,37 @@ //! - //! - //! -//! -//! Data flows like this: -//! 1) during MIR typeck, record liveness data needed later: live region variances, as well as the -//! usual NLL liveness data (just computed on more locals). That's the [PoloniusLivenessContext]. -//! 2) once that is done, variance data is transferred, and the NLL region liveness is converted to -//! the polonius shape. That's the main [PoloniusContext]. -//! 3) during region inference, that data and the NLL outlives constraints are used to create the -//! localized outlives constraints, as described above. That's the [PoloniusDiagnosticsContext]. -//! 4) transfer this back to the main borrowck procedure: it handles computing errors and -//! diagnostics, debugging and MIR dumping concerns. mod constraints; mod dump; pub(crate) mod legacy; mod liveness_constraints; -mod loan_liveness; -mod typeck_constraints; use std::collections::BTreeMap; use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::SparseBitMatrix; -use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::mir::{Body, Local}; -use rustc_middle::ty::{RegionVid, TyCtxt}; +use rustc_middle::ty::RegionVid; use rustc_mir_dataflow::points::PointIndex; -pub(crate) use self::constraints::*; +pub(self) use self::constraints::*; pub(crate) use self::dump::dump_polonius_mir; -use self::liveness_constraints::create_liveness_constraints; -use self::loan_liveness::compute_loan_liveness; -use self::typeck_constraints::convert_typeck_constraints; use crate::dataflow::BorrowIndex; +use crate::region_infer::values::LivenessValues; use crate::{BorrowSet, RegionInferenceContext}; pub(crate) type LiveLoans = SparseBitMatrix; -/// This struct holds the liveness data created during MIR typeck, and which will be used later in -/// the process, to compute the polonius localized constraints. +/// This struct holds the necessary +/// - liveness data, created during MIR typeck, and which will be used to lazily compute the +/// polonius localized constraints, during NLL region inference as well as MIR dumping, +/// - data needed by the borrowck error computation and diagnostics. #[derive(Default)] -pub(crate) struct PoloniusLivenessContext { +pub(crate) struct PoloniusContext { + /// The graph from which we extract the localized outlives constraints. + graph: Option, + /// The expected edge direction per live region: the kind of directed edge we'll create as /// liveness constraints depends on the variance of types with respect to each contained region. live_region_variances: BTreeMap, @@ -84,27 +74,6 @@ pub(crate) struct PoloniusLivenessContext { pub(crate) boring_nll_locals: FxHashSet, } -/// This struct holds the data needed to create the Polonius localized constraints. Its data is -/// transferred and converted from the [PoloniusLivenessContext] at the end of MIR typeck. -pub(crate) struct PoloniusContext { - /// The liveness data we recorded during MIR typeck. - liveness_context: PoloniusLivenessContext, - - /// The set of regions that are live at a given point in the CFG, used to create localized - /// outlives constraints between regions that are live at connected points in the CFG. - live_regions: SparseBitMatrix, -} - -/// This struct holds the data needed by the borrowck error computation and diagnostics. Its data is -/// computed from the [PoloniusContext] when computing NLL regions. -pub(crate) struct PoloniusDiagnosticsContext { - /// The localized outlives constraints that were computed in the main analysis. - localized_outlives_constraints: LocalizedOutlivesConstraintSet, - - /// The liveness data computed during MIR typeck: [PoloniusLivenessContext::boring_nll_locals]. - pub(crate) boring_nll_locals: FxHashSet, -} - /// The direction a constraint can flow into. Used to create liveness constraints according to /// variance. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -120,26 +89,6 @@ enum ConstraintDirection { } impl PoloniusContext { - /// Unlike NLLs, in polonius we traverse the cfg to look for regions live across an edge, so we - /// need to transpose the "points where each region is live" matrix to a "live regions per point" - /// matrix. - // FIXME: avoid this conversion by always storing liveness data in this shape in the rest of - // borrowck. - pub(crate) fn create_from_liveness( - liveness_context: PoloniusLivenessContext, - num_regions: usize, - points_per_live_region: &SparseIntervalMatrix, - ) -> PoloniusContext { - let mut live_regions_per_point = SparseBitMatrix::new(num_regions); - for region in points_per_live_region.rows() { - for point in points_per_live_region.row(region).unwrap().iter() { - live_regions_per_point.insert(point, region); - } - } - - PoloniusContext { live_regions: live_regions_per_point, liveness_context } - } - /// Computes live loans using the set of loans model for `-Zpolonius=next`. /// /// First, creates a constraint graph combining regions and CFG points, by: @@ -151,44 +100,90 @@ impl PoloniusContext { /// /// The constraint data will be used to compute errors and diagnostics. pub(crate) fn compute_loan_liveness<'tcx>( - self, - tcx: TyCtxt<'tcx>, + &mut self, regioncx: &mut RegionInferenceContext<'tcx>, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, - ) -> PoloniusDiagnosticsContext { - let PoloniusLivenessContext { live_region_variances, boring_nll_locals } = - self.liveness_context; + ) { + let liveness = regioncx.liveness_constraints(); - let mut localized_outlives_constraints = LocalizedOutlivesConstraintSet::default(); - convert_typeck_constraints( - tcx, - body, - regioncx.liveness_constraints(), - regioncx.outlives_constraints(), - regioncx.universal_regions(), - &mut localized_outlives_constraints, - ); + // We don't need to prepare the graph (index NLL constraints, etc.) if we have no loans to + // trace throughout localized constraints. + if borrow_set.len() > 0 { + // From the outlives constraints, liveness, and variances, we can compute reachability + // on the lazy localized constraint graph to trace the liveness of loans, for the next + // step in the chain (the NLL loan scope and active loans computations). + let graph = LocalizedConstraintGraph::new(liveness, regioncx.outlives_constraints()); - create_liveness_constraints( - body, - regioncx.liveness_constraints(), - &self.live_regions, - &live_region_variances, - regioncx.universal_regions(), - &mut localized_outlives_constraints, - ); + let mut live_loans = LiveLoans::new(borrow_set.len()); + let mut visitor = LoanLivenessVisitor { liveness, live_loans: &mut live_loans }; + graph.traverse( + body, + liveness, + &self.live_region_variances, + regioncx.universal_regions(), + borrow_set, + &mut visitor, + ); + regioncx.record_live_loans(live_loans); - // Now that we have a complete graph, we can compute reachability to trace the liveness of - // loans for the next step in the chain, the NLL loan scope and active loans computations. - let live_loans = compute_loan_liveness( - regioncx.liveness_constraints(), - regioncx.outlives_constraints(), - borrow_set, - &localized_outlives_constraints, - ); - regioncx.record_live_loans(live_loans); - - PoloniusDiagnosticsContext { localized_outlives_constraints, boring_nll_locals } + // The graph can be traversed again during MIR dumping, so we store it here. + self.graph = Some(graph); + } + } +} + +/// Visitor to record loan liveness when traversing the localized constraint graph. +struct LoanLivenessVisitor<'a> { + liveness: &'a LivenessValues, + live_loans: &'a mut LiveLoans, +} + +impl LocalizedConstraintGraphVisitor for LoanLivenessVisitor<'_> { + fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode) { + // Record the loan as being live on entry to this point if it reaches a live region + // there. + // + // This is an approximation of liveness (which is the thing we want), in that we're + // using a single notion of reachability to represent what used to be _two_ different + // transitive closures. It didn't seem impactful when coming up with the single-graph + // and reachability through space (regions) + time (CFG) concepts, but in practice the + // combination of time-traveling with kills is more impactful than initially + // anticipated. + // + // Kills should prevent a loan from reaching its successor points in the CFG, but not + // while time-traveling: we're not actually at that CFG point, but looking for + // predecessor regions that contain the loan. One of the two TCs we had pushed the + // transitive subset edges to each point instead of having backward edges, and the + // problem didn't exist before. In the abstract, naive reachability is not enough to + // model this, we'd need a slightly different solution. For example, maybe with a + // two-step traversal: + // - at each point we first traverse the subgraph (and possibly time-travel) looking for + // exit nodes while ignoring kills, + // - and then when we're back at the current point, we continue normally. + // + // Another (less annoying) subtlety is that kills and the loan use-map are + // flow-insensitive. Kills can actually appear in places before a loan is introduced, or + // at a location that is actually unreachable in the CFG from the introduction point, + // and these can also be encountered during time-traveling. + // + // The simplest change that made sense to "fix" the issues above is taking into account + // kills that are: + // - reachable from the introduction point + // - encountered during forward traversal. Note that this is not transitive like the + // two-step traversal described above: only kills encountered on exit via a backward + // edge are ignored. + // + // This version of the analysis, however, is enough in practice to pass the tests that + // we care about and NLLs reject, without regressions on crater, and is an actionable + // subset of the full analysis. It also naturally points to areas of improvement that we + // wish to explore later, namely handling kills appropriately during traversal, instead + // of continuing traversal to all the reachable nodes. + // + // FIXME: analyze potential unsoundness, possibly in concert with a borrowck + // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples. + if self.liveness.is_live_at_point(node.region, node.point) { + self.live_loans.insert(node.point, loan); + } } } diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs deleted file mode 100644 index cfe9376fb502..000000000000 --- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs +++ /dev/null @@ -1,208 +0,0 @@ -use rustc_data_structures::fx::FxHashSet; -use rustc_middle::mir::{Body, Location, Statement, StatementKind, Terminator, TerminatorKind}; -use rustc_middle::ty::{TyCtxt, TypeVisitable}; -use rustc_mir_dataflow::points::PointIndex; - -use super::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; -use crate::constraints::OutlivesConstraint; -use crate::region_infer::values::LivenessValues; -use crate::type_check::Locations; -use crate::universal_regions::UniversalRegions; - -/// Propagate loans throughout the subset graph at a given point (with some subtleties around the -/// location where effects start to be visible). -pub(super) fn convert_typeck_constraints<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - liveness: &LivenessValues, - outlives_constraints: impl Iterator>, - universal_regions: &UniversalRegions<'tcx>, - localized_outlives_constraints: &mut LocalizedOutlivesConstraintSet, -) { - for outlives_constraint in outlives_constraints { - match outlives_constraint.locations { - Locations::All(_) => { - // We don't turn constraints holding at all points into physical edges at every - // point in the graph. They are encoded into *traversal* instead: a given node's - // successors will combine these logical edges with the regular, physical, localized - // edges. - continue; - } - - Locations::Single(location) => { - // This constraint is marked as holding at one location, we localize it to that - // location or its successor, depending on the corresponding MIR - // statement/terminator. Unfortunately, they all show up from typeck as coming "on - // entry", so for now we modify them to take effects that should apply "on exit" - // into account. - // - // FIXME: this approach is subtle, complicated, and hard to test, so we should track - // this information better in MIR typeck instead, for example with a new `Locations` - // variant that contains which node is crossing over between entry and exit. - let point = liveness.point_from_location(location); - let localized_constraint = if let Some(stmt) = - body[location.block].statements.get(location.statement_index) - { - localize_statement_constraint( - tcx, - stmt, - &outlives_constraint, - point, - universal_regions, - ) - } else { - assert_eq!(location.statement_index, body[location.block].statements.len()); - let terminator = body[location.block].terminator(); - localize_terminator_constraint( - tcx, - body, - terminator, - liveness, - &outlives_constraint, - point, - universal_regions, - ) - }; - localized_outlives_constraints.push(localized_constraint); - } - } - } -} - -/// For a given outlives constraint arising from a MIR statement, localize the constraint with the -/// needed CFG `from`-`to` intra-block nodes. -fn localize_statement_constraint<'tcx>( - tcx: TyCtxt<'tcx>, - stmt: &Statement<'tcx>, - outlives_constraint: &OutlivesConstraint<'tcx>, - current_point: PointIndex, - universal_regions: &UniversalRegions<'tcx>, -) -> LocalizedOutlivesConstraint { - match &stmt.kind { - StatementKind::Assign(box (lhs, rhs)) => { - // To create localized outlives constraints without midpoints, we rely on the property - // that no input regions from the RHS of the assignment will flow into themselves: they - // should not appear in the output regions in the LHS. We believe this to be true by - // construction of the MIR, via temporaries, and assert it here. - // - // We think we don't need midpoints because: - // - every LHS Place has a unique set of regions that don't appear elsewhere - // - this implies that for them to be part of the RHS, the same Place must be read and - // written - // - and that should be impossible in MIR - // - // When we have a more complete implementation in the future, tested with crater, etc, - // we can remove this assertion. It's a debug assert because it can be expensive. - debug_assert!( - { - let mut lhs_regions = FxHashSet::default(); - tcx.for_each_free_region(lhs, |region| { - let region = universal_regions.to_region_vid(region); - lhs_regions.insert(region); - }); - - let mut rhs_regions = FxHashSet::default(); - tcx.for_each_free_region(rhs, |region| { - let region = universal_regions.to_region_vid(region); - rhs_regions.insert(region); - }); - - // The intersection between LHS and RHS regions should be empty. - lhs_regions.is_disjoint(&rhs_regions) - }, - "there should be no common regions between the LHS and RHS of an assignment" - ); - } - _ => { - // Assignments should be the only statement that can both generate constraints that - // apply on entry (specific to the RHS place) *and* others that only apply on exit (the - // subset of RHS regions that actually flow into the LHS): i.e., where midpoints would - // be used to ensure the former happen before the latter, within the same MIR Location. - } - } - - // We generally localize an outlives constraint to where it arises. - LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from: current_point, - target: outlives_constraint.sub, - to: current_point, - } -} - -/// For a given outlives constraint arising from a MIR terminator, localize the constraint with the -/// needed CFG `from`-`to` inter-block nodes. -fn localize_terminator_constraint<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - terminator: &Terminator<'tcx>, - liveness: &LivenessValues, - outlives_constraint: &OutlivesConstraint<'tcx>, - current_point: PointIndex, - universal_regions: &UniversalRegions<'tcx>, -) -> LocalizedOutlivesConstraint { - // FIXME: check if other terminators need the same handling as `Call`s, in particular - // Assert/Yield/Drop. - match &terminator.kind { - // FIXME: also handle diverging calls. - TerminatorKind::Call { destination, target: Some(target), .. } => { - // If there is a target for the call we also relate what flows into the destination here - // to entry to that successor. - let destination_ty = destination.ty(&body.local_decls, tcx); - let successor_location = Location { block: *target, statement_index: 0 }; - let successor_point = liveness.point_from_location(successor_location); - compute_constraint_direction( - tcx, - outlives_constraint, - &destination_ty, - current_point, - successor_point, - universal_regions, - ) - } - _ => { - // Typeck constraints guide loans between regions at the current point, so we do that in - // the general case, and liveness will take care of making them flow to the terminator's - // successors. - LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from: current_point, - target: outlives_constraint.sub, - to: current_point, - } - } - } -} - -/// For a given outlives constraint and CFG edge, returns the localized constraint with the -/// appropriate `from`-`to` direction. This is computed according to whether the constraint flows to -/// or from a free region in the given `value`, some kind of result for an effectful operation, like -/// the LHS of an assignment. -fn compute_constraint_direction<'tcx>( - tcx: TyCtxt<'tcx>, - outlives_constraint: &OutlivesConstraint<'tcx>, - value: &impl TypeVisitable>, - current_point: PointIndex, - successor_point: PointIndex, - universal_regions: &UniversalRegions<'tcx>, -) -> LocalizedOutlivesConstraint { - let mut to = current_point; - let mut from = current_point; - tcx.for_each_free_region(value, |region| { - let region = universal_regions.to_region_vid(region); - if region == outlives_constraint.sub { - // This constraint flows into the result, its effects start becoming visible on exit. - to = successor_point; - } else if region == outlives_constraint.sup { - // This constraint flows from the result, its effects start becoming visible on exit. - from = successor_point; - } - }); - - LocalizedOutlivesConstraint { - source: outlives_constraint.sup, - from, - target: outlives_constraint.sub, - to, - } -} diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 526e1850c2ef..ceb33d82deba 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -52,7 +52,7 @@ fn render_region_vid<'tcx>( format!(" (for<{}>)", tcx.item_name(def_id)) } ty::BoundRegionKind::ClosureEnv | ty::BoundRegionKind::Anon => " (for<'_>)".to_string(), - ty::BoundRegionKind::NamedAnon(_) => { + ty::BoundRegionKind::NamedForPrinting(_) => { bug!("only used for pretty printing") } }, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 6ed70b39c5b7..5cdda777723b 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1379,11 +1379,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { .elements_contained_in(longer_fr_scc) .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) { + let illegally_outlived_r = self.region_from_element(longer_fr, &error_element); // Stop after the first error, it gets too noisy otherwise, and does not provide more information. - errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { + errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion { longer_fr, - error_element, - placeholder, + illegally_outlived_r, }); } else { debug!("check_bound_universal_region: all bounds satisfied"); @@ -1572,7 +1572,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Get the region outlived by `longer_fr` and live at `element`. - pub(crate) fn region_from_element( + fn region_from_element( &self, longer_fr: RegionVid, element: &RegionElement<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 0c4a82f3d2f3..23ad964c7cd9 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -24,13 +24,13 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use tracing::{debug, instrument}; use super::reverse_sccs::ReverseSccGraph; -use crate::BorrowckInferCtxt; use crate::consumers::RegionInferenceContext; use crate::session_diagnostics::LifetimeMismatchOpaqueParam; use crate::type_check::canonical::fully_perform_op_raw; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::type_check::{Locations, MirTypeckRegionConstraints}; use crate::universal_regions::{RegionClassification, UniversalRegions}; +use crate::{BorrowckInferCtxt, CollectRegionConstraintsResult}; mod member_constraints; mod region_ctxt; @@ -126,6 +126,31 @@ fn nll_var_to_universal_region<'tcx>( } } +/// Record info needed to report the same name error later. +#[derive(Copy, Clone, Debug)] +pub(crate) struct UnexpectedHiddenRegion<'tcx> { + // The def_id of the body where this error occurs. + // Needed to handle region vars with their corresponding `infcx`. + def_id: LocalDefId, + opaque_type_key: OpaqueTypeKey<'tcx>, + hidden_type: ProvisionalHiddenType<'tcx>, + member_region: Region<'tcx>, +} + +impl<'tcx> UnexpectedHiddenRegion<'tcx> { + pub(crate) fn to_error(self) -> (LocalDefId, DeferredOpaqueTypeError<'tcx>) { + let UnexpectedHiddenRegion { def_id, opaque_type_key, hidden_type, member_region } = self; + ( + def_id, + DeferredOpaqueTypeError::UnexpectedHiddenRegion { + opaque_type_key, + hidden_type, + member_region, + }, + ) + } +} + /// Collect all defining uses of opaque types inside of this typeck root. This /// expects the hidden type to be mapped to the definition parameters of the opaque /// and errors if we end up with distinct hidden types. @@ -176,11 +201,13 @@ struct DefiningUse<'tcx> { /// It also means that this whole function is not really soundness critical as we /// recheck all uses of the opaques regardless. pub(crate) fn compute_definition_site_hidden_types<'tcx>( + def_id: LocalDefId, infcx: &BorrowckInferCtxt<'tcx>, universal_region_relations: &Frozen>, constraints: &MirTypeckRegionConstraints<'tcx>, location_map: Rc, hidden_types: &mut FxIndexMap>, + unconstrained_hidden_type_errors: &mut Vec>, opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)], ) -> Vec> { let mut errors = Vec::new(); @@ -204,8 +231,10 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>( // up equal to one of their choice regions and compute the actual hidden type of // the opaque type definition. This is stored in the `root_cx`. compute_definition_site_hidden_types_from_defining_uses( + def_id, &rcx, hidden_types, + unconstrained_hidden_type_errors, &defining_uses, &mut errors, ); @@ -274,8 +303,10 @@ fn collect_defining_uses<'tcx>( #[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))] fn compute_definition_site_hidden_types_from_defining_uses<'tcx>( + def_id: LocalDefId, rcx: &RegionCtxt<'_, 'tcx>, hidden_types: &mut FxIndexMap>, + unconstrained_hidden_type_errors: &mut Vec>, defining_uses: &[DefiningUse<'tcx>], errors: &mut Vec>, ) { @@ -293,16 +324,29 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>( Ok(hidden_type) => hidden_type, Err(r) => { debug!("UnexpectedHiddenRegion: {:?}", r); - errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion { - hidden_type, - opaque_type_key, - member_region: ty::Region::new_var(tcx, r), - }); - let guar = tcx.dcx().span_delayed_bug( - hidden_type.span, - "opaque type with non-universal region args", - ); - ty::ProvisionalHiddenType::new_error(tcx, guar) + // If we're using the next solver, the unconstrained region may be resolved by a + // fully defining use from another body. + // So we don't generate error eagerly here. + if rcx.infcx.tcx.use_typing_mode_borrowck() { + unconstrained_hidden_type_errors.push(UnexpectedHiddenRegion { + def_id, + hidden_type, + opaque_type_key, + member_region: ty::Region::new_var(tcx, r), + }); + continue; + } else { + errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion { + hidden_type, + opaque_type_key, + member_region: ty::Region::new_var(tcx, r), + }); + let guar = tcx.dcx().span_delayed_bug( + hidden_type.span, + "opaque type with non-universal region args", + ); + ty::ProvisionalHiddenType::new_error(tcx, guar) + } } }; @@ -570,6 +614,40 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>( errors } +/// We handle `UnexpectedHiddenRegion` error lazily in the next solver as +/// there may be a fully defining use in another body. +/// +/// In case such a defining use does not exist, we register an error here. +pub(crate) fn handle_unconstrained_hidden_type_errors<'tcx>( + tcx: TyCtxt<'tcx>, + hidden_types: &mut FxIndexMap>, + unconstrained_hidden_type_errors: &mut Vec>, + collect_region_constraints_results: &mut FxIndexMap< + LocalDefId, + CollectRegionConstraintsResult<'tcx>, + >, +) { + let mut unconstrained_hidden_type_errors = std::mem::take(unconstrained_hidden_type_errors); + unconstrained_hidden_type_errors + .retain(|unconstrained| !hidden_types.contains_key(&unconstrained.opaque_type_key.def_id)); + + unconstrained_hidden_type_errors.iter().for_each(|t| { + tcx.dcx() + .span_delayed_bug(t.hidden_type.span, "opaque type with non-universal region args"); + }); + + // `UnexpectedHiddenRegion` error contains region var which only makes sense in the + // corresponding `infcx`. + // So we need to insert the error to the body where it originates from. + for error in unconstrained_hidden_type_errors { + let (def_id, error) = error.to_error(); + let Some(result) = collect_region_constraints_results.get_mut(&def_id) else { + unreachable!("the body should depend on opaques type if it has opaque use"); + }; + result.deferred_opaque_type_errors.push(error); + } +} + /// In theory `apply_definition_site_hidden_types` could introduce new uses of opaque types. /// We do not check these new uses so this could be unsound. /// diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 0063af25d781..c1fed1260340 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -10,8 +10,8 @@ use rustc_middle::ty::{self, RegionVid}; use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use tracing::debug; +use crate::BorrowIndex; use crate::polonius::LiveLoans; -use crate::{BorrowIndex, TyCtxt}; rustc_index::newtype_index! { /// A single integer representing a `ty::Placeholder`. @@ -131,9 +131,17 @@ impl LivenessValues { } } - /// Returns whether `region` is marked live at the given `location`. + /// Returns whether `region` is marked live at the given + /// [`location`][rustc_middle::mir::Location]. pub(crate) fn is_live_at(&self, region: RegionVid, location: Location) -> bool { let point = self.location_map.point_from_location(location); + self.is_live_at_point(region, point) + } + + /// Returns whether `region` is marked live at the given + /// [`point`][rustc_mir_dataflow::points::PointIndex]. + #[inline] + pub(crate) fn is_live_at_point(&self, region: RegionVid, point: PointIndex) -> bool { if let Some(points) = &self.points { points.row(region).is_some_and(|r| r.contains(point)) } else { @@ -420,18 +428,18 @@ impl ToElementIndex<'_> for RegionVid { impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> { fn add_to_row(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool where - Self: Into, ty::BoundRegion>>, + Self: Into>, { - let placeholder: ty::Placeholder, ty::BoundRegion> = self.into(); + let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.insert(row, index) } fn contained_in_row(self, values: &RegionValues<'tcx, N>, row: N) -> bool where - Self: Into, ty::BoundRegion>>, + Self: Into>, { - let placeholder: ty::Placeholder, ty::BoundRegion> = self.into(); + let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.contains(row, index) } diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index 4d42055df168..a082aba35b8a 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -12,8 +12,9 @@ use smallvec::SmallVec; use crate::consumers::BorrowckConsumer; use crate::nll::compute_closure_requirements_modulo_opaques; use crate::region_infer::opaque_types::{ - apply_definition_site_hidden_types, clone_and_resolve_opaque_types, + UnexpectedHiddenRegion, apply_definition_site_hidden_types, clone_and_resolve_opaque_types, compute_definition_site_hidden_types, detect_opaque_types_added_while_handling_opaque_types, + handle_unconstrained_hidden_type_errors, }; use crate::type_check::{Locations, constraint_conversion}; use crate::{ @@ -26,7 +27,12 @@ use crate::{ pub(super) struct BorrowCheckRootCtxt<'tcx> { pub tcx: TyCtxt<'tcx>, root_def_id: LocalDefId, + /// This contains fully resolved hidden types or `ty::Error`. hidden_types: FxIndexMap>, + /// This contains unconstrained regions in hidden types. + /// Only used for deferred error reporting. See + /// [`crate::region_infer::opaque_types::handle_unconstrained_hidden_type_errors`] + unconstrained_hidden_type_errors: Vec>, /// The region constraints computed by [borrowck_collect_region_constraints]. This uses /// an [FxIndexMap] to guarantee that iterating over it visits nested bodies before /// their parents. @@ -49,6 +55,7 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> { tcx, root_def_id, hidden_types: Default::default(), + unconstrained_hidden_type_errors: Default::default(), collect_region_constraints_results: Default::default(), propagated_borrowck_results: Default::default(), tainted_by_errors: None, @@ -84,23 +91,32 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> { fn handle_opaque_type_uses(&mut self) { let mut per_body_info = Vec::new(); - for input in self.collect_region_constraints_results.values_mut() { + for (def_id, input) in &mut self.collect_region_constraints_results { let (num_entries, opaque_types) = clone_and_resolve_opaque_types( &input.infcx, &input.universal_region_relations, &mut input.constraints, ); input.deferred_opaque_type_errors = compute_definition_site_hidden_types( + *def_id, &input.infcx, &input.universal_region_relations, &input.constraints, Rc::clone(&input.location_map), &mut self.hidden_types, + &mut self.unconstrained_hidden_type_errors, &opaque_types, ); per_body_info.push((num_entries, opaque_types)); } + handle_unconstrained_hidden_type_errors( + self.tcx, + &mut self.hidden_types, + &mut self.unconstrained_hidden_type_errors, + &mut self.collect_region_constraints_results, + ); + for (input, (opaque_types_storage_num_entries, opaque_types)) in self.collect_region_constraints_results.values_mut().zip(per_body_info) { diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5143b2fa2059..7bde534dafd2 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -7,16 +7,16 @@ use rustc_span::Span; use crate::diagnostics::RegionName; #[derive(Diagnostic)] -#[diag(borrowck_move_unsized, code = E0161)] +#[diag("cannot move a value of type `{$ty}`", code = E0161)] pub(crate) struct MoveUnsized<'tcx> { pub ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("the size of `{$ty}` cannot be statically determined")] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_lifetime_error)] +#[diag("higher-ranked lifetime error")] pub(crate) struct HigherRankedLifetimeError { #[subdiagnostic] pub cause: Option, @@ -26,21 +26,21 @@ pub(crate) struct HigherRankedLifetimeError { #[derive(Subdiagnostic)] pub(crate) enum HigherRankedErrorCause { - #[note(borrowck_could_not_prove)] + #[note("could not prove `{$predicate}`")] CouldNotProve { predicate: String }, - #[note(borrowck_could_not_normalize)] + #[note("could not normalize `{$value}`")] CouldNotNormalize { value: String }, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_subtype_error)] +#[diag("higher-ranked subtype error")] pub(crate) struct HigherRankedSubtypeError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_generic_does_not_live_long_enough)] +#[diag("`{$kind}` does not live long enough")] pub(crate) struct GenericDoesNotLiveLongEnough { pub kind: String, #[primary_span] @@ -48,15 +48,20 @@ pub(crate) struct GenericDoesNotLiveLongEnough { } #[derive(LintDiagnostic)] -#[diag(borrowck_var_does_not_need_mut)] +#[diag("variable does not need to be mutable")] pub(crate) struct VarNeedNotMut { - #[suggestion(style = "short", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this `mut`", + style = "short", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_var_cannot_escape_closure)] -#[note] -#[note(borrowck_cannot_escape)] +#[diag("captured variable cannot escape `FnMut` closure body")] +#[note("`FnMut` closures only have access to their captured variables while they are executing...")] +#[note("...therefore, they cannot allow references to captured variables to escape")] pub(crate) struct FnMutError { #[primary_span] pub span: Span, @@ -66,17 +71,17 @@ pub(crate) struct FnMutError { #[derive(Subdiagnostic)] pub(crate) enum VarHereDenote { - #[label(borrowck_var_here_captured)] + #[label("variable captured here")] Captured { #[primary_span] span: Span, }, - #[label(borrowck_var_here_defined)] + #[label("variable defined here")] Defined { #[primary_span] span: Span, }, - #[label(borrowck_closure_inferred_mut)] + #[label("inferred to be a `FnMut` closure")] FnMutInferred { #[primary_span] span: Span, @@ -85,17 +90,21 @@ pub(crate) enum VarHereDenote { #[derive(Subdiagnostic)] pub(crate) enum FnMutReturnTypeErr { - #[label(borrowck_returned_closure_escaped)] + #[label( + "returns a closure that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnClosure { #[primary_span] span: Span, }, - #[label(borrowck_returned_async_block_escaped)] + #[label( + "returns an `async` block that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnAsyncBlock { #[primary_span] span: Span, }, - #[label(borrowck_returned_ref_escaped)] + #[label("returns a reference to a captured variable which escapes the closure body")] ReturnRef { #[primary_span] span: Span, @@ -103,7 +112,7 @@ pub(crate) enum FnMutReturnTypeErr { } #[derive(Diagnostic)] -#[diag(borrowck_lifetime_constraints_error)] +#[diag("lifetime may not live long enough")] pub(crate) struct LifetimeOutliveErr { #[primary_span] pub span: Span, @@ -111,7 +120,9 @@ pub(crate) struct LifetimeOutliveErr { #[derive(Subdiagnostic)] pub(crate) enum LifetimeReturnCategoryErr<'a> { - #[label(borrowck_returned_lifetime_wrong)] + #[label( + "{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`" + )] WrongReturn { #[primary_span] span: Span, @@ -119,7 +130,9 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { outlived_fr_name: RegionName, fr_name: &'a RegionName, }, - #[label(borrowck_returned_lifetime_short)] + #[label( + "{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`" + )] ShortReturn { #[primary_span] span: Span, @@ -131,7 +144,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { #[derive(Subdiagnostic)] pub(crate) enum RequireStaticErr { - #[note(borrowck_used_impl_require_static)] + #[note("the used `impl` has a `'static` requirement")] UsedImpl { #[primary_span] multi_span: MultiSpan, @@ -140,42 +153,42 @@ pub(crate) enum RequireStaticErr { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarPathUseCause { - #[label(borrowck_borrow_due_to_use_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_coroutine)] + #[label("use occurs due to use in coroutine")] UseInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_coroutine)] + #[label("assign occurs due to use in coroutine")] AssignInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_coroutine)] + #[label("assign to part occurs due to use in coroutine")] AssignPartInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_borrow_due_to_use_closure)] + #[label("borrow occurs due to use in closure")] BorrowInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_closure)] + #[label("use occurs due to use in closure")] UseInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_closure)] + #[label("assignment occurs due to use in closure")] AssignInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_closure)] + #[label("assignment to part occurs due to use in closure")] AssignPartInClosure { #[primary_span] path_span: Span, @@ -184,17 +197,17 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { - #[label(borrowck_capture_immute)] + #[label("capture is immutable because of use here")] Immut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_mut)] + #[label("capture is mutable because of use here")] Mut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_move)] + #[label("capture is moved because of use here")] Move { #[primary_span] kind_span: Span, @@ -203,77 +216,97 @@ pub(crate) enum CaptureVarKind { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarCause { - #[label(borrowck_var_borrow_by_use_place_in_coroutine)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in coroutine" + )] BorrowUsePlaceCoroutine { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_place_in_closure)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure" + )] BorrowUsePlaceClosure { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_closure)] + #[label("borrow occurs due to use in closure")] BorrowUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_coroutine)] + #[label("move occurs due to use in coroutine")] MoveUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_closure)] + #[label("move occurs due to use in closure")] MoveUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_coroutine)] + #[label("first borrow occurs due to use of {$place} in coroutine")] FirstBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + #[label("first borrow occurs due to use of {$place} in closure")] FirstBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_coroutine)] + #[label("second borrow occurs due to use of {$place} in coroutine")] SecondBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + #[label("second borrow occurs due to use of {$place} in closure")] SecondBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + #[label("mutable borrow occurs due to use of {$place} in closure")] MutableBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_partial_var_move_by_use_in_coroutine)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in coroutine" + )] PartialMoveUseInCoroutine { #[primary_span] var_span: Span, is_partial: bool, }, - #[label(borrowck_partial_var_move_by_use_in_closure)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure" + )] PartialMoveUseInClosure { #[primary_span] var_span: Span, @@ -282,34 +315,57 @@ pub(crate) enum CaptureVarCause { } #[derive(Diagnostic)] -#[diag(borrowck_cannot_move_when_borrowed, code = E0505)] +#[diag("cannot move out of {$place -> + [value] value + *[other] {$place} +} because it is borrowed", code = E0505)] pub(crate) struct MoveBorrow<'a> { pub place: &'a str, pub borrow_place: &'a str, pub value_place: &'a str, #[primary_span] - #[label(borrowck_move_label)] + #[label( + "move out of {$value_place -> + [value] value + *[other] {$value_place} + } occurs here" + )] pub span: Span, - #[label] + #[label( + "borrow of {$borrow_place -> + [value] value + *[other] {$borrow_place} + } occurs here" + )] pub borrow_span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_opaque_type_lifetime_mismatch)] +#[diag("opaque type used twice with different lifetimes")] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { pub arg: GenericArg<'tcx>, pub prev: GenericArg<'tcx>, #[primary_span] - #[label] - #[note] + #[label("lifetime `{$arg}` used here")] + #[note( + "if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types" + )] pub span: Span, - #[label(borrowck_prev_lifetime_label)] + #[label("lifetime `{$prev}` previously used here")] pub prev_span: Span, } #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonLabel<'a> { - #[label(borrowck_moved_due_to_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] Call { #[primary_span] fn_call_span: Span, @@ -317,7 +373,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_usage_in_operator)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to usage in {$is_loop_message -> + [true] operator, in previous iteration of loop + *[false] operator + }" + )] OperatorUse { #[primary_span] fn_call_span: Span, @@ -325,7 +389,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_implicit_into_iter_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this implicit call to {$is_loop_message -> + [true] `.into_iter()`, in previous iteration of loop + *[false] `.into_iter()` + }" + )] ImplicitCall { #[primary_span] fn_call_span: Span, @@ -333,7 +405,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_method_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this method {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] MethodCall { #[primary_span] fn_call_span: Span, @@ -341,7 +421,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_await)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] await, in previous iteration of loop + *[false] await + }" + )] Await { #[primary_span] fn_call_span: Span, @@ -349,7 +437,18 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_value_moved_here)] + #[label( + "value {$is_partial -> + [true] partially moved + *[false] moved + } {$is_move_msg -> + [true] into closure here + *[false] here + }{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {\"\"} + }" + )] MovedHere { #[primary_span] move_span: Span, @@ -357,7 +456,7 @@ pub(crate) enum CaptureReasonLabel<'a> { is_move_msg: bool, is_loop_message: bool, }, - #[label(borrowck_consider_borrow_type_contents)] + #[label("help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents")] BorrowContent { #[primary_span] var_span: Span, @@ -366,22 +465,22 @@ pub(crate) enum CaptureReasonLabel<'a> { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonNote { - #[note(borrowck_moved_a_fn_once_in_call)] + #[note("this value implements `FnOnce`, which causes it to be moved when called")] FnOnceMoveInCall { #[primary_span] var_span: Span, }, - #[note(borrowck_calling_operator_moves)] + #[note("calling this operator moves the value")] UnOpMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_calling_operator_moves_lhs)] + #[note("calling this operator moves the left-hand side")] LhsMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_func_take_self_moved_place)] + #[note("`{$func}` takes ownership of the receiver `self`, which moves {$place_name}")] FuncTakeSelf { func: String, place_name: String, @@ -393,7 +492,7 @@ pub(crate) enum CaptureReasonNote { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonSuggest<'tcx> { #[suggestion( - borrowck_suggest_iterate_over_slice, + "consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop", applicability = "maybe-incorrect", code = "&", style = "verbose" @@ -404,7 +503,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { span: Span, }, #[suggestion( - borrowck_suggest_create_fresh_reborrow, + "consider reborrowing the `Pin` instead of moving it", applicability = "maybe-incorrect", code = ".as_mut()", style = "verbose" @@ -417,13 +516,18 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum CaptureArgLabel { - #[label(borrowck_value_capture_here)] + #[label( + "value captured {$is_within -> + [true] here by coroutine + *[false] here + }" + )] Capture { is_within: bool, #[primary_span] args_span: Span, }, - #[label(borrowck_move_out_place_here)] + #[label("{$place} is moved here")] MoveOutPlace { place: String, #[primary_span] @@ -433,13 +537,17 @@ pub(crate) enum CaptureArgLabel { #[derive(Subdiagnostic)] pub(crate) enum OnClosureNote<'a> { - #[note(borrowck_closure_invoked_twice)] + #[note( + "closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment" + )] InvokedTwice { place_name: &'a str, #[primary_span] span: Span, }, - #[note(borrowck_closure_moved_twice)] + #[note( + "closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment" + )] MovedTwice { place_name: &'a str, #[primary_span] @@ -449,7 +557,12 @@ pub(crate) enum OnClosureNote<'a> { #[derive(Subdiagnostic)] pub(crate) enum TypeNoCopy<'a, 'tcx> { - #[label(borrowck_ty_no_impl_copy)] + #[label( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Label { is_partial_move: bool, ty: Ty<'tcx>, @@ -457,12 +570,24 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[primary_span] span: Span, }, - #[note(borrowck_ty_no_impl_copy)] + #[note( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } #[derive(Diagnostic)] -#[diag(borrowck_simd_intrinsic_arg_const)] +#[diag( + "{$arg -> + [1] 1st + [2] 2nd + [3] 3rd + *[other] {$arg}th + } argument of `{$intrinsic}` is required to be a `const` item" +)] pub(crate) struct SimdIntrinsicArgConst { #[primary_span] pub span: Span, @@ -471,8 +596,8 @@ pub(crate) struct SimdIntrinsicArgConst { } #[derive(LintDiagnostic)] -#[diag(borrowck_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] pub(crate) struct TailExprDropOrder { - #[label] + #[label("this temporary value will be dropped at the end of the block")] pub borrowed: Span, } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index ca1b850f7665..442c37e26ec1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -11,7 +11,7 @@ use tracing::debug; use super::TypeChecker; use crate::constraints::OutlivesConstraintSet; -use crate::polonius::PoloniusLivenessContext; +use crate::polonius::PoloniusContext; use crate::region_infer::values::LivenessValues; use crate::universal_regions::UniversalRegions; @@ -48,7 +48,7 @@ pub(super) fn generate<'tcx>( if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() { let (_, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - typeck.polonius_liveness.as_mut().unwrap().boring_nll_locals = + typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring_locals.into_iter().collect(); free_regions = typeck.universal_regions.universal_regions_iter().collect(); } @@ -63,7 +63,7 @@ pub(super) fn generate<'tcx>( typeck.tcx(), &mut typeck.constraints.liveness_constraints, &typeck.universal_regions, - &mut typeck.polonius_liveness, + &mut typeck.polonius_context, typeck.body, ); } @@ -140,11 +140,11 @@ fn record_regular_live_regions<'tcx>( tcx: TyCtxt<'tcx>, liveness_constraints: &mut LivenessValues, universal_regions: &UniversalRegions<'tcx>, - polonius_liveness: &mut Option, + polonius_context: &mut Option, body: &Body<'tcx>, ) { let mut visitor = - LiveVariablesVisitor { tcx, liveness_constraints, universal_regions, polonius_liveness }; + LiveVariablesVisitor { tcx, liveness_constraints, universal_regions, polonius_context }; for (bb, data) in body.basic_blocks.iter_enumerated() { visitor.visit_basic_block_data(bb, data); } @@ -155,7 +155,7 @@ struct LiveVariablesVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, liveness_constraints: &'a mut LivenessValues, universal_regions: &'a UniversalRegions<'tcx>, - polonius_liveness: &'a mut Option, + polonius_context: &'a mut Option, } impl<'a, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'a, 'tcx> { @@ -207,8 +207,8 @@ impl<'a, 'tcx> LiveVariablesVisitor<'a, 'tcx> { }); // When using `-Zpolonius=next`, we record the variance of each live region. - if let Some(polonius_liveness) = self.polonius_liveness { - polonius_liveness.record_live_region_variance(self.tcx, self.universal_regions, value); + if let Some(polonius_context) = self.polonius_context { + polonius_context.record_live_region_variance(self.tcx, self.universal_regions, value); } } } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 7ac94020de03..840210496eb4 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -622,8 +622,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> { }); // When using `-Zpolonius=next`, we record the variance of each live region. - if let Some(polonius_liveness) = typeck.polonius_liveness.as_mut() { - polonius_liveness.record_live_region_variance( + if let Some(polonius_context) = typeck.polonius_context.as_mut() { + polonius_context.record_live_region_variance( typeck.infcx.tcx, typeck.universal_regions, value, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 676b45e9974c..7d34d7c88e62 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -42,8 +42,8 @@ use tracing::{debug, instrument, trace}; use crate::borrow_set::BorrowSet; use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet}; use crate::diagnostics::UniverseInfo; +use crate::polonius::PoloniusContext; use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable}; -use crate::polonius::{PoloniusContext, PoloniusLivenessContext}; use crate::region_infer::TypeTest; use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices}; use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; @@ -139,8 +139,8 @@ pub(crate) fn type_check<'tcx>( debug!(?normalized_inputs_and_output); - let polonius_liveness = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { - Some(PoloniusLivenessContext::default()) + let polonius_context = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { + Some(PoloniusContext::default()) } else { None }; @@ -162,7 +162,7 @@ pub(crate) fn type_check<'tcx>( borrow_set, constraints: &mut constraints, deferred_closure_requirements: &mut deferred_closure_requirements, - polonius_liveness, + polonius_context, }; typeck.check_user_type_annotations(); @@ -172,14 +172,7 @@ pub(crate) fn type_check<'tcx>( liveness::generate(&mut typeck, &location_map, move_data); - // We're done with typeck, we can finalize the polonius liveness context for region inference. - let polonius_context = typeck.polonius_liveness.take().map(|liveness_context| { - PoloniusContext::create_from_liveness( - liveness_context, - infcx.num_region_vars(), - typeck.constraints.liveness_constraints.points(), - ) - }); + let polonius_context = typeck.polonius_context; // In case type check encountered an error region, we suppress unhelpful extra // errors in by clearing out all outlives bounds that we may end up checking. @@ -238,7 +231,7 @@ struct TypeChecker<'a, 'tcx> { constraints: &'a mut MirTypeckRegionConstraints<'tcx>, deferred_closure_requirements: &'a mut DeferredClosureRequirements<'tcx>, /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints. - polonius_liveness: Option, + polonius_context: Option, } /// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions @@ -775,7 +768,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ty::BoundRegionKind::Anon => sym::anon, ty::BoundRegionKind::Named(def_id) => tcx.item_name(def_id), ty::BoundRegionKind::ClosureEnv => sym::env, - ty::BoundRegionKind::NamedAnon(_) => { + ty::BoundRegionKind::NamedForPrinting(_) => { bug!("only used for pretty printing") } }; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 045507ceb4b4..e2d684e12a81 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -174,7 +174,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { let infcx = self.type_checker.infcx; let mut lazy_universe = None; let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { // The first time this closure is called, create a // new universe for the placeholders we will make // from here out. @@ -191,10 +191,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { placeholder_reg }, - types: &mut |_bound_ty: ty::BoundTy| { + types: &mut |_bound_ty: ty::BoundTy<'tcx>| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_const: ty::BoundConst| { + consts: &mut |_bound_const: ty::BoundConst<'tcx>| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -218,7 +218,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { let infcx = self.type_checker.infcx; let mut reg_map = FxHashMap::default(); let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { if let Some(ex_reg_var) = reg_map.get(&br) { *ex_reg_var } else { @@ -230,10 +230,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { ex_reg_var } }, - types: &mut |_bound_ty: ty::BoundTy| { + types: &mut |_bound_ty: ty::BoundTy<'tcx>| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_const: ty::BoundConst| { + consts: &mut |_bound_const: ty::BoundConst<'tcx>| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -268,7 +268,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { ty::BoundRegionKind::Anon => sym::anon, ty::BoundRegionKind::Named(def_id) => self.type_checker.tcx().item_name(def_id), ty::BoundRegionKind::ClosureEnv => sym::env, - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"), }; if cfg!(debug_assertions) { diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index ce9a3ce3f248..dd84a2c1802d 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -15,7 +15,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl deleted file mode 100644 index f9ffddf79084..000000000000 --- a/compiler/rustc_builtin_macros/messages.ftl +++ /dev/null @@ -1,320 +0,0 @@ -builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function -builtin_macros_alloc_must_statics = allocators must be statics - -builtin_macros_asm_attribute_not_supported = - this attribute is not supported on assembly - -builtin_macros_asm_clobber_abi = clobber_abi -builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs -builtin_macros_asm_clobber_outputs = generic outputs - -builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}` - .label = previously here - .arg = duplicate argument - -builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names - -builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option - -builtin_macros_asm_modifier_invalid = asm template modifier must be a single character - -builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive - -builtin_macros_asm_no_matched_argument_name = there is no argument named `{$name}` - -builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option - -builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided - .label = this option was already provided - .suggestion = remove this option - -builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments - .pos = positional argument - .named = named argument - .explicit = explicit register argument - -builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly` - -builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output - -builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!` - -builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!` - .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly - .suggestion = remove this option - -builtin_macros_assert_missing_comma = unexpected string literal - .suggestion = try adding a comma - -builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument - .label = boolean expression required - -builtin_macros_assert_requires_expression = macro requires an expression as an argument - .suggestion = try removing semicolon - -builtin_macros_autodiff = autodiff must be applied to function -builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode -builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode -builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} -builtin_macros_autodiff_ret_activity = invalid return activity {$act} in {$mode} Mode -builtin_macros_autodiff_ty_activity = {$act} can not be used for this type -builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}` - -builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width} - -builtin_macros_avoid_att_syntax = avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - -builtin_macros_avoid_intel_syntax = avoid using `.intel_syntax`, Intel syntax is the default - -builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s - .label = not applicable here - .label2 = not a `struct`, `enum` or `union` - -builtin_macros_bench_sig = functions used as benches must have signature `fn(&mut Bencher) -> impl Termination` - - -builtin_macros_cannot_derive_union = this trait cannot be derived for unions - -builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments - -builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not - -builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal -builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified -builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified - -builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true - -builtin_macros_cfg_select_unreachable = unreachable predicate - .label = always matches - .label2 = this predicate is never reached - -builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized` - -builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field - -builtin_macros_coerce_pointee_requires_one_generic = `CoercePointee` can only be derived on `struct`s that are generic over at least one type - -builtin_macros_coerce_pointee_requires_one_pointee = exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits - -builtin_macros_coerce_pointee_requires_transparent = `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]` - -builtin_macros_coerce_pointee_too_many_pointees = only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits - .label = here another type parameter is marked as `#[pointee]` - - -builtin_macros_concat_bytes_array = cannot concatenate doubly nested array - .note = byte strings are treated as arrays of bytes - .help = try flattening the array - -builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number - -builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals - .byte_char = try using a byte character - .byte_str = try using a byte string - .c_str = try using a null-terminated byte string - .c_str_note = concatenating C strings is ambiguous about including the '\0' - .number_array = try wrapping the number in an array - -builtin_macros_concat_bytes_missing_literal = expected a byte literal - .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` - -builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8` - -builtin_macros_concat_bytes_oob = numeric literal is out of bounds - -builtin_macros_concat_bytestr = cannot concatenate a byte string literal -builtin_macros_concat_c_str_lit = cannot concatenate a C string literal - -builtin_macros_concat_missing_literal = expected a literal - .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` - -builtin_macros_default_arg = `#[default]` attribute does not accept a value - .suggestion = try using `#[default]` - -builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field - -builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struct with {$multiple_fields -> - [true] multiple fields - *[false] no fields -} - -builtin_macros_derive_from_wrong_target = `#[derive(From)]` used on {$kind} - -builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros - -builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments - .suggestion = remove the arguments - -builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values - .suggestion = remove the value - -builtin_macros_duplicate_macro_attribute = duplicated attribute - -builtin_macros_eii_declaration_expected_list = `#[eii_declaration(...)]` expects a list of one or two elements -builtin_macros_eii_declaration_expected_macro = `#[eii_declaration(...)]` is only valid on macros -builtin_macros_eii_declaration_expected_unsafe = expected this argument to be "unsafe" - .note = the second argument is optional - -builtin_macros_eii_only_once = `#[{$name}]` can only be specified once - .note = specified again here - -builtin_macros_eii_shared_macro_expected_function = `#[{$name}]` is only valid on functions -builtin_macros_eii_shared_macro_expected_max_one_argument = `#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]` -builtin_macros_eii_shared_macro_in_statement_position = `#[{$name}]` can only be used on functions inside a module - .label = `#[{$name}]` is used on this item, which is part of another item's local scope - -builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time - .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead - .cargo_typo = there is a similar Cargo environment variable: `{$suggested_var}` - .custom = use `std::env::var({$var_expr})` to read the variable at run time - -builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Unicode string - -builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments - -builtin_macros_expected_comma_in_list = expected token: `,` - -builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern - -builtin_macros_expected_other = expected operand, {$is_inline_asm -> - [false] options - *[true] clobber_abi, options - }, or additional template string - -builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently - -builtin_macros_format_add_missing_colon = add a colon before the format specifier - -builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}` - .label1 = previously here - .label2 = duplicate argument - -builtin_macros_format_no_arg_named = there is no argument named `{$name}` - .note = did you intend to capture a variable `{$name}` from the surrounding scope? - .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - -builtin_macros_format_pos_mismatch = {$n} positional {$n -> - [one] argument - *[more] arguments - } in format string, but {$desc} - -builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments - .label = positional arguments must be before named arguments - .named_args = named argument - -builtin_macros_format_redundant_args = redundant {$n -> - [one] argument - *[more] arguments - } - .help = {$n -> - [one] the formatting string already captures the binding directly, it doesn't need to be included in the argument list - *[more] the formatting strings already captures the bindings directly, they don't need to be included in the argument list - } - .note = {$n -> - [one] the formatting specifier is referencing the binding already - *[more] the formatting specifiers are referencing the bindings already - } - .suggestion = this can be removed - -builtin_macros_format_remove_raw_ident = remove the `r#` - -builtin_macros_format_reorder_format_parameter = did you mean `{$replacement}`? - -builtin_macros_format_requires_string = requires at least a format string argument - -builtin_macros_format_string_invalid = invalid format string: {$desc} - .label = {$label1} in format string - .note = {$note} - .second_label = {$label} - -builtin_macros_format_unknown_trait = unknown format trait `{$ty}` - .note = the only appropriate formatting traits are: - - ``, which uses the `Display` trait - - `?`, which uses the `Debug` trait - - `e`, which uses the `LowerExp` trait - - `E`, which uses the `UpperExp` trait - - `o`, which uses the `Octal` trait - - `p`, which uses the `Pointer` trait - - `b`, which uses the `Binary` trait - - `x`, which uses the `LowerHex` trait - - `X`, which uses the `UpperHex` trait - .suggestion = use the `{$trait_name}` trait - -builtin_macros_format_unused_arg = {$named -> - [true] named argument - *[false] argument - } never used - -builtin_macros_format_unused_args = multiple unused formatting arguments - .label = multiple missing formatting specifiers - -builtin_macros_format_use_positional = consider using a positional formatting argument instead - -builtin_macros_incomplete_include = include macro expected single expression in source - -builtin_macros_multiple_default_attrs = multiple `#[default]` attributes - .note = only one `#[default]` attribute is needed - .label = `#[default]` used here - .label_again = `#[default]` used again here - .help = try removing {$only_one -> - [true] this - *[false] these - } - -builtin_macros_multiple_defaults = multiple declared defaults - .label = first default - .additional = additional default - .note = only one variant can be default - .suggestion = make `{$ident}` default - -builtin_macros_naked_functions_testing_attribute = - cannot use `#[unsafe(naked)]` with testing attributes - .label = function marked with testing attribute here - .naked_attribute = `#[unsafe(naked)]` is incompatible with testing attributes - -builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]` - .label = this enum needs a unit variant marked with `#[default]` - .suggestion = make this unit variant default by placing `#[default]` on it - -builtin_macros_non_exhaustive_default = default variant must be exhaustive - .label = declared `#[non_exhaustive]` here - .help = consider a manual implementation of `Default` - -builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters - -builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants{$post} - .help = consider a manual implementation of `Default` - -builtin_macros_only_one_argument = {$name} takes 1 argument - -builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` - -builtin_macros_proc_macro_attribute_only_usable_with_crate_type = the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type - -builtin_macros_requires_cfg_pattern = - macro requires a cfg-pattern as an argument - .label = cfg-pattern required - -builtin_macros_source_utils_expected_item = expected item, found `{$token}` - -builtin_macros_takes_no_arguments = {$name} takes no arguments - -builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests - .label = `{$kind}` because of this - -builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items - -builtin_macros_test_runner_invalid = `test_runner` argument must be a path -builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument - -builtin_macros_tests_not_support = building tests with panic=abort is not supported without `-Zpanic_abort_tests` - -builtin_macros_trace_macros = trace_macros! accepts only `true` or `false` - -builtin_macros_unexpected_lit = expected path to a trait, found literal - .label = not a trait - .str_lit = try using `#[derive({$sym})]` - .other = for example, write `#[derive(Debug)]` for `Debug` - -builtin_macros_unnameable_test_items = cannot test inner items diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 12ccc4a6de04..c87f1e41043d 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -43,7 +43,7 @@ pub(crate) fn expand( // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new())); - let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))); + let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))); let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); let const_item = if is_stmt { Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item))) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 2958686f86cd..62a39d957b9c 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -288,6 +288,18 @@ fn expand_preparsed_asm( let msg = "asm template must be a string literal"; let template_sp = template_expr.span; let template_is_mac_call = matches!(template_expr.kind, ast::ExprKind::MacCall(_)); + + // Gets the span inside `template_sp` corresponding to the given range + let span_in_template = |range: std::ops::Range| -> Span { + if template_is_mac_call { + // When the template is a macro call we can't reliably get inner spans + // so just use the entire template span (see ICEs #129503, #131292) + template_sp + } else { + template_sp.from_inner(InnerSpan::new(range.start, range.end)) + } + }; + let ExprToSpannedString { symbol: template_str, style: template_style, @@ -382,13 +394,8 @@ fn expand_preparsed_asm( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let err_sp = if template_is_mac_call { - // If the template is a macro call we can't reliably point to the error's - // span so just use the template's span as the error span (fixes #129503) - template_span - } else { - template_span.from_inner(InnerSpan::new(err.span.start, err.span.end)) - }; + + let err_sp = span_in_template(err.span); let msg = format!("invalid asm template string: {}", err.description); let mut e = ecx.dcx().struct_span_err(err_sp, msg); @@ -397,8 +404,7 @@ fn expand_preparsed_asm( e.note(note); } if let Some((label, span)) = err.secondary_label { - let err_sp = template_span.from_inner(InnerSpan::new(span.start, span.end)); - e.span_label(err_sp, label); + e.span_label(span_in_template(span), label); } let guar = e.emit(); return ExpandResult::Ready(Err(guar)); @@ -477,8 +483,7 @@ fn expand_preparsed_asm( ecx.dcx() .create_err(errors::AsmNoMatchedArgumentName { name: name.to_owned(), - span: template_span - .from_inner(InnerSpan::new(span.start, span.end)), + span: span_in_template(span), }) .emit(); None @@ -490,11 +495,7 @@ fn expand_preparsed_asm( let mut chars = arg.format.ty.chars(); let mut modifier = chars.next(); if chars.next().is_some() { - let span = arg - .format - .ty_span - .map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end))) - .unwrap_or(template_sp); + let span = arg.format.ty_span.map(span_in_template).unwrap_or(template_sp); ecx.dcx().emit_err(errors::AsmModifierInvalid { span }); modifier = None; } diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 8e925cfe09a2..3ebde949b99b 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -13,6 +13,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpa use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; +use rustc_parse::parser::Recovery; use rustc_span::{ErrorGuaranteed, Span, sym}; use crate::errors; @@ -42,7 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result, span: Span, tts: TokenStream) -> Result( ecx.current_expansion.lint_node_id, ) { Ok(mut branches) => { - if let Some((underscore, _, _)) = branches.wildcard { - // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. - for (predicate, _, _) in &branches.unreachable { - let span = match predicate { - CfgSelectPredicate::Wildcard(underscore) => underscore.span, - CfgSelectPredicate::Cfg(cfg) => cfg.span(), - }; - let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; - ecx.dcx().emit_warn(err); - } - } - if let Some((selected_tts, selected_span)) = branches.pop_first_match(|cfg| { matches!(attr::eval_config_entry(&ecx.sess, cfg), EvalConfigResult::True) }) { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index d6fdf088b0d1..8984e51c0844 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -463,44 +463,44 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b> } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_transparent, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`", code = E0802)] struct RequireTransparent { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with at least one field", code = E0802)] struct RequireOneField { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s that are generic over at least one type", code = E0802)] struct RequireOneGeneric { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_pointee, code = E0802)] +#[diag("exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits", code = E0802)] struct RequireOnePointee { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_too_many_pointees, code = E0802)] +#[diag("only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits", code = E0802)] struct TooManyPointees { #[primary_span] one: Span, - #[label] + #[label("here another type parameter is marked as `#[pointee]`")] another: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)] +#[diag("`derive(CoercePointee)` requires `{$name}` to be marked `?Sized`", code = E0802)] struct RequiresMaybeSized { #[primary_span] span: Span, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c2260a459097..3fe5e89ef06d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -540,6 +540,7 @@ impl<'a> TraitDef<'a> { .filter(|a| { a.has_any_name(&[ sym::allow, + sym::expect, sym::warn, sym::deny, sym::forbid, @@ -638,27 +639,27 @@ impl<'a> TraitDef<'a> { GenericParamKind::Type { .. } => { // Extra restrictions on the generics parameters to the // type being derived upon. + let span = param.ident.span.with_ctxt(ctxt); let bounds: Vec<_> = self .additional_bounds .iter() .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) + cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) }) .chain( // Add a bound for the current trait. - self.skip_path_as_bound - .not() - .then(|| cx.trait_bound(trait_path.clone(), self.is_const)), + self.skip_path_as_bound.not().then(|| { + let mut trait_path = trait_path.clone(); + trait_path.span = span; + cx.trait_bound(trait_path, self.is_const) + }), ) .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); Some(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), + p.to_path(cx, span, type_ident, generics), self.is_const, )) } else { @@ -671,7 +672,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + cx.typaram(span, param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { @@ -791,7 +792,8 @@ impl<'a> TraitDef<'a> { .collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params); + let path = + cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let rustc_const_unstable = cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 538f5afae5fc..7b651ed84828 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -232,7 +232,7 @@ fn generate_default_impl( span, underscore, unit, - ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))), + ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))), ) }; diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 0aaa8cf558c4..29ab8ee505d6 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,150 +1,157 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - Subdiagnostic, + Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; #[derive(LintDiagnostic)] -#[diag(builtin_macros_avoid_intel_syntax)] +#[diag("avoid using `.intel_syntax`, Intel syntax is the default")] pub(crate) struct AvoidIntelSyntax; #[derive(LintDiagnostic)] -#[diag(builtin_macros_avoid_att_syntax)] +#[diag("avoid using `.att_syntax`, prefer using `options(att_syntax)` instead")] pub(crate) struct AvoidAttSyntax; #[derive(LintDiagnostic)] -#[diag(builtin_macros_incomplete_include)] +#[diag("include macro expected single expression in source")] pub(crate) struct IncompleteInclude; #[derive(LintDiagnostic)] -#[diag(builtin_macros_unnameable_test_items)] +#[diag("cannot test inner items")] pub(crate) struct UnnameableTestItems; #[derive(LintDiagnostic)] -#[diag(builtin_macros_duplicate_macro_attribute)] +#[diag("duplicated attribute")] pub(crate) struct DuplicateMacroAttribute; #[derive(Diagnostic)] -#[diag(builtin_macros_requires_cfg_pattern)] +#[diag("macro requires a cfg-pattern as an argument")] pub(crate) struct RequiresCfgPattern { #[primary_span] - #[label] + #[label("cfg-pattern required")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_one_cfg_pattern)] +#[diag("expected 1 cfg-pattern")] pub(crate) struct OneCfgPattern { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_alloc_error_must_be_fn)] +#[diag("alloc_error_handler must be a function")] pub(crate) struct AllocErrorMustBeFn { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_requires_boolean)] +#[diag("macro requires a boolean expression as an argument")] pub(crate) struct AssertRequiresBoolean { #[primary_span] - #[label] + #[label("boolean expression required")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_requires_expression)] +#[diag("macro requires an expression as an argument")] pub(crate) struct AssertRequiresExpression { #[primary_span] pub(crate) span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("try removing semicolon", code = "", applicability = "maybe-incorrect")] pub(crate) token: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_missing_comma)] +#[diag("unexpected string literal")] pub(crate) struct AssertMissingComma { #[primary_span] pub(crate) span: Span, - #[suggestion(code = ", ", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "try adding a comma", + code = ", ", + applicability = "maybe-incorrect", + style = "short" + )] pub(crate) comma: Span, } #[derive(Diagnostic)] pub(crate) enum CfgAccessibleInvalid { - #[diag(builtin_macros_cfg_accessible_unspecified_path)] + #[diag("`cfg_accessible` path is not specified")] UnspecifiedPath(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_multiple_paths)] + #[diag("multiple `cfg_accessible` paths are specified")] MultiplePaths(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_literal_path)] + #[diag("`cfg_accessible` path cannot be a literal")] LiteralPath(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_has_args)] + #[diag("`cfg_accessible` path cannot accept arguments")] HasArguments(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_accessible_indeterminate)] +#[diag("cannot determine whether the path is accessible or not")] pub(crate) struct CfgAccessibleIndeterminate { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_missing_literal)] -#[note] +#[diag("expected a literal")] +#[note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`")] pub(crate) struct ConcatMissingLiteral { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytestr)] +#[diag("cannot concatenate a byte string literal")] pub(crate) struct ConcatBytestr { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_c_str_lit)] +#[diag("cannot concatenate a C string literal")] pub(crate) struct ConcatCStrLit { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_export_macro_rules)] +#[diag("cannot export macro_rules! macros from a `proc-macro` crate type currently")] pub(crate) struct ExportMacroRules { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_proc_macro)] +#[diag( + "`proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`" +)] pub(crate) struct ProcMacro { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_trace_macros)] +#[diag("trace_macros! accepts only `true` or `false`")] pub(crate) struct TraceMacros { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_bench_sig)] +#[diag("functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`")] pub(crate) struct BenchSig { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_alloc_must_statics)] +#[diag("allocators must be statics")] pub(crate) struct AllocMustStatics { #[primary_span] pub(crate) span: Span, @@ -155,27 +162,27 @@ pub(crate) use autodiff::*; mod autodiff { use super::*; #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_missing_config)] + #[diag("autodiff requires at least a name and mode")] pub(crate) struct AutoDiffMissingConfig { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_unknown_activity)] + #[diag("did not recognize Activity: `{$act}`")] pub(crate) struct AutoDiffUnknownActivity { #[primary_span] pub(crate) span: Span, pub(crate) act: String, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_ty_activity)] + #[diag("{$act} can not be used for this type")] pub(crate) struct AutoDiffInvalidTypeForActivity { #[primary_span] pub(crate) span: Span, pub(crate) act: String, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_number_activities)] + #[diag("expected {$expected} activities, but found {$found}")] pub(crate) struct AutoDiffInvalidNumberActivities { #[primary_span] pub(crate) span: Span, @@ -183,7 +190,7 @@ mod autodiff { pub(crate) found: usize, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_mode_activity)] + #[diag("{$act} can not be used in {$mode} Mode")] pub(crate) struct AutoDiffInvalidApplicationModeAct { #[primary_span] pub(crate) span: Span, @@ -192,7 +199,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_ret_activity)] + #[diag("invalid return activity {$act} in {$mode} Mode")] pub(crate) struct AutoDiffInvalidRetAct { #[primary_span] pub(crate) span: Span, @@ -201,7 +208,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_width)] + #[diag("autodiff width must fit u32, but is {$width}")] pub(crate) struct AutoDiffInvalidWidth { #[primary_span] pub(crate) span: Span, @@ -209,7 +216,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff)] + #[diag("autodiff must be applied to function")] pub(crate) struct AutoDiffInvalidApplication { #[primary_span] pub(crate) span: Span, @@ -217,21 +224,21 @@ mod autodiff { } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_invalid)] +#[diag("cannot concatenate {$lit_kind} literals")] pub(crate) struct ConcatBytesInvalid { #[primary_span] pub(crate) span: Span, pub(crate) lit_kind: &'static str, #[subdiagnostic] pub(crate) sugg: Option, - #[note(builtin_macros_c_str_note)] + #[note("concatenating C strings is ambiguous about including the '\\0'")] pub(crate) cs_note: Option<()>, } #[derive(Subdiagnostic)] pub(crate) enum ConcatBytesInvalidSuggestion { #[suggestion( - builtin_macros_byte_char, + "try using a byte character", code = "b{snippet}", applicability = "machine-applicable" )] @@ -241,7 +248,7 @@ pub(crate) enum ConcatBytesInvalidSuggestion { snippet: String, }, #[suggestion( - builtin_macros_byte_str, + "try using a byte string", code = "b{snippet}", applicability = "machine-applicable" )] @@ -250,15 +257,19 @@ pub(crate) enum ConcatBytesInvalidSuggestion { span: Span, snippet: String, }, - #[note(builtin_macros_c_str_note)] - #[suggestion(builtin_macros_c_str, code = "{as_bstr}", applicability = "machine-applicable")] + #[note("concatenating C strings is ambiguous about including the '\\0'")] + #[suggestion( + "try using a null-terminated byte string", + code = "{as_bstr}", + applicability = "machine-applicable" + )] CStrLit { #[primary_span] span: Span, as_bstr: String, }, #[suggestion( - builtin_macros_number_array, + "try wrapping the number in an array", code = "[{snippet}]", applicability = "machine-applicable" )] @@ -270,63 +281,65 @@ pub(crate) enum ConcatBytesInvalidSuggestion { } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_oob)] +#[diag("numeric literal is out of bounds")] pub(crate) struct ConcatBytesOob { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_non_u8)] +#[diag("numeric literal is not a `u8`")] pub(crate) struct ConcatBytesNonU8 { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_missing_literal)] -#[note] +#[diag("expected a byte literal")] +#[note( + "only byte literals (like `b\"foo\"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`" +)] pub(crate) struct ConcatBytesMissingLiteral { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_array)] +#[diag("cannot concatenate doubly nested array")] pub(crate) struct ConcatBytesArray { #[primary_span] pub(crate) span: Span, - #[note] - #[help] + #[note("byte strings are treated as arrays of bytes")] + #[help("try flattening the array")] pub(crate) bytestr: bool, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_bad_repeat)] +#[diag("repeat count is not a positive number")] pub(crate) struct ConcatBytesBadRepeat { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_bad_derive_target, code = E0774)] +#[diag("`derive` may only be applied to `struct`s, `enum`s and `union`s", code = E0774)] pub(crate) struct BadDeriveTarget { #[primary_span] - #[label] + #[label("not applicable here")] pub(crate) span: Span, - #[label(builtin_macros_label2)] + #[label("not a `struct`, `enum` or `union`")] pub(crate) item: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_tests_not_support)] +#[diag("building tests with panic=abort is not supported without `-Zpanic_abort_tests`")] pub(crate) struct TestsNotSupport {} #[derive(Diagnostic)] -#[diag(builtin_macros_unexpected_lit, code = E0777)] +#[diag("expected path to a trait, found literal", code = E0777)] pub(crate) struct BadDeriveLit { #[primary_span] - #[label] + #[label("not a trait")] pub(crate) span: Span, #[subdiagnostic] pub help: BadDeriveLitHelp, @@ -334,55 +347,59 @@ pub(crate) struct BadDeriveLit { #[derive(Subdiagnostic)] pub(crate) enum BadDeriveLitHelp { - #[help(builtin_macros_str_lit)] + #[help("try using `#[derive({$sym})]`")] StrLit { sym: Symbol }, - #[help(builtin_macros_other)] + #[help("for example, write `#[derive(Debug)]` for `Debug`")] Other, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_path_args_list)] +#[diag("traits in `#[derive(...)]` don't accept arguments")] pub(crate) struct DerivePathArgsList { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the arguments", code = "", applicability = "machine-applicable")] #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_path_args_value)] +#[diag("traits in `#[derive(...)]` don't accept values")] pub(crate) struct DerivePathArgsValue { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the value", code = "", applicability = "machine-applicable")] #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_no_default_variant, code = E0665)] +#[diag("`#[derive(Default)]` on enum with no `#[default]`", code = E0665)] pub(crate) struct NoDefaultVariant { #[primary_span] pub(crate) span: Span, - #[label] + #[label("this enum needs a unit variant marked with `#[default]`")] pub(crate) item_span: Span, #[subdiagnostic] pub(crate) suggs: Vec, } #[derive(Subdiagnostic)] -#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")] +#[suggestion( + "make this unit variant default by placing `#[default]` on it", + code = "#[default] ", + applicability = "maybe-incorrect" +)] pub(crate) struct NoDefaultVariantSugg { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_multiple_defaults)] -#[note] +#[diag("multiple declared defaults")] +#[note("only one variant can be default")] pub(crate) struct MultipleDefaults { #[primary_span] pub(crate) span: Span, - #[label] + #[label("first default")] pub(crate) first: Span, - #[label(builtin_macros_additional)] + #[label("additional default")] pub additional: Vec, #[subdiagnostic] pub suggs: Vec, @@ -390,7 +407,7 @@ pub(crate) struct MultipleDefaults { #[derive(Subdiagnostic)] #[multipart_suggestion( - builtin_macros_suggestion, + "make `{$ident}` default", applicability = "maybe-incorrect", style = "tool-only" )] @@ -401,8 +418,8 @@ pub(crate) struct MultipleDefaultsSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_unit_default)] -#[help] +#[diag("the `#[default]` attribute may only be used on unit enum variants{$post}")] +#[help("consider a manual implementation of `Default`")] pub(crate) struct NonUnitDefault { #[primary_span] pub(crate) span: Span, @@ -410,26 +427,31 @@ pub(crate) struct NonUnitDefault { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_exhaustive_default)] -#[help] +#[diag("default variant must be exhaustive")] +#[help("consider a manual implementation of `Default`")] pub(crate) struct NonExhaustiveDefault { #[primary_span] pub(crate) span: Span, - #[label] + #[label("declared `#[non_exhaustive]` here")] pub(crate) non_exhaustive: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_multiple_default_attrs)] -#[note] +#[diag("multiple `#[default]` attributes")] +#[note("only one `#[default]` attribute is needed")] pub(crate) struct MultipleDefaultAttrs { #[primary_span] pub(crate) span: Span, - #[label] + #[label("`#[default]` used here")] pub(crate) first: Span, - #[label(builtin_macros_label_again)] + #[label("`#[default]` used again here")] pub(crate) first_rest: Span, - #[help] + #[help( + "try removing {$only_one -> + [true] this + *[false] these + }" + )] pub(crate) rest: MultiSpan, pub(crate) only_one: bool, #[subdiagnostic] @@ -438,7 +460,7 @@ pub(crate) struct MultipleDefaultAttrs { #[derive(Subdiagnostic)] #[multipart_suggestion( - builtin_macros_help, + "consider a manual implementation of `Default`", applicability = "machine-applicable", style = "tool-only" )] @@ -448,16 +470,21 @@ pub(crate) struct MultipleDefaultAttrsSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_default_arg)] +#[diag("`#[default]` attribute does not accept a value")] pub(crate) struct DefaultHasArg { #[primary_span] - #[suggestion(code = "#[default]", style = "hidden", applicability = "maybe-incorrect")] + #[suggestion( + "try using `#[default]`", + code = "#[default]", + style = "hidden", + applicability = "maybe-incorrect" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_from_wrong_target)] -#[note(builtin_macros_derive_from_usage_note)] +#[diag("`#[derive(From)]` used on {$kind}")] +#[note("`#[derive(From)]` can only be used on structs with exactly one field")] pub(crate) struct DeriveFromWrongTarget<'a> { #[primary_span] pub(crate) span: MultiSpan, @@ -465,8 +492,13 @@ pub(crate) struct DeriveFromWrongTarget<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_from_wrong_field_count)] -#[note(builtin_macros_derive_from_usage_note)] +#[diag( + "`#[derive(From)]` used on a struct with {$multiple_fields -> + [true] multiple fields + *[false] no fields + }" +)] +#[note("`#[derive(From)]` can only be used on structs with exactly one field")] pub(crate) struct DeriveFromWrongFieldCount { #[primary_span] pub(crate) span: MultiSpan, @@ -474,21 +506,21 @@ pub(crate) struct DeriveFromWrongFieldCount { } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_macro_call)] +#[diag("`derive` cannot be used on items with type macros")] pub(crate) struct DeriveMacroCall { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_cannot_derive_union)] +#[diag("this trait cannot be derived for unions")] pub(crate) struct DeriveUnion { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_env_takes_args)] +#[diag("`env!()` takes 1 or 2 arguments")] pub(crate) struct EnvTakesArgs { #[primary_span] pub(crate) span: Span, @@ -511,24 +543,26 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessag #[derive(Diagnostic)] pub(crate) enum EnvNotDefined<'a> { - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_cargo)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help( + "Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead" + )] CargoEnvVar { #[primary_span] span: Span, var: Symbol, var_expr: &'a rustc_ast::Expr, }, - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_cargo_typo)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help("there is a similar Cargo environment variable: `{$suggested_var}`")] CargoEnvVarTypo { #[primary_span] span: Span, var: Symbol, suggested_var: Symbol, }, - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_custom)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help("use `std::env::var({$var_expr})` to read the variable at run time")] CustomEnvVar { #[primary_span] span: Span, @@ -538,7 +572,7 @@ pub(crate) enum EnvNotDefined<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_env_not_unicode)] +#[diag("environment variable `{$var}` is not a valid Unicode string")] pub(crate) struct EnvNotUnicode { #[primary_span] pub(crate) span: Span, @@ -546,39 +580,39 @@ pub(crate) struct EnvNotUnicode { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_requires_string)] +#[diag("requires at least a format string argument")] pub(crate) struct FormatRequiresString { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_duplicate_arg)] +#[diag("duplicate argument named `{$ident}`")] pub(crate) struct FormatDuplicateArg { #[primary_span] pub(crate) span: Span, - #[label(builtin_macros_label1)] + #[label("previously here")] pub(crate) prev: Span, - #[label(builtin_macros_label2)] + #[label("duplicate argument")] pub(crate) duplicate: Span, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_positional_after_named)] +#[diag("positional arguments cannot follow named arguments")] pub(crate) struct PositionalAfterNamed { #[primary_span] - #[label] + #[label("positional arguments must be before named arguments")] pub(crate) span: Span, - #[label(builtin_macros_named_args)] + #[label("named argument")] pub(crate) args: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_string_invalid)] +#[diag("invalid format string: {$desc}")] pub(crate) struct InvalidFormatString { #[primary_span] - #[label] + #[label("{$label1} in format string")] pub(crate) span: Span, pub(crate) desc: String, pub(crate) label1: String, @@ -591,13 +625,13 @@ pub(crate) struct InvalidFormatString { } #[derive(Subdiagnostic)] -#[note(builtin_macros_note)] +#[note("{$note}")] pub(crate) struct InvalidFormatStringNote { pub(crate) note: String, } #[derive(Subdiagnostic)] -#[label(builtin_macros_second_label)] +#[label("{$label}")] pub(crate) struct InvalidFormatStringLabel { #[primary_span] pub(crate) span: Span, @@ -607,7 +641,7 @@ pub(crate) struct InvalidFormatStringLabel { #[derive(Subdiagnostic)] pub(crate) enum InvalidFormatStringSuggestion { #[multipart_suggestion( - builtin_macros_format_use_positional, + "consider using a positional formatting argument instead", style = "verbose", applicability = "machine-applicable" )] @@ -619,17 +653,13 @@ pub(crate) enum InvalidFormatStringSuggestion { span: Span, arg: String, }, - #[suggestion( - builtin_macros_format_remove_raw_ident, - code = "", - applicability = "machine-applicable" - )] + #[suggestion("remove the `r#`", code = "", applicability = "machine-applicable")] RemoveRawIdent { #[primary_span] span: Span, }, #[suggestion( - builtin_macros_format_reorder_format_parameter, + "did you mean `{$replacement}`?", code = "{replacement}", style = "verbose", applicability = "machine-applicable" @@ -640,7 +670,7 @@ pub(crate) enum InvalidFormatStringSuggestion { replacement: String, }, #[suggestion( - builtin_macros_format_add_missing_colon, + "add a colon before the format specifier", code = ":?", applicability = "machine-applicable" )] @@ -648,12 +678,26 @@ pub(crate) enum InvalidFormatStringSuggestion { #[primary_span] span: Span, }, + + #[suggestion( + "use rust debug printing macro", + code = "{replacement}", + style = "verbose", + applicability = "machine-applicable" + )] + UseRustDebugPrintingMacro { + #[primary_span] + macro_span: Span, + replacement: String, + }, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_no_arg_named)] -#[note] -#[note(builtin_macros_note2)] +#[diag("there is no argument named `{$name}`")] +#[note("did you intend to capture a variable `{$name}` from the surrounding scope?")] +#[note( + "to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro" +)] pub(crate) struct FormatNoArgNamed { #[primary_span] pub(crate) span: Span, @@ -661,8 +705,19 @@ pub(crate) struct FormatNoArgNamed { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unknown_trait)] -#[note] +#[diag("unknown format trait `{$ty}`")] +#[note( + "the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait" +)] pub(crate) struct FormatUnknownTrait<'a> { #[primary_span] pub(crate) span: Span, @@ -673,7 +728,7 @@ pub(crate) struct FormatUnknownTrait<'a> { #[derive(Subdiagnostic)] #[suggestion( - builtin_macros_suggestion, + "use the `{$trait_name}` trait", code = "{fmt}", style = "tool-only", applicability = "maybe-incorrect" @@ -686,10 +741,20 @@ pub(crate) struct FormatUnknownTraitSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unused_arg)] +#[diag( + "{$named -> + [true] named argument + *[false] argument + } never used" +)] pub(crate) struct FormatUnusedArg { #[primary_span] - #[label(builtin_macros_format_unused_arg)] + #[label( + "{$named -> + [true] named argument + *[false] argument + } never used" + )] pub(crate) span: Span, pub(crate) named: bool, } @@ -699,25 +764,35 @@ pub(crate) struct FormatUnusedArg { impl Subdiagnostic for FormatUnusedArg { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("named", self.named); - let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg); + let msg = diag.eagerly_translate(msg!( + "{$named -> + [true] named argument + *[false] argument + } never used" + )); diag.remove_arg("named"); diag.span_label(self.span, msg); } } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unused_args)] +#[diag("multiple unused formatting arguments")] pub(crate) struct FormatUnusedArgs { #[primary_span] pub(crate) unused: Vec, - #[label] + #[label("multiple missing formatting specifiers")] pub(crate) fmt: Span, #[subdiagnostic] pub(crate) unused_labels: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_pos_mismatch)] +#[diag( + "{$n} positional {$n -> + [one] argument + *[more] arguments + } in format string, but {$desc}" +)] pub(crate) struct FormatPositionalMismatch { #[primary_span] pub(crate) span: MultiSpan, @@ -728,13 +803,23 @@ pub(crate) struct FormatPositionalMismatch { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_redundant_args)] +#[diag( + "redundant {$n -> + [one] argument + *[more] arguments + }" +)] pub(crate) struct FormatRedundantArgs { #[primary_span] pub(crate) span: MultiSpan, pub(crate) n: usize, - #[note] + #[note( + "{$n -> + [one] the formatting specifier is referencing the binding already + *[more] the formatting specifiers are referencing the bindings already + }" + )] pub(crate) note: MultiSpan, #[subdiagnostic] @@ -742,38 +827,38 @@ pub(crate) struct FormatRedundantArgs { } #[derive(Subdiagnostic)] -#[multipart_suggestion(builtin_macros_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("this can be removed", applicability = "machine-applicable")] pub(crate) struct FormatRedundantArgsSugg { #[suggestion_part(code = "")] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_test_case_non_item)] +#[diag("`#[test_case]` attribute is only allowed on items")] pub(crate) struct TestCaseNonItem { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_test_bad_fn)] +#[diag("{$kind} functions cannot be used for tests")] pub(crate) struct TestBadFn { #[primary_span] pub(crate) span: Span, - #[label] + #[label("`{$kind}` because of this")] pub(crate) cause: Span, pub(crate) kind: &'static str, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_explicit_register_name)] +#[diag("explicit register arguments cannot have names")] pub(crate) struct AsmExplicitRegisterName { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_mutually_exclusive)] +#[diag("the `{$opt1}` and `{$opt2}` options are mutually exclusive")] pub(crate) struct AsmMutuallyExclusive { #[primary_span] pub(crate) spans: Vec, @@ -782,65 +867,65 @@ pub(crate) struct AsmMutuallyExclusive { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pure_combine)] +#[diag("the `pure` option must be combined with either `nomem` or `readonly`")] pub(crate) struct AsmPureCombine { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pure_no_output)] +#[diag("asm with the `pure` option must have at least one output")] pub(crate) struct AsmPureNoOutput { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_modifier_invalid)] +#[diag("asm template modifier must be a single character")] pub(crate) struct AsmModifierInvalid { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_attribute_not_supported)] +#[diag("this attribute is not supported on assembly")] pub(crate) struct AsmAttributeNotSupported { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_duplicate_arg)] +#[diag("duplicate argument named `{$name}`")] pub(crate) struct AsmDuplicateArg { #[primary_span] - #[label(builtin_macros_arg)] + #[label("duplicate argument")] pub(crate) span: Span, - #[label] + #[label("previously here")] pub(crate) prev: Span, pub(crate) name: Symbol, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pos_after)] +#[diag("positional arguments cannot follow named arguments or explicit register arguments")] pub(crate) struct AsmPositionalAfter { #[primary_span] - #[label(builtin_macros_pos)] + #[label("positional argument")] pub(crate) span: Span, - #[label(builtin_macros_named)] + #[label("named argument")] pub(crate) named: Vec, - #[label(builtin_macros_explicit)] + #[label("explicit register argument")] pub(crate) explicit: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_noreturn)] +#[diag("asm outputs are not allowed with the `noreturn` option")] pub(crate) struct AsmNoReturn { #[primary_span] pub(crate) outputs_sp: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_no_matched_argument_name)] +#[diag("there is no argument named `{$name}`")] pub(crate) struct AsmNoMatchedArgumentName { pub(crate) name: String, #[primary_span] @@ -848,7 +933,7 @@ pub(crate) struct AsmNoMatchedArgumentName { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_mayunwind)] +#[diag("asm labels are not allowed with the `may_unwind` option")] pub(crate) struct AsmMayUnwind { #[primary_span] pub(crate) labels_sp: Vec, @@ -862,46 +947,54 @@ pub(crate) struct AsmClobberNoReg { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { // eager translation as `span_labels` takes `AsRef` - let lbl1 = dcx.eagerly_translate_to_string( - crate::fluent_generated::builtin_macros_asm_clobber_abi, - [].into_iter(), - ); - let lbl2 = dcx.eagerly_translate_to_string( - crate::fluent_generated::builtin_macros_asm_clobber_outputs, - [].into_iter(), - ); - Diag::new(dcx, level, crate::fluent_generated::builtin_macros_asm_clobber_no_reg) - .with_span(self.spans.clone()) - .with_span_labels(self.clobbers, &lbl1) - .with_span_labels(self.spans, &lbl2) + let lbl1 = dcx.eagerly_translate_to_string(msg!("clobber_abi"), [].into_iter()); + let lbl2 = dcx.eagerly_translate_to_string(msg!("generic outputs"), [].into_iter()); + Diag::new( + dcx, + level, + msg!("asm with `clobber_abi` must specify explicit registers for outputs"), + ) + .with_span(self.spans.clone()) + .with_span_labels(self.clobbers, &lbl1) + .with_span_labels(self.spans, &lbl2) } } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_opt_already_provided)] +#[diag("the `{$symbol}` option was already provided")] pub(crate) struct AsmOptAlreadyprovided { #[primary_span] - #[label] + #[label("this option was already provided")] pub(crate) span: Span, pub(crate) symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove this option", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub(crate) span_with_comma: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_option)] +#[diag("the `{$symbol}` option cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedOption { #[primary_span] - #[label] + #[label("the `{$symbol}` option is not meaningful for global-scoped inline assembly")] pub(crate) span: Span, pub(crate) symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove this option", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub(crate) span_with_comma: Span, pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_clobber_abi)] +#[diag("`clobber_abi` cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedClobberAbi { #[primary_span] pub(crate) spans: Vec, @@ -909,28 +1002,14 @@ pub(crate) struct AsmUnsupportedClobberAbi { } #[derive(Diagnostic)] -#[diag(builtin_macros_test_runner_invalid)] -pub(crate) struct TestRunnerInvalid { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_test_runner_nargs)] -pub(crate) struct TestRunnerNargs { - #[primary_span] - pub(crate) span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_expected_comma_in_list)] +#[diag("expected token: `,`")] pub(crate) struct ExpectedCommaInList { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_only_one_argument)] +#[diag("{$name} takes 1 argument")] pub(crate) struct OnlyOneArgument<'a> { #[primary_span] pub span: Span, @@ -938,7 +1017,7 @@ pub(crate) struct OnlyOneArgument<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_takes_no_arguments)] +#[diag("{$name} takes no arguments")] pub(crate) struct TakesNoArguments<'a> { #[primary_span] pub span: Span, @@ -946,7 +1025,7 @@ pub(crate) struct TakesNoArguments<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_proc_macro_attribute_only_usable_with_crate_type)] +#[diag("the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type")] pub(crate) struct AttributeOnlyUsableWithCrateType<'a> { #[primary_span] pub span: Span, @@ -954,7 +1033,7 @@ pub(crate) struct AttributeOnlyUsableWithCrateType<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_source_utils_expected_item)] +#[diag("expected item, found `{$token}`")] pub(crate) struct ExpectedItem<'a> { #[primary_span] pub span: Span, @@ -962,73 +1041,72 @@ pub(crate) struct ExpectedItem<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] +#[diag("cannot use `#[unsafe(naked)]` with testing attributes", code = E0736)] pub(crate) struct NakedFunctionTestingAttribute { #[primary_span] - #[label(builtin_macros_naked_attribute)] + #[label("`#[unsafe(naked)]` is incompatible with testing attributes")] pub naked_span: Span, - #[label] + #[label("function marked with testing attribute here")] pub testing_span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_non_generic_pointee)] +#[diag("the `#[pointee]` attribute may only be used on generic parameters")] pub(crate) struct NonGenericPointee { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_other)] +#[diag( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" +)] pub(crate) struct AsmExpectedOther { #[primary_span] - #[label(builtin_macros_expected_other)] + #[label( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" + )] pub(crate) span: Span, pub(crate) is_inline_asm: bool, } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_select_no_matches)] +#[diag("none of the predicates in this `cfg_select` evaluated to true")] pub(crate) struct CfgSelectNoMatches { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_select_unreachable)] -pub(crate) struct CfgSelectUnreachable { - #[primary_span] - #[label(builtin_macros_label2)] - pub span: Span, - - #[label] - pub wildcard_span: Span, -} - -#[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_macro)] +#[diag("`#[eii_declaration(...)]` is only valid on macros")] pub(crate) struct EiiExternTargetExpectedMacro { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_list)] +#[diag("`#[eii_declaration(...)]` expects a list of one or two elements")] pub(crate) struct EiiExternTargetExpectedList { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_unsafe)] +#[diag("expected this argument to be \"unsafe\"")] pub(crate) struct EiiExternTargetExpectedUnsafe { #[primary_span] - #[note] + #[note("the second argument is optional")] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_expected_function)] +#[diag("`#[{$name}]` is only valid on functions")] pub(crate) struct EiiSharedMacroExpectedFunction { #[primary_span] pub span: Span, @@ -1036,27 +1114,27 @@ pub(crate) struct EiiSharedMacroExpectedFunction { } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_in_statement_position)] +#[diag("`#[{$name}]` can only be used on functions inside a module")] pub(crate) struct EiiSharedMacroInStatementPosition { #[primary_span] pub span: Span, pub name: String, - #[label] + #[label("`#[{$name}]` is used on this item, which is part of another item's local scope")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_only_once)] +#[diag("`#[{$name}]` can only be specified once")] pub(crate) struct EiiOnlyOnce { #[primary_span] pub span: Span, - #[note] + #[note("specified again here")] pub first_span: Span, pub name: String, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_expected_max_one_argument)] +#[diag("`#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]`")] pub(crate) struct EiiMacroExpectedMaxOneArgument { #[primary_span] pub span: Span, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 12cb2cd00694..f47dae5eba00 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -160,6 +160,7 @@ fn make_format_args( ecx: &mut ExtCtxt<'_>, input: MacroInput, append_newline: bool, + macro_span: Span, ) -> ExpandResult, ()> { let msg = "format argument must be a string literal"; let unexpanded_fmt_span = input.fmtstr.span; @@ -333,6 +334,23 @@ fn make_format_args( let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); e.sugg_ = Some(errors::InvalidFormatStringSuggestion::AddMissingColon { span }); } + parse::Suggestion::UseRustDebugPrintingMacro => { + // This targets `println!("{=}", x);` and `println!("{0=}", x);` + if let [arg] = args.all_args() { + let expr_span = arg.expr.span; + if let Ok(expr_snippet) = ecx.source_map().span_to_snippet(expr_span) { + let replacement = format!("{}!({})", "dbg", expr_snippet); + + let call_span = macro_span.source_callsite(); + e.sugg_ = Some( + errors::InvalidFormatStringSuggestion::UseRustDebugPrintingMacro { + macro_span: call_span, + replacement, + }, + ); + } + } + } } let guar = ecx.dcx().emit_err(e); return ExpandResult::Ready(Err(guar)); @@ -1048,7 +1066,7 @@ fn expand_format_args_impl<'cx>( sp = ecx.with_def_site_ctxt(sp); ExpandResult::Ready(match parse_args(ecx, sp, tts) { Ok(input) => { - let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else { + let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl, sp) else { return ExpandResult::Retry(()); }; match mac { diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index bb031dafdcfd..d9116182eed0 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -47,7 +47,7 @@ pub(crate) fn expand( // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new())); - let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))); + let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))); let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); let const_item = if is_stmt { Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item))) @@ -128,11 +128,15 @@ impl AllocFnFactory<'_, '_> { let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span)); let ty_usize = self.cx.ty_path(usize); - args.push(self.cx.param(self.span, size, ty_usize.clone())); - args.push(self.cx.param(self.span, align, ty_usize)); + args.push(self.cx.param(self.span, size, ty_usize)); + let ty_align = self.ptr_alignment(); + args.push(self.cx.param(self.span, align, ty_align)); - let layout_new = - self.cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]); + let layout_new = self.cx.std_path(&[ + sym::alloc, + sym::Layout, + sym::from_size_alignment_unchecked, + ]); let layout_new = self.cx.expr_path(self.cx.path(self.span, layout_new)); let size = self.cx.expr_ident(self.span, size); let align = self.cx.expr_ident(self.span, align); @@ -175,6 +179,12 @@ impl AllocFnFactory<'_, '_> { self.cx.ty_path(usize) } + fn ptr_alignment(&self) -> Box { + let path = self.cx.std_path(&[sym::ptr, sym::Alignment]); + let path = self.cx.path(self.span, path); + self.cx.ty_path(path) + } + fn ptr_u8(&self) -> Box { let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span)); let ty_u8 = self.cx.ty_path(u8); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 120e3f849ff6..08da5935bbea 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -3,7 +3,7 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] @@ -57,8 +57,6 @@ pub mod standard_library_imports; pub mod test_harness; pub mod util; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { let mut register = |name, kind| resolver.register_builtin_macro(name, kind); macro register_bang($($name:ident: $f:expr,)*) { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index e30d506a31b9..24a5d79958c6 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -385,7 +385,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box { cx.attr_nested_word(sym::allow, sym::deprecated, span), ]); - let block = ast::ConstItemRhs::Body(cx.expr_block( + let block = ast::ConstItemRhsKind::new_body(cx.expr_block( cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]), )); diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index d5f774865a9e..a9718d53ac49 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench( ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), define_opaque: None, // test::TestDescAndFn { - rhs: Some(ast::ConstItemRhs::Body( + rhs_kind: ast::ConstItemRhsKind::new_body( cx.expr_struct( sp, test_path("TestDescAndFn"), @@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench( field("testfn", test_fn), // } ], ), // } - )), + ), } .into(), ), diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 8d6969b0ca12..b5d63511fce9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -8,10 +8,11 @@ use rustc_ast::entry::EntryPointType; use rustc_ast::mut_visit::*; use rustc_ast::visit::Visitor; use rustc_ast::{ModKind, attr}; -use rustc_errors::DiagCtxtHandle; +use rustc_attr_parsing::AttributeParser; use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; +use rustc_hir::attrs::AttributeKind; use rustc_session::Session; use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS; use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency}; @@ -60,7 +61,7 @@ pub fn inject( // Do this here so that the test_runner crate attribute gets marked as used // even in non-test builds - let test_runner = get_test_runner(dcx, krate); + let test_runner = get_test_runner(sess, features, krate); if sess.is_test_crate() { let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) { @@ -386,20 +387,16 @@ fn get_test_name(i: &ast::Item) -> Option { attr::first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker) } -fn get_test_runner(dcx: DiagCtxtHandle<'_>, krate: &ast::Crate) -> Option { - let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; - let meta_list = test_attr.meta_item_list()?; - let span = test_attr.span; - match &*meta_list { - [single] => match single.meta_item() { - Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), - _ => { - dcx.emit_err(errors::TestRunnerInvalid { span }); - } - }, - _ => { - dcx.emit_err(errors::TestRunnerNargs { span }); - } +fn get_test_runner(sess: &Session, features: &Features, krate: &ast::Crate) -> Option { + match AttributeParser::parse_limited( + sess, + &krate.attrs, + sym::test_runner, + krate.spans.inner_span, + krate.id, + Some(features), + ) { + Some(rustc_hir::Attribute::Parsed(AttributeKind::TestRunner(path))) => Some(path), + _ => None, } - None } diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 760e23f2171b..fc5c634d9570 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -2,29 +2,26 @@ //! standalone executable. use std::env; -use std::fs::{self, File}; +use std::fs::File; use std::io::BufWriter; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::Arc; use std::thread::JoinHandle; use cranelift_object::{ObjectBuilder, ObjectModule}; use rustc_codegen_ssa::assert_module_sources::CguReuse; -use rustc_codegen_ssa::back::link::ensure_removed; +use rustc_codegen_ssa::back::write::{CompiledModules, produce_final_output_artifacts}; use rustc_codegen_ssa::base::determine_cgu_reuse; -use rustc_codegen_ssa::{ - CodegenResults, CompiledModule, CrateInfo, ModuleKind, errors as ssa_errors, -}; +use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_hir::attrs::Linkage as RLinkage; -use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility}; use rustc_session::Session; -use rustc_session::config::{OutFileName, OutputFilenames, OutputType}; +use rustc_session::config::{OutputFilenames, OutputType}; use crate::base::CodegenedFunction; use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; @@ -125,203 +122,22 @@ impl OngoingCodegen { sess.dcx().abort_if_errors(); - let codegen_results = CodegenResults { - modules, - allocator_module: self.allocator_module, - crate_info: self.crate_info, - }; + let compiled_modules = CompiledModules { modules, allocator_module: self.allocator_module }; - produce_final_output_artifacts(sess, &codegen_results, outputs); + produce_final_output_artifacts(sess, &compiled_modules, outputs); - (codegen_results, work_products) + ( + CodegenResults { + crate_info: self.crate_info, + + modules: compiled_modules.modules, + allocator_module: compiled_modules.allocator_module, + }, + work_products, + ) } } -// Adapted from https://github.com/rust-lang/rust/blob/73476d49904751f8d90ce904e16dfbc278083d2c/compiler/rustc_codegen_ssa/src/back/write.rs#L547C1-L706C2 -fn produce_final_output_artifacts( - sess: &Session, - codegen_results: &CodegenResults, - crate_output: &OutputFilenames, -) { - let user_wants_bitcode = false; - let mut user_wants_objects = false; - - // Produce final compile outputs. - let copy_gracefully = |from: &Path, to: &OutFileName| match to { - OutFileName::Stdout => { - if let Err(e) = copy_to_stdout(from) { - sess.dcx().emit_err(ssa_errors::CopyPath::new(from, to.as_path(), e)); - } - } - OutFileName::Real(path) => { - if let Err(e) = fs::copy(from, path) { - sess.dcx().emit_err(ssa_errors::CopyPath::new(from, path, e)); - } - } - }; - - let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| { - if codegen_results.modules.len() == 1 { - // 1) Only one codegen unit. In this case it's no difficulty - // to copy `foo.0.x` to `foo.x`. - let path = crate_output.temp_path_for_cgu( - output_type, - &codegen_results.modules[0].name, - sess.invocation_temp.as_deref(), - ); - let output = crate_output.path(output_type); - if !output_type.is_text_output() && output.is_tty() { - sess.dcx() - .emit_err(ssa_errors::BinaryOutputToTty { shorthand: output_type.shorthand() }); - } else { - copy_gracefully(&path, &output); - } - if !sess.opts.cg.save_temps && !keep_numbered { - // The user just wants `foo.x`, not `foo.#module-name#.x`. - ensure_removed(sess.dcx(), &path); - } - } else { - if crate_output.outputs.contains_explicit_name(&output_type) { - // 2) Multiple codegen units, with `--emit foo=some_name`. We have - // no good solution for this case, so warn the user. - sess.dcx() - .emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() }); - } else if crate_output.single_output_file.is_some() { - // 3) Multiple codegen units, with `-o some_name`. We have - // no good solution for this case, so warn the user. - sess.dcx() - .emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() }); - } else { - // 4) Multiple codegen units, but no explicit name. We - // just leave the `foo.0.x` files in place. - // (We don't have to do any work in this case.) - } - } - }; - - // Flag to indicate whether the user explicitly requested bitcode. - // Otherwise, we produced it only as a temporary output, and will need - // to get rid of it. - for output_type in crate_output.outputs.keys() { - match *output_type { - OutputType::Bitcode | OutputType::ThinLinkBitcode => { - // Cranelift doesn't have bitcode - // user_wants_bitcode = true; - // // Copy to .bc, but always keep the .0.bc. There is a later - // // check to figure out if we should delete .0.bc files, or keep - // // them for making an rlib. - // copy_if_one_unit(OutputType::Bitcode, true); - } - OutputType::LlvmAssembly => { - // Cranelift IR text already emitted during codegen - // copy_if_one_unit(OutputType::LlvmAssembly, false); - } - OutputType::Assembly => { - // Currently no support for emitting raw assembly files - // copy_if_one_unit(OutputType::Assembly, false); - } - OutputType::Object => { - user_wants_objects = true; - copy_if_one_unit(OutputType::Object, true); - } - OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {} - } - } - - // Clean up unwanted temporary files. - - // We create the following files by default: - // - #crate#.#module-name#.bc - // - #crate#.#module-name#.o - // - #crate#.crate.metadata.bc - // - #crate#.crate.metadata.o - // - #crate#.o (linked from crate.##.o) - // - #crate#.bc (copied from crate.##.bc) - // We may create additional files if requested by the user (through - // `-C save-temps` or `--emit=` flags). - - if !sess.opts.cg.save_temps { - // Remove the temporary .#module-name#.o objects. If the user didn't - // explicitly request bitcode (with --emit=bc), and the bitcode is not - // needed for building an rlib, then we must remove .#module-name#.bc as - // well. - - // Specific rules for keeping .#module-name#.bc: - // - If the user requested bitcode (`user_wants_bitcode`), and - // codegen_units > 1, then keep it. - // - If the user requested bitcode but codegen_units == 1, then we - // can toss .#module-name#.bc because we copied it to .bc earlier. - // - If we're not building an rlib and the user didn't request - // bitcode, then delete .#module-name#.bc. - // If you change how this works, also update back::link::link_rlib, - // where .#module-name#.bc files are (maybe) deleted after making an - // rlib. - let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe); - - let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1; - - let keep_numbered_objects = - needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1); - - for module in codegen_results.modules.iter() { - if let Some(ref path) = module.object { - if !keep_numbered_objects { - ensure_removed(sess.dcx(), path); - } - } - - if let Some(ref path) = module.dwarf_object { - if !keep_numbered_objects { - ensure_removed(sess.dcx(), path); - } - } - - if let Some(ref path) = module.bytecode { - if !keep_numbered_bitcode { - ensure_removed(sess.dcx(), path); - } - } - } - - if !user_wants_bitcode { - if let Some(ref allocator_module) = codegen_results.allocator_module { - if let Some(ref path) = allocator_module.bytecode { - ensure_removed(sess.dcx(), path); - } - } - } - } - - if sess.opts.json_artifact_notifications { - if codegen_results.modules.len() == 1 { - codegen_results.modules[0].for_each_output(|_path, ty| { - if sess.opts.output_types.contains_key(&ty) { - let descr = ty.shorthand(); - // for single cgu file is renamed to drop cgu specific suffix - // so we regenerate it the same way - let path = crate_output.path(ty); - sess.dcx().emit_artifact_notification(path.as_path(), descr); - } - }); - } else { - for module in &codegen_results.modules { - module.for_each_output(|path, ty| { - if sess.opts.output_types.contains_key(&ty) { - let descr = ty.shorthand(); - sess.dcx().emit_artifact_notification(path, descr); - } - }); - } - } - } - - // We leave the following files around by default: - // - #crate#.o - // - #crate#.crate.metadata.o - // - #crate#.bc - // These are used in linking steps and will be cleaned up afterward. -} - fn make_module(sess: &Session, name: String) -> UnwindModule { let isa = crate::build_isa(sess, false); diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 97d6cecf6848..1daf428acf76 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -106,6 +106,7 @@ fn codegen_global_asm_inner<'tcx>( match *piece { InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { + use rustc_codegen_ssa::back::symbol_export::escape_symbol_name; match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { global_asm.push_str(string); @@ -121,7 +122,7 @@ fn codegen_global_asm_inner<'tcx>( let symbol = tcx.symbol_name(instance); // FIXME handle the case where the function was made private to the // current codegen unit - global_asm.push_str(symbol.name); + global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { if cfg!(not(feature = "inline_asm_sym")) { @@ -133,7 +134,7 @@ fn codegen_global_asm_inner<'tcx>( let instance = Instance::mono(tcx, def_id); let symbol = tcx.symbol_name(instance); - global_asm.push_str(symbol.name); + global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); } } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 7361a6af4178..656e7b0aec5b 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -2,8 +2,8 @@ // Note: please avoid adding other feature gates where possible #![feature(rustc_private)] // Only used to define intrinsics in `compiler_builtins.rs`. -#![feature(f16)] -#![feature(f128)] +#![cfg_attr(feature = "jit", feature(f16))] +#![cfg_attr(feature = "jit", feature(f128))] // Note: please avoid adding other feature gates where possible #![warn(rust_2018_idioms)] #![warn(unreachable_pub)] @@ -23,7 +23,6 @@ extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; extern crate rustc_log; -extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; extern crate rustc_symbol_mangling; @@ -125,11 +124,6 @@ pub struct CraneliftCodegenBackend { } impl CodegenBackend for CraneliftCodegenBackend { - fn locale_resource(&self) -> &'static str { - // FIXME(rust-lang/rust#100717) - cranelift codegen backend is not yet translated - "" - } - fn name(&self) -> &'static str { "cranelift" } diff --git a/compiler/rustc_codegen_gcc/.cspell.json b/compiler/rustc_codegen_gcc/.cspell.json index 388ccce2b091..556432d69a41 100644 --- a/compiler/rustc_codegen_gcc/.cspell.json +++ b/compiler/rustc_codegen_gcc/.cspell.json @@ -18,6 +18,7 @@ ], "ignorePaths": [ "src/intrinsic/archs.rs", + "src/intrinsic/old_archs.rs", "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 5c8e7d628169..840c09409bba 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -113,6 +113,10 @@ jobs: git config --global user.name "User" ./y.sh prepare + - name: Add more failing tests for GCC without 128-bit integers support + if: ${{ matrix.libgccjit_version.gcc == 'gcc-15-without-int128.deb' }} + run: cat tests/failing-ui-tests-without-128bit-integers.txt >> tests/failing-ui-tests.txt + - name: Run tests run: | ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml index e49c62d6c931..11bc88e67d2d 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml @@ -83,7 +83,7 @@ jobs: run: | ./y.sh prepare --only-libcore --cross ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json - CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json + CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build -Zjson-target-spec --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json ./y.sh clean all - name: Build diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index dea1207b05da..a283ea4cb0b0 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.1.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683" +checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.1.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f81d901767ddba371a619fa9bba657066a4d3c5607ee69bbb557c1c5ba9bf85" +checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" dependencies = [ "libc", ] diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index 18847f50d46a..29af6a1fc434 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -24,7 +24,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.1.1", features = ["dlopen"] } +gccjit = { version = "3.3.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index cd6aeae4b42e..ce5ee1e4adee 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -45,12 +45,12 @@ The default configuration (see below in the [Quick start](#quick-start) section) ./y.sh test --release ``` -If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should +If you don't need to test GCC patches you wrote in our GCC fork, then the default configuration should be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC. ### Building with your own GCC version -If you wrote a patch for GCC and want to test it without this backend, you will need +If you wrote a patch for GCC and want to test it with this backend, you will need to do a few more things. To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue): @@ -127,7 +127,7 @@ You have to run these commands, in the corresponding order: $ ./y.sh prepare $ ./y.sh build --sysroot ``` -To check if all is working correctly, run: +To check if all is working correctly, run: ```bash $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml diff --git a/compiler/rustc_codegen_gcc/_typos.toml b/compiler/rustc_codegen_gcc/_typos.toml index 4a6a506a981a..c4918b114621 100644 --- a/compiler/rustc_codegen_gcc/_typos.toml +++ b/compiler/rustc_codegen_gcc/_typos.toml @@ -6,4 +6,4 @@ seh = "seh" typ = "typ" [files] -extend-exclude = ["src/intrinsic/archs.rs"] +extend-exclude = ["src/intrinsic/archs.rs", "src/intrinsic/old_archs.rs"] diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs index 9b7ee8380ca5..839c762fed74 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/build.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs @@ -141,6 +141,10 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu } let mut args: Vec<&dyn AsRef> = vec![&"cargo", &"build", &"--target", &config.target]; + if config.target.ends_with(".json") { + args.push(&"-Zjson-target-spec"); + } + for feature in &config.features { args.push(&"--features"); args.push(feature); diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index ca2a2a7dc2de..096f8c98376c 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -679,10 +679,10 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { create_dir(projects_path)?; let nb_parts = args.nb_parts.unwrap_or(0); - if nb_parts > 0 { + if let Some(count) = projects.len().checked_div(nb_parts) { // We increment the number of tests by one because if this is an odd number, we would skip // one test. - let count = projects.len() / nb_parts + 1; + let count = count + 1; let current_part = args.current_part.unwrap(); let start = current_part * count; // We remove the projects we don't want to test. diff --git a/compiler/rustc_codegen_gcc/doc/debugging.md b/compiler/rustc_codegen_gcc/doc/debugging.md index 6ff4edf8877c..853852271708 100644 --- a/compiler/rustc_codegen_gcc/doc/debugging.md +++ b/compiler/rustc_codegen_gcc/doc/debugging.md @@ -2,9 +2,9 @@ ## How to debug GCC LTO -Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger. +Run the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger. -## How to debug stdarch tests that cannot be ran locally +## How to debug stdarch tests that cannot be run locally First, run the tests normally: diff --git a/compiler/rustc_codegen_gcc/doc/errors.md b/compiler/rustc_codegen_gcc/doc/errors.md index 5727b0ff7c86..81621d49b4f1 100644 --- a/compiler/rustc_codegen_gcc/doc/errors.md +++ b/compiler/rustc_codegen_gcc/doc/errors.md @@ -15,7 +15,7 @@ That can be caused by the fact that you try to compile with `lto = "fat"`, but y ### ld: cannot find crtbegin.o -When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors: +When compiling an executable with libgccjit, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors: ``` ld: cannot find crtbegin.o: No such file or directory diff --git a/compiler/rustc_codegen_gcc/doc/gimple.md b/compiler/rustc_codegen_gcc/doc/gimple.md index 145c4eda3c1c..bd298d65ed26 100644 --- a/compiler/rustc_codegen_gcc/doc/gimple.md +++ b/compiler/rustc_codegen_gcc/doc/gimple.md @@ -3,7 +3,7 @@ You can see the full documentation about what GIMPLE is [here](https://gcc.gnu.org/onlinedocs/gccint/GIMPLE.html). In this document we will explain how to generate it. First, we'll copy the content from `gcc/gcc/testsuite/jit.dg/test-const-attribute.c` into a -file named `local.c` and remove the content we're not interested into: +file named `local.c` and remove the content we're not interested in: ```diff - /* { dg-do compile { target x86_64-*-* } } */ diff --git a/compiler/rustc_codegen_gcc/doc/tips.md b/compiler/rustc_codegen_gcc/doc/tips.md index 38bc98c02d92..ff92566d4a1a 100644 --- a/compiler/rustc_codegen_gcc/doc/tips.md +++ b/compiler/rustc_codegen_gcc/doc/tips.md @@ -53,7 +53,7 @@ If you wish to build a custom sysroot, pass the path of your sysroot source to ` ### How to use [mem-trace](https://github.com/antoyo/mem-trace) -`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. +`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't have a chance to intercept the calls to `malloc`. ### How to generate GIMPLE diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version index bab62f642365..abc967702fb0 100644 --- a/compiler/rustc_codegen_gcc/libgccjit.version +++ b/compiler/rustc_codegen_gcc/libgccjit.version @@ -1 +1 @@ -0081ca6631abdfa02bf42bc85aaf507b8a0e6beb +efdd0a7290c22f5438d7c5380105d353ee3e8518 diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl deleted file mode 100644 index b9b77b7d18c6..000000000000 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ /dev/null @@ -1,8 +0,0 @@ -codegen_gcc_unwinding_inline_asm = - GCC backend does not support unwinding from inline asm - -codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err} - -codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) - -codegen_gcc_explicit_tail_calls_unsupported = explicit tail calls with the 'become' keyword are not implemented in the GCC backend diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index 86ae738d4483..655fa6abbab2 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-12-20" +channel = "nightly-2026-02-14" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index ceb3dd3ffedf..319f3d327873 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -575,9 +575,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) { let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); - let builtin_unreachable: RValue<'gcc> = - unsafe { std::mem::transmute(builtin_unreachable) }; - self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None); + self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } // Write results to outputs. diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index c93a2e8f8da5..a08e3dc0df87 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -17,30 +17,26 @@ // /usr/bin/ld: warning: type of symbol `_RNvNvNvNvNtNtNtCsAj5i4SGTR7_3std4sync4mpmc5waker17current_thread_id5DUMMY7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o // /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization // cSpell:enable -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use std::sync::Arc; -use std::sync::atomic::Ordering; -use gccjit::{Context, OutputKind}; +use gccjit::OutputKind; use object::read::archive::ArchiveFile; -use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; +use rustc_codegen_ssa::back::lto::SerializedModule; use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::memmap::Mmap; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; -use rustc_middle::bug; -use rustc_middle::dep_graph::WorkProduct; use rustc_session::config::Lto; -use rustc_target::spec::RelocModel; use tempfile::{TempDir, tempdir}; use crate::back::write::save_temp_bitcode; use crate::errors::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, LTO_SUPPORTED, LtoMode, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; struct LtoData { // TODO(antoyo): use symbols_below_threshold. @@ -50,7 +46,7 @@ struct LtoData { } fn prepare_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>, ) -> LtoData { @@ -111,7 +107,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -123,6 +120,7 @@ pub(crate) fn run_fat( lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( cgcx, + prof, dcx, modules, lto_data.upstream_modules, @@ -132,14 +130,15 @@ pub(crate) fn run_fat( } fn fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, _dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> ModuleCodegen { - let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -223,8 +222,7 @@ fn fat_lto( // We add the object files and save in should_combine_object_files that we should combine // them into a single object file when compiling later. for (bc_decoded, name) in serialized_modules { - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -278,384 +276,3 @@ impl ModuleBufferMethods for ModuleBuffer { &[] } } - -/// Performs thin LTO by performing necessary global analysis and returning two -/// lists, one of the modules that need optimization and another for modules that -/// can simply be copied over from the incr. comp. cache. -pub(crate) fn run_thin( - cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, - each_linked_rlib_for_lto: &[PathBuf], - modules: Vec<(String, ThinBuffer)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, -) -> (Vec>, Vec) { - let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); - if cgcx.use_linker_plugin_lto { - unreachable!( - "We should never reach this case if the LTO step \ - is deferred to the linker" - ); - } - thin_lto( - cgcx, - dcx, - modules, - lto_data.upstream_modules, - lto_data.tmp_path, - cached_modules, - //<o_data.symbols_below_threshold, - ) -} - -pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBuffer) { - let name = module.name; - //let buffer = ThinBuffer::new(module.module_llvm.context, true); - let buffer = ThinBuffer::new(&module.module_llvm.context); - (name, buffer) -} - -/// Prepare "thin" LTO to get run on these modules. -/// -/// The general structure of ThinLTO is quite different from the structure of -/// "fat" LTO above. With "fat" LTO all LLVM modules in question are merged into -/// one giant LLVM module, and then we run more optimization passes over this -/// big module after internalizing most symbols. Thin LTO, on the other hand, -/// avoid this large bottleneck through more targeted optimization. -/// -/// At a high level Thin LTO looks like: -/// -/// 1. Prepare a "summary" of each LLVM module in question which describes -/// the values inside, cost of the values, etc. -/// 2. Merge the summaries of all modules in question into one "index" -/// 3. Perform some global analysis on this index -/// 4. For each module, use the index and analysis calculated previously to -/// perform local transformations on the module, for example inlining -/// small functions from other modules. -/// 5. Run thin-specific optimization passes over each module, and then code -/// generate everything at the end. -/// -/// The summary for each module is intended to be quite cheap, and the global -/// index is relatively quite cheap to create as well. As a result, the goal of -/// ThinLTO is to reduce the bottleneck on LTO and enable LTO to be used in more -/// situations. For example one cheap optimization is that we can parallelize -/// all codegen modules, easily making use of all the cores on a machine. -/// -/// With all that in mind, the function here is designed at specifically just -/// calculating the *index* for ThinLTO. This index will then be shared amongst -/// all of the `LtoModuleCodegen` units returned below and destroyed once -/// they all go out of scope. -fn thin_lto( - cgcx: &CodegenContext, - _dcx: DiagCtxtHandle<'_>, - modules: Vec<(String, ThinBuffer)>, - serialized_modules: Vec<(SerializedModule, CString)>, - tmp_path: TempDir, - cached_modules: Vec<(SerializedModule, WorkProduct)>, - //_symbols_below_threshold: &[String], -) -> (Vec>, Vec) { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis"); - info!("going for that thin, thin LTO"); - - /*let green_modules: FxHashMap<_, _> = - cached_modules.iter().map(|(_, wp)| (wp.cgu_name.clone(), wp.clone())).collect();*/ - - let full_scope_len = modules.len() + serialized_modules.len() + cached_modules.len(); - let mut thin_buffers = Vec::with_capacity(modules.len()); - let mut module_names = Vec::with_capacity(full_scope_len); - //let mut thin_modules = Vec::with_capacity(full_scope_len); - - for (i, (name, buffer)) in modules.into_iter().enumerate() { - info!("local module: {} - {}", i, name); - let cname = CString::new(name.as_bytes()).unwrap(); - /*thin_modules.push(llvm::ThinLTOModule { - identifier: cname.as_ptr(), - data: buffer.data().as_ptr(), - len: buffer.data().len(), - });*/ - thin_buffers.push(buffer); - module_names.push(cname); - } - - // FIXME: All upstream crates are deserialized internally in the - // function below to extract their summary and modules. Note that - // unlike the loop above we *must* decode and/or read something - // here as these are all just serialized files on disk. An - // improvement, however, to make here would be to store the - // module summary separately from the actual module itself. Right - // now this is store in one large bitcode file, and the entire - // file is deflate-compressed. We could try to bypass some of the - // decompression by storing the index uncompressed and only - // lazily decompressing the bytecode if necessary. - // - // Note that truly taking advantage of this optimization will - // likely be further down the road. We'd have to implement - // incremental ThinLTO first where we could actually avoid - // looking at upstream modules entirely sometimes (the contents, - // we must always unconditionally look at the index). - let mut serialized = Vec::with_capacity(serialized_modules.len() + cached_modules.len()); - - let cached_modules = - cached_modules.into_iter().map(|(sm, wp)| (sm, CString::new(wp.cgu_name).unwrap())); - - for (module, name) in serialized_modules.into_iter().chain(cached_modules) { - info!("upstream or cached module {:?}", name); - /*thin_modules.push(llvm::ThinLTOModule { - identifier: name.as_ptr(), - data: module.data().as_ptr(), - len: module.data().len(), - });*/ - - match module { - SerializedModule::Local(_) => { - //let path = module_buffer.0.to_str().expect("path"); - //let my_path = PathBuf::from(path); - //let exists = my_path.exists(); - /*module.module_llvm.should_combine_object_files = true; - module - .module_llvm - .context - .add_driver_option(module_buffer.0.to_str().expect("path"));*/ - } - SerializedModule::FromRlib(_) => unimplemented!("from rlib"), - SerializedModule::FromUncompressedFile(_) => { - unimplemented!("from uncompressed file") - } - } - - serialized.push(module); - module_names.push(name); - } - - // Sanity check - //assert_eq!(thin_modules.len(), module_names.len()); - - // Delegate to the C++ bindings to create some data here. Once this is a - // tried-and-true interface we may wish to try to upstream some of this - // to LLVM itself, right now we reimplement a lot of what they do - // upstream... - /*let data = llvm::LLVMRustCreateThinLTOData( - thin_modules.as_ptr(), - thin_modules.len() as u32, - symbols_below_threshold.as_ptr(), - symbols_below_threshold.len() as u32, - ) - .ok_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext))?; - */ - - let data = ThinData; //(Arc::new(tmp_path))/*(data)*/; - - info!("thin LTO data created"); - - /*let (key_map_path, prev_key_map, curr_key_map) = - if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir { - let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME); - // If the previous file was deleted, or we get an IO error - // reading the file, then we'll just use `None` as the - // prev_key_map, which will force the code to be recompiled. - let prev = - if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None }; - let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names); - (Some(path), prev, curr) - } - else { - // If we don't compile incrementally, we don't need to load the - // import data from LLVM. - assert!(green_modules.is_empty()); - let curr = ThinLTOKeysMap::default(); - (None, None, curr) - }; - info!("thin LTO cache key map loaded"); - info!("prev_key_map: {:#?}", prev_key_map); - info!("curr_key_map: {:#?}", curr_key_map);*/ - - // Throw our data in an `Arc` as we'll be sharing it across threads. We - // also put all memory referenced by the C++ data (buffers, ids, etc) - // into the arc as well. After this we'll create a thin module - // codegen per module in this data. - let shared = - Arc::new(ThinShared { data, thin_buffers, serialized_modules: serialized, module_names }); - - let copy_jobs = vec![]; - let mut opt_jobs = vec![]; - - info!("checking which modules can be-reused and which have to be re-optimized."); - for (module_index, module_name) in shared.module_names.iter().enumerate() { - let module_name = module_name_to_str(module_name); - /*if let (Some(prev_key_map), true) = - (prev_key_map.as_ref(), green_modules.contains_key(module_name)) - { - assert!(cgcx.incr_comp_session_dir.is_some()); - - // If a module exists in both the current and the previous session, - // and has the same LTO cache key in both sessions, then we can re-use it - if prev_key_map.keys.get(module_name) == curr_key_map.keys.get(module_name) { - let work_product = green_modules[module_name].clone(); - copy_jobs.push(work_product); - info!(" - {}: re-used", module_name); - assert!(cgcx.incr_comp_session_dir.is_some()); - continue; - } - }*/ - - info!(" - {}: re-compiled", module_name); - opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index }); - } - - // Save the current ThinLTO import information for the next compilation - // session, overwriting the previous serialized data (if any). - /*if let Some(path) = key_map_path { - if let Err(err) = curr_key_map.save_to_file(&path) { - return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err })); - } - }*/ - - // NOTE: save the temporary directory used by LTO so that it gets deleted after linking instead - // of now. - //module.module_llvm.temp_dir = Some(tmp_path); - // TODO: save the directory so that it gets deleted later. - std::mem::forget(tmp_path); - - (opt_jobs, copy_jobs) -} - -pub fn optimize_thin_module( - thin_module: ThinModule, - _cgcx: &CodegenContext, -) -> ModuleCodegen { - //let module_name = &thin_module.shared.module_names[thin_module.idx]; - /*let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap()); - let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&dcx, e))?;*/ - - // Right now the implementation we've got only works over serialized - // modules, so we create a fresh new LLVM context and parse the module - // into that context. One day, however, we may do this for upstream - // crates but for locally codegened modules we may be able to reuse - // that LLVM Context and Module. - //let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - //let llmod_raw = parse_module(llcx, module_name, thin_module.data(), &dcx)? as *const _; - let mut lto_mode = LtoMode::None; - let context = match thin_module.shared.thin_buffers.get(thin_module.idx) { - Some(thin_buffer) => Arc::clone(&thin_buffer.context), - None => { - let context = Context::default(); - let len = thin_module.shared.thin_buffers.len(); - let module = &thin_module.shared.serialized_modules[thin_module.idx - len]; - match *module { - SerializedModule::Local(ref module_buffer) => { - let path = module_buffer.0.to_str().expect("path"); - context.add_driver_option(path); - lto_mode = LtoMode::Thin; - /*module.module_llvm.should_combine_object_files = true; - module - .module_llvm - .context - .add_driver_option(module_buffer.0.to_str().expect("path"));*/ - } - SerializedModule::FromRlib(_) => unimplemented!("from rlib"), - SerializedModule::FromUncompressedFile(_) => { - unimplemented!("from uncompressed file") - } - } - Arc::new(SyncContext::new(context)) - } - }; - let lto_supported = LTO_SUPPORTED.load(Ordering::SeqCst); - let module = ModuleCodegen::new_regular( - thin_module.name().to_string(), - GccContext { - context, - lto_mode, - lto_supported, - // TODO(antoyo): use the correct relocation model here. - relocation_model: RelocModel::Pic, - temp_dir: None, - }, - ); - /*{ - let target = &*module.module_llvm.tm; - let llmod = module.module_llvm.llmod(); - save_temp_bitcode(cgcx, &module, "thin-lto-input"); - - // Up next comes the per-module local analyses that we do for Thin LTO. - // Each of these functions is basically copied from the LLVM - // implementation and then tailored to suit this implementation. Ideally - // each of these would be supported by upstream LLVM but that's perhaps - // a patch for another day! - // - // You can find some more comments about these functions in the LLVM - // bindings we've got (currently `PassWrapper.cpp`) - { - let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); - unsafe { llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) }; - save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); - } - - { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); - if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { - return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule)); - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve"); - } - - { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); - if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { - return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule)); - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize"); - } - - { - let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); - if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) { - return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule)); - } - save_temp_bitcode(cgcx, &module, "thin-lto-after-import"); - } - - // Alright now that we've done everything related to the ThinLTO - // analysis it's time to run some optimizations! Here we use the same - // `run_pass_manager` as the "fat" LTO above except that we tell it to - // populate a thin-specific pass manager, which presumably LLVM treats a - // little differently. - { - info!("running thin lto passes over {}", module.name); - run_pass_manager(cgcx, &dcx, &mut module, true)?; - save_temp_bitcode(cgcx, &module, "thin-lto-after-pm"); - } - }*/ - // FIXME: switch to #[expect] when the clippy bug is fixed. - #[allow(clippy::let_and_return)] - module -} - -pub struct ThinBuffer { - context: Arc, -} - -impl ThinBuffer { - pub(crate) fn new(context: &Arc) -> Self { - Self { context: Arc::clone(context) } - } -} - -impl ThinBufferMethods for ThinBuffer { - fn data(&self) -> &[u8] { - &[] - } -} - -pub struct ThinData; //(Arc); - -fn module_name_to_str(c_str: &CStr) -> &str { - c_str.to_str().unwrap_or_else(|e| { - bug!("Encountered non-utf8 GCC module name `{}`: {}", c_str.to_string_lossy(), e) - }) -} diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index b6223c5be370..ddf13558027b 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -6,6 +6,7 @@ use rustc_codegen_ssa::back::write::{ BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter, }; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::DiagCtxt; use rustc_fs_util::link_or_copy; use rustc_log::tracing::debug; @@ -14,10 +15,11 @@ use rustc_target::spec::SplitDebuginfo; use crate::base::add_pic_option; use crate::errors::CopyBitcode; -use crate::{GccCodegenBackend, GccContext, LtoMode}; +use crate::{GccContext, LtoMode}; pub(crate) fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, @@ -25,7 +27,7 @@ pub(crate) fn codegen( let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); - let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); + let _timer = prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); { let context = &module.module_llvm.context; @@ -44,9 +46,8 @@ pub(crate) fn codegen( ); if config.bitcode_needed() { - let _timer = cgcx - .prof - .generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name); + let _timer = + prof.generic_activity_with_arg("GCC_module_codegen_make_bitcode", &*module.name); // TODO(antoyo) /*if let Some(bitcode_filename) = bc_out.file_name() { @@ -58,8 +59,7 @@ pub(crate) fn codegen( }*/ if config.emit_bc || config.emit_obj == EmitObj::Bitcode { - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name); if lto_supported { context.add_command_line_option("-flto=auto"); @@ -70,8 +70,7 @@ pub(crate) fn codegen( } if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { // TODO(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? @@ -98,7 +97,7 @@ pub(crate) fn codegen( if config.emit_asm { let _timer = - cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); + prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path_for_cgu( OutputType::Assembly, &module.name, @@ -109,9 +108,8 @@ pub(crate) fn codegen( match config.emit_obj { EmitObj::ObjectCode(_) => { - let _timer = cgcx - .prof - .generic_activity_with_arg("GCC_module_codegen_emit_obj", &*module.name); + let _timer = + prof.generic_activity_with_arg("GCC_module_codegen_emit_obj", &*module.name); if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") { println!("Module {}", module.name); } @@ -227,7 +225,7 @@ pub(crate) fn codegen( } pub(crate) fn save_temp_bitcode( - cgcx: &CodegenContext, + cgcx: &CodegenContext, _module: &ModuleCodegen, _name: &str, ) { diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 3def9a5c015c..e1937f5c11eb 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1495,6 +1495,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> { + use crate::context::new_array_type; + let vector_type = vec .get_type() .unqualified() @@ -1503,7 +1505,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let element_type = vector_type.get_element_type(); let vec_num_units = vector_type.get_num_units(); let array_type = - self.context.new_array_type(self.location, element_type, vec_num_units as u64); + new_array_type(self.context, self.location, element_type, vec_num_units as u64); let array = self.context.new_bitcast(self.location, vec, array_type).to_rvalue(); self.context.new_array_access(self.location, array, idx).to_rvalue() } @@ -1871,32 +1873,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. - let int_max = |signed: bool, int_width: u64| -> u128 { + fn int_max(signed: bool, int_width: u64) -> u128 { let shift_amount = 128 - int_width; if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount } - }; - let int_min = |signed: bool, int_width: u64| -> i128 { + } + fn int_min(signed: bool, int_width: u64) -> i128 { if signed { i128::MIN >> (128 - int_width) } else { 0 } - }; + } - let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) { + // TODO: rewrite using a generic function with . + let compute_clamp_bounds_half = |signed: bool, int_width: u64| -> (u128, u128) { let rounded_min = - ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero); - assert_eq!(rounded_min.status, Status::OK); + ieee::Half::from_i128_r(int_min(signed, int_width), Round::TowardZero); + //assert_eq!(rounded_min.status, Status::OK); let rounded_max = - ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero); + ieee::Half::from_u128_r(int_max(signed, int_width), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) }; - let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) { - let rounded_min = - ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero); + fn compute_clamp_bounds(signed: bool, int_width: u64) -> (u128, u128) { + let rounded_min = F::from_i128_r(int_min(signed, int_width), Round::TowardZero); assert_eq!(rounded_min.status, Status::OK); - let rounded_max = - ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero); + let rounded_max = F::from_u128_r(int_max(signed, int_width), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) - }; + } // To implement saturation, we perform the following steps: // // 1. Cast val to an integer with fpto[su]i. This may result in undef. @@ -1926,15 +1927,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let float_bits_to_llval = |bx: &mut Self, bits| { let bits_llval = match float_width { + 16 => bx.cx().const_u16(bits as u16), 32 => bx.cx().const_u32(bits as u32), 64 => bx.cx().const_u64(bits as u64), + 128 => bx.cx().const_u128(bits), n => bug!("unsupported float width {}", n), }; bx.bitcast(bits_llval, float_ty) }; let (f_min, f_max) = match float_width { - 32 => compute_clamp_bounds_single(signed, int_width), - 64 => compute_clamp_bounds_double(signed, int_width), + 16 => compute_clamp_bounds_half(signed, int_width), + 32 => compute_clamp_bounds::(signed, int_width), + 64 => compute_clamp_bounds::(signed, int_width), + 128 => compute_clamp_bounds::(signed, int_width), n => bug!("unsupported float width {}", n), }; let f_min = float_bits_to_llval(self, f_min); diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 7c2969e58718..86a4eeac89d5 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, new_array_type}; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -20,6 +20,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { bytes_in_context(self, bytes) } + pub fn const_u16(&self, i: u16) -> RValue<'gcc> { + self.const_uint(self.type_u16(), i as u64) + } + fn global_string(&self, string: &str) -> LValue<'gcc> { // TODO(antoyo): handle non-null-terminated strings. let string = self.context.new_string_literal(string); @@ -55,7 +59,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> 0 => { let context = &cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 8); + let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); let elements: Vec<_> = bytes .chunks_exact(8) .map(|arr| { @@ -76,7 +80,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> 4 => { let context = &cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 4); + let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); let elements: Vec<_> = bytes .chunks_exact(4) .map(|arr| { @@ -95,7 +99,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> _ => { let context = cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64); + let typ = new_array_type(context, None, byte_type, bytes.len() as u64); let elements: Vec<_> = bytes .iter() .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index d200d5319a93..03f207f45724 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -19,6 +19,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; +#[cfg(feature = "master")] +use rustc_session::config::DebugInfo; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; @@ -145,6 +147,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_f64_type: bool, supports_f128_type: bool, ) -> Self { + #[cfg(feature = "master")] + if tcx.sess.opts.debuginfo != DebugInfo::None { + context.set_filename(codegen_unit.name().as_str()); + } + let create_type = |ctype, rust_type| { let layout = tcx .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type)) @@ -194,8 +201,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in // gcc_jit_context_new_array_constructor (it should not use reinterpret_cast). - let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/; - let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/; + let i128_type = new_array_type(context, None, i64_type, 2)/*.get_aligned(i128_align)*/; + let u128_type = new_array_type(context, None, u64_type, 2)/*.get_aligned(u128_align)*/; (i128_type, u128_type) }; @@ -601,3 +608,17 @@ fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { TlsModel::Emulated => gccjit::TlsModel::GlobalDynamic, } } + +pub fn new_array_type<'gcc>( + context: &'gcc Context<'gcc>, + location: Option>, + typ: Type<'gcc>, + size: u64, +) -> Type<'gcc> { + #[cfg(feature = "master")] + { + context.new_array_type_u64(location, typ, size) + } + #[cfg(not(feature = "master"))] + context.new_array_type(location, typ, size) +} diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index e4130b221ee3..6450e2d4039c 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -151,7 +151,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -#[expect(clippy::let_and_return)] fn declare_raw_fn<'gcc>( cx: &CodegenCx<'gcc, '_>, name: &str, diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index b252c39c0c05..f5815e723392 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -2,24 +2,24 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(codegen_gcc_unwinding_inline_asm)] +#[diag("GCC backend does not support unwinding from inline asm")] pub(crate) struct UnwindingInlineAsm { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_gcc_copy_bitcode)] +#[diag("failed to copy bitcode to object file: {$err}")] pub(crate) struct CopyBitcode { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_gcc_lto_bitcode_from_rlib)] +#[diag("failed to get bitcode from object file for LTO ({$gcc_err})")] pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } #[derive(Diagnostic)] -#[diag(codegen_gcc_explicit_tail_calls_unsupported)] +#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] pub(crate) struct ExplicitTailCallsUnsupported; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 49de0b490e88..51612d604c8f 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -942,7 +942,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn float_to_int_cast( &self, signed: bool, - value: RValue<'gcc>, + mut value: RValue<'gcc>, dest_typ: Type<'gcc>, ) -> RValue<'gcc> { let value_type = value.get_type(); @@ -951,16 +951,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } debug_assert!(dest_typ.dyncast_array().is_some()); + let (dest_type, param_type) = match self.type_kind(value_type) { + TypeKind::Half => (Some(self.float_type), self.float_type), + _ => (None, value_type), + }; let name_suffix = match self.type_kind(value_type) { // cSpell:disable - TypeKind::Float => "sfti", + // Since we will cast Half to a float, we use sfti for both. + TypeKind::Half | TypeKind::Float => "sfti", TypeKind::Double => "dfti", + TypeKind::FP128 => "tfti", // cSpell:enable kind => panic!("cannot cast a {:?} to non-native integer", kind), }; let sign = if signed { "" } else { "uns" }; let func_name = format!("__fix{}{}", sign, name_suffix); - let param = self.context.new_parameter(None, value_type, "n"); + let param = self.context.new_parameter(None, param_type, "n"); let func = self.context.new_function( None, FunctionType::Extern, @@ -969,6 +975,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { func_name, false, ); + if let Some(dest_type) = dest_type { + value = self.context.new_cast(None, value, dest_type); + } self.context.new_call(None, func, &[value]) } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs index 43e7c352c34a..3c1698df6dec 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs @@ -6,47 +6,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) }; let Some((arch, name)) = name.split_once('.') else { - unimplemented!("***** unsupported LLVM intrinsic {}", name) + unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) }; + let old_arch_res = old_archs(arch, name); + if let ArchCheckResult::Ok(res) = old_arch_res { + return res; + } match arch { - "AMDGPU" => { - #[expect(non_snake_case)] - fn AMDGPU(name: &str, full_name: &str) -> &'static str { - match name { - // AMDGPU - "div.fixup.f32" => "__builtin_amdgpu_div_fixup", - "div.fixup.f64" => "__builtin_amdgpu_div_fixup", - "div.fixup.v2f64" => "__builtin_amdgpu_div_fixup", - "div.fixup.v4f32" => "__builtin_amdgpu_div_fixup", - "div.fmas.f32" => "__builtin_amdgpu_div_fmas", - "div.fmas.f64" => "__builtin_amdgpu_div_fmas", - "div.fmas.v2f64" => "__builtin_amdgpu_div_fmas", - "div.fmas.v4f32" => "__builtin_amdgpu_div_fmas", - "ldexp.f32" => "__builtin_amdgpu_ldexp", - "ldexp.f64" => "__builtin_amdgpu_ldexp", - "ldexp.v2f64" => "__builtin_amdgpu_ldexp", - "ldexp.v4f32" => "__builtin_amdgpu_ldexp", - "rcp.f32" => "__builtin_amdgpu_rcp", - "rcp.f64" => "__builtin_amdgpu_rcp", - "rcp.v2f64" => "__builtin_amdgpu_rcp", - "rcp.v4f32" => "__builtin_amdgpu_rcp", - "rsq.clamped.f32" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.f64" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.v2f64" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.v4f32" => "__builtin_amdgpu_rsq_clamped", - "rsq.f32" => "__builtin_amdgpu_rsq", - "rsq.f64" => "__builtin_amdgpu_rsq", - "rsq.v2f64" => "__builtin_amdgpu_rsq", - "rsq.v4f32" => "__builtin_amdgpu_rsq", - "trig.preop.f32" => "__builtin_amdgpu_trig_preop", - "trig.preop.f64" => "__builtin_amdgpu_trig_preop", - "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", - "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - AMDGPU(name, full_name) - } "aarch64" => { fn aarch64(name: &str, full_name: &str) -> &'static str { match name { @@ -58,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", "sve.aese" => "__builtin_sve_svaese_u8", @@ -448,6 +415,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", + "s.wakeup.barrier" => "__builtin_amdgcn_s_wakeup_barrier", "sad.hi.u8" => "__builtin_amdgcn_sad_hi_u8", "sad.u16" => "__builtin_amdgcn_sad_u16", "sad.u8" => "__builtin_amdgcn_sad_u8", @@ -537,8 +505,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ldcl" => "__builtin_arm_ldcl", "mcr" => "__builtin_arm_mcr", "mcr2" => "__builtin_arm_mcr2", - "mcrr" => "__builtin_arm_mcrr", - "mcrr2" => "__builtin_arm_mcrr2", "mrc" => "__builtin_arm_mrc", "mrc2" => "__builtin_arm_mrc2", "qadd" => "__builtin_arm_qadd", @@ -595,7 +561,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "stcl" => "__builtin_arm_stcl", "sxtab16" => "__builtin_arm_sxtab16", "sxtb16" => "__builtin_arm_sxtb16", - "thread.pointer" => "__builtin_thread_pointer", "uadd16" => "__builtin_arm_uadd16", "uadd8" => "__builtin_arm_uadd8", "uasx" => "__builtin_arm_uasx", @@ -646,16 +611,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } bpf(name, full_name) } - "cuda" => { - fn cuda(name: &str, full_name: &str) -> &'static str { - match name { - // cuda - "syncthreads" => "__syncthreads", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - cuda(name, full_name) - } "hexagon" => { fn hexagon(name: &str, full_name: &str) -> &'static str { match name { @@ -959,19 +914,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "F2.dfcmpge" => "__builtin_HEXAGON_F2_dfcmpge", "F2.dfcmpgt" => "__builtin_HEXAGON_F2_dfcmpgt", "F2.dfcmpuo" => "__builtin_HEXAGON_F2_dfcmpuo", - "F2.dffixupd" => "__builtin_HEXAGON_F2_dffixupd", - "F2.dffixupn" => "__builtin_HEXAGON_F2_dffixupn", - "F2.dffixupr" => "__builtin_HEXAGON_F2_dffixupr", - "F2.dffma" => "__builtin_HEXAGON_F2_dffma", - "F2.dffma.lib" => "__builtin_HEXAGON_F2_dffma_lib", - "F2.dffma.sc" => "__builtin_HEXAGON_F2_dffma_sc", - "F2.dffms" => "__builtin_HEXAGON_F2_dffms", - "F2.dffms.lib" => "__builtin_HEXAGON_F2_dffms_lib", "F2.dfimm.n" => "__builtin_HEXAGON_F2_dfimm_n", "F2.dfimm.p" => "__builtin_HEXAGON_F2_dfimm_p", "F2.dfmax" => "__builtin_HEXAGON_F2_dfmax", "F2.dfmin" => "__builtin_HEXAGON_F2_dfmin", - "F2.dfmpy" => "__builtin_HEXAGON_F2_dfmpy", "F2.dfmpyfix" => "__builtin_HEXAGON_F2_dfmpyfix", "F2.dfmpyhh" => "__builtin_HEXAGON_F2_dfmpyhh", "F2.dfmpylh" => "__builtin_HEXAGON_F2_dfmpylh", @@ -1398,7 +1344,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "S2.asr.r.vw" => "__builtin_HEXAGON_S2_asr_r_vw", "S2.brev" => "__builtin_HEXAGON_S2_brev", "S2.brevp" => "__builtin_HEXAGON_S2_brevp", - "S2.cabacencbin" => "__builtin_HEXAGON_S2_cabacencbin", "S2.cl0" => "__builtin_HEXAGON_S2_cl0", "S2.cl0p" => "__builtin_HEXAGON_S2_cl0p", "S2.cl1" => "__builtin_HEXAGON_S2_cl1", @@ -1569,7 +1514,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "S6.vsplatrbp" => "__builtin_HEXAGON_S6_vsplatrbp", "S6.vtrunehb.ppp" => "__builtin_HEXAGON_S6_vtrunehb_ppp", "S6.vtrunohb.ppp" => "__builtin_HEXAGON_S6_vtrunohb_ppp", - "SI.to.SXTHI.asrh" => "__builtin_SI_to_SXTHI_asrh", "V6.extractw" => "__builtin_HEXAGON_V6_extractw", "V6.extractw.128B" => "__builtin_HEXAGON_V6_extractw_128B", "V6.get.qfext" => "__builtin_HEXAGON_V6_get_qfext", @@ -2160,14 +2104,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vlsrwv.128B" => "__builtin_HEXAGON_V6_vlsrwv_128B", "V6.vlut4" => "__builtin_HEXAGON_V6_vlut4", "V6.vlut4.128B" => "__builtin_HEXAGON_V6_vlut4_128B", - "V6.vlutb" => "__builtin_HEXAGON_V6_vlutb", - "V6.vlutb.128B" => "__builtin_HEXAGON_V6_vlutb_128B", - "V6.vlutb.acc" => "__builtin_HEXAGON_V6_vlutb_acc", - "V6.vlutb.acc.128B" => "__builtin_HEXAGON_V6_vlutb_acc_128B", - "V6.vlutb.dv" => "__builtin_HEXAGON_V6_vlutb_dv", - "V6.vlutb.dv.128B" => "__builtin_HEXAGON_V6_vlutb_dv_128B", - "V6.vlutb.dv.acc" => "__builtin_HEXAGON_V6_vlutb_dv_acc", - "V6.vlutb.dv.acc.128B" => "__builtin_HEXAGON_V6_vlutb_dv_acc_128B", "V6.vlutvvb" => "__builtin_HEXAGON_V6_vlutvvb", "V6.vlutvvb.128B" => "__builtin_HEXAGON_V6_vlutvvb_128B", "V6.vlutvvb.nm" => "__builtin_HEXAGON_V6_vlutvvb_nm", @@ -2669,17 +2605,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "Y6.dmresume" => "__builtin_HEXAGON_Y6_dmresume", "Y6.dmstart" => "__builtin_HEXAGON_Y6_dmstart", "Y6.dmwait" => "__builtin_HEXAGON_Y6_dmwait", - "brev.ldb" => "__builtin_brev_ldb", - "brev.ldd" => "__builtin_brev_ldd", - "brev.ldh" => "__builtin_brev_ldh", - "brev.ldub" => "__builtin_brev_ldub", - "brev.lduh" => "__builtin_brev_lduh", - "brev.ldw" => "__builtin_brev_ldw", - "brev.stb" => "__builtin_brev_stb", - "brev.std" => "__builtin_brev_std", - "brev.sth" => "__builtin_brev_sth", - "brev.sthhi" => "__builtin_brev_sthhi", - "brev.stw" => "__builtin_brev_stw", "circ.ldb" => "__builtin_circ_ldb", "circ.ldd" => "__builtin_circ_ldd", "circ.ldh" => "__builtin_circ_ldh", @@ -2691,7 +2616,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "circ.sth" => "__builtin_circ_sth", "circ.sthhi" => "__builtin_circ_sthhi", "circ.stw" => "__builtin_circ_stw", - "mm256i.vaddw" => "__builtin__mm256i_vaddw", "prefetch" => "__builtin_HEXAGON_prefetch", "vmemcpy" => "__builtin_hexagon_vmemcpy", "vmemset" => "__builtin_hexagon_vmemset", @@ -4910,45 +4834,37 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { fn nvvm(name: &str, full_name: &str) -> &'static str { match name { // nvvm - "abs.i" => "__nvvm_abs_i", - "abs.ll" => "__nvvm_abs_ll", "activemask" => "__nvvm_activemask", "add.rm.d" => "__nvvm_add_rm_d", "add.rm.f" => "__nvvm_add_rm_f", "add.rm.ftz.f" => "__nvvm_add_rm_ftz_f", + "add.rm.ftz.sat.f" => "__nvvm_add_rm_ftz_sat_f", + "add.rm.sat.f" => "__nvvm_add_rm_sat_f", "add.rn.d" => "__nvvm_add_rn_d", "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", + "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.sat.f" => "__nvvm_add_rn_sat_f", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", + "add.rp.ftz.sat.f" => "__nvvm_add_rp_ftz_sat_f", + "add.rp.sat.f" => "__nvvm_add_rp_sat_f", "add.rz.d" => "__nvvm_add_rz_d", "add.rz.f" => "__nvvm_add_rz_f", "add.rz.ftz.f" => "__nvvm_add_rz_ftz_f", - "bar.sync" => "__nvvm_bar_sync", + "add.rz.ftz.sat.f" => "__nvvm_add_rz_ftz_sat_f", + "add.rz.sat.f" => "__nvvm_add_rz_sat_f", "bar.warp.sync" => "__nvvm_bar_warp_sync", - "barrier0" => "__nvvm_bar0", - // [DUPLICATE]: "barrier0" => "__syncthreads", - "barrier0.and" => "__nvvm_bar0_and", - "barrier0.or" => "__nvvm_bar0_or", - "barrier0.popc" => "__nvvm_bar0_popc", "bf16x2.to.ue8m0x2.rp" => "__nvvm_bf16x2_to_ue8m0x2_rp", "bf16x2.to.ue8m0x2.rp.satfinite" => "__nvvm_bf16x2_to_ue8m0x2_rp_satfinite", "bf16x2.to.ue8m0x2.rz" => "__nvvm_bf16x2_to_ue8m0x2_rz", "bf16x2.to.ue8m0x2.rz.satfinite" => "__nvvm_bf16x2_to_ue8m0x2_rz_satfinite", "bf2h.rn" => "__nvvm_bf2h_rn", "bf2h.rn.ftz" => "__nvvm_bf2h_rn_ftz", - "bitcast.d2ll" => "__nvvm_bitcast_d2ll", - "bitcast.f2i" => "__nvvm_bitcast_f2i", - "bitcast.i2f" => "__nvvm_bitcast_i2f", - "bitcast.ll2d" => "__nvvm_bitcast_ll2d", - "brev32" => "__nvvm_brev32", - "brev64" => "__nvvm_brev64", "ceil.d" => "__nvvm_ceil_d", "ceil.f" => "__nvvm_ceil_f", "ceil.ftz.f" => "__nvvm_ceil_ftz_f", - "clz.i" => "__nvvm_clz_i", - "clz.ll" => "__nvvm_clz_ll", "cos.approx.f" => "__nvvm_cos_approx_f", "cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f", "cp.async.commit.group" => "__nvvm_cp_async_commit_group", @@ -5012,9 +4928,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "e4m3x2.to.f16x2.rn.relu" => "__nvvm_e4m3x2_to_f16x2_rn_relu", "e5m2x2.to.f16x2.rn" => "__nvvm_e5m2x2_to_f16x2_rn", "e5m2x2.to.f16x2.rn.relu" => "__nvvm_e5m2x2_to_f16x2_rn_relu", - "ex2.approx.d" => "__nvvm_ex2_approx_d", - "ex2.approx.f" => "__nvvm_ex2_approx_f", - "ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", "exit" => "__nvvm_exit", "f16x2.to.e4m3x2.rn" => "__nvvm_f16x2_to_e4m3x2_rn", "f16x2.to.e4m3x2.rn.relu" => "__nvvm_f16x2_to_e4m3x2_rn_relu", @@ -5100,9 +5013,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "__nvvm_f32x4_to_e5m2x4_rs_relu_satfinite" } "f32x4.to.e5m2x4.rs.satfinite" => "__nvvm_f32x4_to_e5m2x4_rs_satfinite", - "fabs.d" => "__nvvm_fabs_d", - "fabs.f" => "__nvvm_fabs_f", - "fabs.ftz.f" => "__nvvm_fabs_ftz_f", "ff.to.e2m1x2.rn.relu.satfinite" => "__nvvm_ff_to_e2m1x2_rn_relu_satfinite", "ff.to.e2m1x2.rn.satfinite" => "__nvvm_ff_to_e2m1x2_rn_satfinite", "ff.to.e2m3x2.rn.relu.satfinite" => "__nvvm_ff_to_e2m3x2_rn_relu_satfinite", @@ -5147,6 +5057,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rm.d" => "__nvvm_fma_rm_d", "fma.rm.f" => "__nvvm_fma_rm_f", "fma.rm.ftz.f" => "__nvvm_fma_rm_ftz_f", + "fma.rm.ftz.sat.f" => "__nvvm_fma_rm_ftz_sat_f", + "fma.rm.sat.f" => "__nvvm_fma_rm_sat_f", "fma.rn.bf16" => "__nvvm_fma_rn_bf16", "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", @@ -5158,16 +5070,22 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", + "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", + "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", "fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f", + "fma.rp.ftz.sat.f" => "__nvvm_fma_rp_ftz_sat_f", + "fma.rp.sat.f" => "__nvvm_fma_rp_sat_f", "fma.rz.d" => "__nvvm_fma_rz_d", "fma.rz.f" => "__nvvm_fma_rz_f", "fma.rz.ftz.f" => "__nvvm_fma_rz_ftz_f", + "fma.rz.ftz.sat.f" => "__nvvm_fma_rz_ftz_sat_f", + "fma.rz.sat.f" => "__nvvm_fma_rz_sat_f", "fmax.bf16" => "__nvvm_fmax_bf16", "fmax.bf16x2" => "__nvvm_fmax_bf16x2", "fmax.d" => "__nvvm_fmax_d", @@ -5219,7 +5137,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2", "fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f", "fns" => "__nvvm_fns", - "h2f" => "__nvvm_h2f", "i2d.rm" => "__nvvm_i2d_rm", "i2d.rn" => "__nvvm_i2d_rn", "i2d.rp" => "__nvvm_i2d_rp", @@ -5250,10 +5167,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "lohi.i2d" => "__nvvm_lohi_i2d", "match.any.sync.i32" => "__nvvm_match_any_sync_i32", "match.any.sync.i64" => "__nvvm_match_any_sync_i64", - "max.i" => "__nvvm_max_i", - "max.ll" => "__nvvm_max_ll", - "max.ui" => "__nvvm_max_ui", - "max.ull" => "__nvvm_max_ull", "mbarrier.arrive" => "__nvvm_mbarrier_arrive", "mbarrier.arrive.drop" => "__nvvm_mbarrier_arrive_drop", "mbarrier.arrive.drop.noComplete" => "__nvvm_mbarrier_arrive_drop_noComplete", @@ -5276,10 +5189,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "membar.cta" => "__nvvm_membar_cta", "membar.gl" => "__nvvm_membar_gl", "membar.sys" => "__nvvm_membar_sys", - "min.i" => "__nvvm_min_i", - "min.ll" => "__nvvm_min_ll", - "min.ui" => "__nvvm_min_ui", - "min.ull" => "__nvvm_min_ull", "mul.rm.d" => "__nvvm_mul_rm_d", "mul.rm.f" => "__nvvm_mul_rm_f", "mul.rm.ftz.f" => "__nvvm_mul_rm_ftz_f", @@ -5304,8 +5213,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "neg.bf16" => "__nvvm_neg_bf16", "neg.bf16x2" => "__nvvm_neg_bf16x2", "pm.event.mask" => "__nvvm_pm_event_mask", - "popc.i" => "__nvvm_popc_i", - "popc.ll" => "__nvvm_popc_ll", "prmt" => "__nvvm_prmt", "rcp.approx.ftz.d" => "__nvvm_rcp_approx_ftz_d", "rcp.approx.ftz.f" => "__nvvm_rcp_approx_ftz_f", @@ -5322,9 +5229,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "rcp.rz.f" => "__nvvm_rcp_rz_f", "rcp.rz.ftz.f" => "__nvvm_rcp_rz_ftz_f", "read.ptx.sreg.clock" => "__nvvm_read_ptx_sreg_clock", - // [DUPLICATE]: "read.ptx.sreg.clock" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.clock64" => "__nvvm_read_ptx_sreg_clock64", - // [DUPLICATE]: "read.ptx.sreg.clock64" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.ctaid.w" => "__nvvm_read_ptx_sreg_ctaid_w", "read.ptx.sreg.ctaid.x" => "__nvvm_read_ptx_sreg_ctaid_x", "read.ptx.sreg.ctaid.y" => "__nvvm_read_ptx_sreg_ctaid_y", @@ -5364,49 +5269,34 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "read.ptx.sreg.globaltimer" => "__nvvm_read_ptx_sreg_globaltimer", "read.ptx.sreg.globaltimer.lo" => "__nvvm_read_ptx_sreg_globaltimer_lo", "read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_gridid", - // [DUPLICATE]: "read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_laneid", - // [DUPLICATE]: "read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.eq" => "__nvvm_read_ptx_sreg_lanemask_eq", - // [DUPLICATE]: "read.ptx.sreg.lanemask.eq" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.ge" => "__nvvm_read_ptx_sreg_lanemask_ge", - // [DUPLICATE]: "read.ptx.sreg.lanemask.ge" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.gt" => "__nvvm_read_ptx_sreg_lanemask_gt", - // [DUPLICATE]: "read.ptx.sreg.lanemask.gt" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.le" => "__nvvm_read_ptx_sreg_lanemask_le", - // [DUPLICATE]: "read.ptx.sreg.lanemask.le" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.lt" => "__nvvm_read_ptx_sreg_lanemask_lt", - // [DUPLICATE]: "read.ptx.sreg.lanemask.lt" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.nctaid.w" => "__nvvm_read_ptx_sreg_nctaid_w", "read.ptx.sreg.nctaid.x" => "__nvvm_read_ptx_sreg_nctaid_x", "read.ptx.sreg.nctaid.y" => "__nvvm_read_ptx_sreg_nctaid_y", "read.ptx.sreg.nctaid.z" => "__nvvm_read_ptx_sreg_nctaid_z", "read.ptx.sreg.nsmid" => "__nvvm_read_ptx_sreg_nsmid", - // [DUPLICATE]: "read.ptx.sreg.nsmid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.ntid.w" => "__nvvm_read_ptx_sreg_ntid_w", "read.ptx.sreg.ntid.x" => "__nvvm_read_ptx_sreg_ntid_x", "read.ptx.sreg.ntid.y" => "__nvvm_read_ptx_sreg_ntid_y", "read.ptx.sreg.ntid.z" => "__nvvm_read_ptx_sreg_ntid_z", "read.ptx.sreg.nwarpid" => "__nvvm_read_ptx_sreg_nwarpid", - // [DUPLICATE]: "read.ptx.sreg.nwarpid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm0" => "__nvvm_read_ptx_sreg_pm0", - // [DUPLICATE]: "read.ptx.sreg.pm0" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_pm1", - // [DUPLICATE]: "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_pm2", - // [DUPLICATE]: "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_pm3", - // [DUPLICATE]: "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_", + "read.ptx.sreg.pm4" => "__nvvm_read_ptx_sreg_pm4", "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_smid", - // [DUPLICATE]: "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.tid.w" => "__nvvm_read_ptx_sreg_tid_w", "read.ptx.sreg.tid.x" => "__nvvm_read_ptx_sreg_tid_x", "read.ptx.sreg.tid.y" => "__nvvm_read_ptx_sreg_tid_y", "read.ptx.sreg.tid.z" => "__nvvm_read_ptx_sreg_tid_z", "read.ptx.sreg.warpid" => "__nvvm_read_ptx_sreg_warpid", - // [DUPLICATE]: "read.ptx.sreg.warpid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.warpsize" => "__nvvm_read_ptx_sreg_warpsize", - // [DUPLICATE]: "read.ptx.sreg.warpsize" => "__nvvm_read_ptx_sreg_", "redux.sync.add" => "__nvvm_redux_sync_add", "redux.sync.and" => "__nvvm_redux_sync_and", "redux.sync.fmax" => "__nvvm_redux_sync_fmax", @@ -5424,9 +5314,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "redux.sync.umin" => "__nvvm_redux_sync_umin", "redux.sync.xor" => "__nvvm_redux_sync_xor", "reflect" => "__nvvm_reflect", - "rotate.b32" => "__nvvm_rotate_b32", - "rotate.b64" => "__nvvm_rotate_b64", - "rotate.right.b64" => "__nvvm_rotate_right_b64", "round.d" => "__nvvm_round_d", "round.f" => "__nvvm_round_f", "round.ftz.f" => "__nvvm_round_ftz_f", @@ -5692,7 +5579,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sust.p.3d.v4i16.trap" => "__nvvm_sust_p_3d_v4i16_trap", "sust.p.3d.v4i32.trap" => "__nvvm_sust_p_3d_v4i32_trap", "sust.p.3d.v4i8.trap" => "__nvvm_sust_p_3d_v4i8_trap", - "swap.lo.hi.b64" => "__nvvm_swap_lo_hi_b64", "trunc.d" => "__nvvm_trunc_d", "trunc.f" => "__nvvm_trunc_f", "trunc.ftz.f" => "__nvvm_trunc_ftz_f", @@ -6132,89 +6018,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "packed2zoned" => "__builtin_ppc_packed2zoned", "pdepd" => "__builtin_pdepd", "pextd" => "__builtin_pextd", - "qpx.qvfabs" => "__builtin_qpx_qvfabs", - "qpx.qvfadd" => "__builtin_qpx_qvfadd", - "qpx.qvfadds" => "__builtin_qpx_qvfadds", - "qpx.qvfcfid" => "__builtin_qpx_qvfcfid", - "qpx.qvfcfids" => "__builtin_qpx_qvfcfids", - "qpx.qvfcfidu" => "__builtin_qpx_qvfcfidu", - "qpx.qvfcfidus" => "__builtin_qpx_qvfcfidus", - "qpx.qvfcmpeq" => "__builtin_qpx_qvfcmpeq", - "qpx.qvfcmpgt" => "__builtin_qpx_qvfcmpgt", - "qpx.qvfcmplt" => "__builtin_qpx_qvfcmplt", - "qpx.qvfcpsgn" => "__builtin_qpx_qvfcpsgn", - "qpx.qvfctid" => "__builtin_qpx_qvfctid", - "qpx.qvfctidu" => "__builtin_qpx_qvfctidu", - "qpx.qvfctiduz" => "__builtin_qpx_qvfctiduz", - "qpx.qvfctidz" => "__builtin_qpx_qvfctidz", - "qpx.qvfctiw" => "__builtin_qpx_qvfctiw", - "qpx.qvfctiwu" => "__builtin_qpx_qvfctiwu", - "qpx.qvfctiwuz" => "__builtin_qpx_qvfctiwuz", - "qpx.qvfctiwz" => "__builtin_qpx_qvfctiwz", - "qpx.qvflogical" => "__builtin_qpx_qvflogical", - "qpx.qvfmadd" => "__builtin_qpx_qvfmadd", - "qpx.qvfmadds" => "__builtin_qpx_qvfmadds", - "qpx.qvfmsub" => "__builtin_qpx_qvfmsub", - "qpx.qvfmsubs" => "__builtin_qpx_qvfmsubs", - "qpx.qvfmul" => "__builtin_qpx_qvfmul", - "qpx.qvfmuls" => "__builtin_qpx_qvfmuls", - "qpx.qvfnabs" => "__builtin_qpx_qvfnabs", - "qpx.qvfneg" => "__builtin_qpx_qvfneg", - "qpx.qvfnmadd" => "__builtin_qpx_qvfnmadd", - "qpx.qvfnmadds" => "__builtin_qpx_qvfnmadds", - "qpx.qvfnmsub" => "__builtin_qpx_qvfnmsub", - "qpx.qvfnmsubs" => "__builtin_qpx_qvfnmsubs", - "qpx.qvfperm" => "__builtin_qpx_qvfperm", - "qpx.qvfre" => "__builtin_qpx_qvfre", - "qpx.qvfres" => "__builtin_qpx_qvfres", - "qpx.qvfrim" => "__builtin_qpx_qvfrim", - "qpx.qvfrin" => "__builtin_qpx_qvfrin", - "qpx.qvfrip" => "__builtin_qpx_qvfrip", - "qpx.qvfriz" => "__builtin_qpx_qvfriz", - "qpx.qvfrsp" => "__builtin_qpx_qvfrsp", - "qpx.qvfrsqrte" => "__builtin_qpx_qvfrsqrte", - "qpx.qvfrsqrtes" => "__builtin_qpx_qvfrsqrtes", - "qpx.qvfsel" => "__builtin_qpx_qvfsel", - "qpx.qvfsub" => "__builtin_qpx_qvfsub", - "qpx.qvfsubs" => "__builtin_qpx_qvfsubs", - "qpx.qvftstnan" => "__builtin_qpx_qvftstnan", - "qpx.qvfxmadd" => "__builtin_qpx_qvfxmadd", - "qpx.qvfxmadds" => "__builtin_qpx_qvfxmadds", - "qpx.qvfxmul" => "__builtin_qpx_qvfxmul", - "qpx.qvfxmuls" => "__builtin_qpx_qvfxmuls", - "qpx.qvfxxcpnmadd" => "__builtin_qpx_qvfxxcpnmadd", - "qpx.qvfxxcpnmadds" => "__builtin_qpx_qvfxxcpnmadds", - "qpx.qvfxxmadd" => "__builtin_qpx_qvfxxmadd", - "qpx.qvfxxmadds" => "__builtin_qpx_qvfxxmadds", - "qpx.qvfxxnpmadd" => "__builtin_qpx_qvfxxnpmadd", - "qpx.qvfxxnpmadds" => "__builtin_qpx_qvfxxnpmadds", - "qpx.qvgpci" => "__builtin_qpx_qvgpci", - "qpx.qvlfcd" => "__builtin_qpx_qvlfcd", - "qpx.qvlfcda" => "__builtin_qpx_qvlfcda", - "qpx.qvlfcs" => "__builtin_qpx_qvlfcs", - "qpx.qvlfcsa" => "__builtin_qpx_qvlfcsa", - "qpx.qvlfd" => "__builtin_qpx_qvlfd", - "qpx.qvlfda" => "__builtin_qpx_qvlfda", - "qpx.qvlfiwa" => "__builtin_qpx_qvlfiwa", - "qpx.qvlfiwaa" => "__builtin_qpx_qvlfiwaa", - "qpx.qvlfiwz" => "__builtin_qpx_qvlfiwz", - "qpx.qvlfiwza" => "__builtin_qpx_qvlfiwza", - "qpx.qvlfs" => "__builtin_qpx_qvlfs", - "qpx.qvlfsa" => "__builtin_qpx_qvlfsa", - "qpx.qvlpcld" => "__builtin_qpx_qvlpcld", - "qpx.qvlpcls" => "__builtin_qpx_qvlpcls", - "qpx.qvlpcrd" => "__builtin_qpx_qvlpcrd", - "qpx.qvlpcrs" => "__builtin_qpx_qvlpcrs", - "qpx.qvstfcd" => "__builtin_qpx_qvstfcd", - "qpx.qvstfcda" => "__builtin_qpx_qvstfcda", - "qpx.qvstfcs" => "__builtin_qpx_qvstfcs", - "qpx.qvstfcsa" => "__builtin_qpx_qvstfcsa", - "qpx.qvstfd" => "__builtin_qpx_qvstfd", - "qpx.qvstfda" => "__builtin_qpx_qvstfda", - "qpx.qvstfiw" => "__builtin_qpx_qvstfiw", - "qpx.qvstfiwa" => "__builtin_qpx_qvstfiwa", - "qpx.qvstfs" => "__builtin_qpx_qvstfs", - "qpx.qvstfsa" => "__builtin_qpx_qvstfsa", "readflm" => "__builtin_readflm", "rlwimi" => "__builtin_ppc_rlwimi", "rlwnm" => "__builtin_ppc_rlwnm", @@ -6329,33 +6132,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } ppc(name, full_name) } - "ptx" => { - fn ptx(name: &str, full_name: &str) -> &'static str { - match name { - // ptx - "bar.sync" => "__builtin_ptx_bar_sync", - "read.clock" => "__builtin_ptx_read_clock", - "read.clock64" => "__builtin_ptx_read_clock64", - "read.gridid" => "__builtin_ptx_read_gridid", - "read.laneid" => "__builtin_ptx_read_laneid", - "read.lanemask.eq" => "__builtin_ptx_read_lanemask_eq", - "read.lanemask.ge" => "__builtin_ptx_read_lanemask_ge", - "read.lanemask.gt" => "__builtin_ptx_read_lanemask_gt", - "read.lanemask.le" => "__builtin_ptx_read_lanemask_le", - "read.lanemask.lt" => "__builtin_ptx_read_lanemask_lt", - "read.nsmid" => "__builtin_ptx_read_nsmid", - "read.nwarpid" => "__builtin_ptx_read_nwarpid", - "read.pm0" => "__builtin_ptx_read_pm0", - "read.pm1" => "__builtin_ptx_read_pm1", - "read.pm2" => "__builtin_ptx_read_pm2", - "read.pm3" => "__builtin_ptx_read_pm3", - "read.smid" => "__builtin_ptx_read_smid", - "read.warpid" => "__builtin_ptx_read_warpid", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - ptx(name, full_name) - } "r600" => { fn r600(name: &str, full_name: &str) -> &'static str { match name { @@ -6610,6 +6386,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { fn spv(name: &str, full_name: &str) -> &'static str { match name { // spv + "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { @@ -6617,6 +6394,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", + "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -7902,10 +7680,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "aadd64" => "__builtin_ia32_aadd64", "aand32" => "__builtin_ia32_aand32", "aand64" => "__builtin_ia32_aand64", - "addcarry.u32" => "__builtin_ia32_addcarry_u32", - "addcarry.u64" => "__builtin_ia32_addcarry_u64", - "addcarryx.u32" => "__builtin_ia32_addcarryx_u32", - "addcarryx.u64" => "__builtin_ia32_addcarryx_u64", "aesni.aesdec" => "__builtin_ia32_aesdec128", "aesni.aesdec.256" => "__builtin_ia32_aesdec256", "aesni.aesdec.512" => "__builtin_ia32_aesdec512", @@ -7924,18 +7698,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "aor64" => "__builtin_ia32_aor64", "avx.addsub.pd.256" => "__builtin_ia32_addsubpd256", "avx.addsub.ps.256" => "__builtin_ia32_addsubps256", - "avx.blend.pd.256" => "__builtin_ia32_blendpd256", - "avx.blend.ps.256" => "__builtin_ia32_blendps256", "avx.blendv.pd.256" => "__builtin_ia32_blendvpd256", "avx.blendv.ps.256" => "__builtin_ia32_blendvps256", - "avx.cmp.pd.256" => "__builtin_ia32_cmppd256", - "avx.cmp.ps.256" => "__builtin_ia32_cmpps256", "avx.cvt.pd2.ps.256" => "__builtin_ia32_cvtpd2ps256", "avx.cvt.pd2dq.256" => "__builtin_ia32_cvtpd2dq256", - "avx.cvt.ps2.pd.256" => "__builtin_ia32_cvtps2pd256", "avx.cvt.ps2dq.256" => "__builtin_ia32_cvtps2dq256", - "avx.cvtdq2.pd.256" => "__builtin_ia32_cvtdq2pd256", - "avx.cvtdq2.ps.256" => "__builtin_ia32_cvtdq2ps256", "avx.cvtt.pd2dq.256" => "__builtin_ia32_cvttpd2dq256", "avx.cvtt.ps2dq.256" => "__builtin_ia32_cvttps2dq256", "avx.dp.ps.256" => "__builtin_ia32_dpps256", @@ -7962,25 +7729,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx.ptestnzc.256" => "__builtin_ia32_ptestnzc256", "avx.ptestz.256" => "__builtin_ia32_ptestz256", "avx.rcp.ps.256" => "__builtin_ia32_rcpps256", - "avx.round.pd.256" => "__builtin_ia32_roundpd256", - "avx.round.ps.256" => "__builtin_ia32_roundps256", "avx.rsqrt.ps.256" => "__builtin_ia32_rsqrtps256", - "avx.sqrt.pd.256" => "__builtin_ia32_sqrtpd256", - "avx.sqrt.ps.256" => "__builtin_ia32_sqrtps256", - "avx.storeu.dq.256" => "__builtin_ia32_storedqu256", - "avx.storeu.pd.256" => "__builtin_ia32_storeupd256", - "avx.storeu.ps.256" => "__builtin_ia32_storeups256", - "avx.vbroadcastf128.pd.256" => "__builtin_ia32_vbroadcastf128_pd256", - "avx.vbroadcastf128.ps.256" => "__builtin_ia32_vbroadcastf128_ps256", - "avx.vextractf128.pd.256" => "__builtin_ia32_vextractf128_pd256", - "avx.vextractf128.ps.256" => "__builtin_ia32_vextractf128_ps256", - "avx.vextractf128.si.256" => "__builtin_ia32_vextractf128_si256", - "avx.vinsertf128.pd.256" => "__builtin_ia32_vinsertf128_pd256", - "avx.vinsertf128.ps.256" => "__builtin_ia32_vinsertf128_ps256", - "avx.vinsertf128.si.256" => "__builtin_ia32_vinsertf128_si256", - "avx.vperm2f128.pd.256" => "__builtin_ia32_vperm2f128_pd256", - "avx.vperm2f128.ps.256" => "__builtin_ia32_vperm2f128_ps256", - "avx.vperm2f128.si.256" => "__builtin_ia32_vperm2f128_si256", "avx.vpermilvar.pd" => "__builtin_ia32_vpermilvarpd", "avx.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256", "avx.vpermilvar.ps" => "__builtin_ia32_vpermilvarps", @@ -8265,33 +8014,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.maskstore.d.256" => "__builtin_ia32_maskstored256", "avx2.maskstore.q" => "__builtin_ia32_maskstoreq", "avx2.maskstore.q.256" => "__builtin_ia32_maskstoreq256", - "avx2.movntdqa" => "__builtin_ia32_movntdqa256", "avx2.mpsadbw" => "__builtin_ia32_mpsadbw256", - "avx2.pabs.b" => "__builtin_ia32_pabsb256", - "avx2.pabs.d" => "__builtin_ia32_pabsd256", - "avx2.pabs.w" => "__builtin_ia32_pabsw256", "avx2.packssdw" => "__builtin_ia32_packssdw256", "avx2.packsswb" => "__builtin_ia32_packsswb256", "avx2.packusdw" => "__builtin_ia32_packusdw256", "avx2.packuswb" => "__builtin_ia32_packuswb256", - "avx2.padds.b" => "__builtin_ia32_paddsb256", - "avx2.padds.w" => "__builtin_ia32_paddsw256", - "avx2.paddus.b" => "__builtin_ia32_paddusb256", - "avx2.paddus.w" => "__builtin_ia32_paddusw256", "avx2.pavg.b" => "__builtin_ia32_pavgb256", "avx2.pavg.w" => "__builtin_ia32_pavgw256", - "avx2.pblendd.128" => "__builtin_ia32_pblendd128", - "avx2.pblendd.256" => "__builtin_ia32_pblendd256", "avx2.pblendvb" => "__builtin_ia32_pblendvb256", - "avx2.pblendw" => "__builtin_ia32_pblendw256", - "avx2.pbroadcastb.128" => "__builtin_ia32_pbroadcastb128", - "avx2.pbroadcastb.256" => "__builtin_ia32_pbroadcastb256", - "avx2.pbroadcastd.128" => "__builtin_ia32_pbroadcastd128", - "avx2.pbroadcastd.256" => "__builtin_ia32_pbroadcastd256", - "avx2.pbroadcastq.128" => "__builtin_ia32_pbroadcastq128", - "avx2.pbroadcastq.256" => "__builtin_ia32_pbroadcastq256", - "avx2.pbroadcastw.128" => "__builtin_ia32_pbroadcastw128", - "avx2.pbroadcastw.256" => "__builtin_ia32_pbroadcastw256", "avx2.permd" => "__builtin_ia32_permvarsi256", "avx2.permps" => "__builtin_ia32_permvarsf256", "avx2.phadd.d" => "__builtin_ia32_phaddd256", @@ -8302,44 +8032,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.phsub.w" => "__builtin_ia32_phsubw256", "avx2.pmadd.ub.sw" => "__builtin_ia32_pmaddubsw256", "avx2.pmadd.wd" => "__builtin_ia32_pmaddwd256", - "avx2.pmaxs.b" => "__builtin_ia32_pmaxsb256", - "avx2.pmaxs.d" => "__builtin_ia32_pmaxsd256", - "avx2.pmaxs.w" => "__builtin_ia32_pmaxsw256", - "avx2.pmaxu.b" => "__builtin_ia32_pmaxub256", - "avx2.pmaxu.d" => "__builtin_ia32_pmaxud256", - "avx2.pmaxu.w" => "__builtin_ia32_pmaxuw256", - "avx2.pmins.b" => "__builtin_ia32_pminsb256", - "avx2.pmins.d" => "__builtin_ia32_pminsd256", - "avx2.pmins.w" => "__builtin_ia32_pminsw256", - "avx2.pminu.b" => "__builtin_ia32_pminub256", - "avx2.pminu.d" => "__builtin_ia32_pminud256", - "avx2.pminu.w" => "__builtin_ia32_pminuw256", "avx2.pmovmskb" => "__builtin_ia32_pmovmskb256", - "avx2.pmovsxbd" => "__builtin_ia32_pmovsxbd256", - "avx2.pmovsxbq" => "__builtin_ia32_pmovsxbq256", - "avx2.pmovsxbw" => "__builtin_ia32_pmovsxbw256", - "avx2.pmovsxdq" => "__builtin_ia32_pmovsxdq256", - "avx2.pmovsxwd" => "__builtin_ia32_pmovsxwd256", - "avx2.pmovsxwq" => "__builtin_ia32_pmovsxwq256", - "avx2.pmovzxbd" => "__builtin_ia32_pmovzxbd256", - "avx2.pmovzxbq" => "__builtin_ia32_pmovzxbq256", - "avx2.pmovzxbw" => "__builtin_ia32_pmovzxbw256", - "avx2.pmovzxdq" => "__builtin_ia32_pmovzxdq256", - "avx2.pmovzxwd" => "__builtin_ia32_pmovzxwd256", - "avx2.pmovzxwq" => "__builtin_ia32_pmovzxwq256", - "avx2.pmul.dq" => "__builtin_ia32_pmuldq256", "avx2.pmul.hr.sw" => "__builtin_ia32_pmulhrsw256", "avx2.pmulh.w" => "__builtin_ia32_pmulhw256", "avx2.pmulhu.w" => "__builtin_ia32_pmulhuw256", - "avx2.pmulu.dq" => "__builtin_ia32_pmuludq256", "avx2.psad.bw" => "__builtin_ia32_psadbw256", "avx2.pshuf.b" => "__builtin_ia32_pshufb256", "avx2.psign.b" => "__builtin_ia32_psignb256", "avx2.psign.d" => "__builtin_ia32_psignd256", "avx2.psign.w" => "__builtin_ia32_psignw256", "avx2.psll.d" => "__builtin_ia32_pslld256", - "avx2.psll.dq" => "__builtin_ia32_pslldqi256", - "avx2.psll.dq.bs" => "__builtin_ia32_pslldqi256_byteshift", "avx2.psll.q" => "__builtin_ia32_psllq256", "avx2.psll.w" => "__builtin_ia32_psllw256", "avx2.pslli.d" => "__builtin_ia32_pslldi256", @@ -8356,8 +8058,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.psrav.d" => "__builtin_ia32_psrav4si", "avx2.psrav.d.256" => "__builtin_ia32_psrav8si", "avx2.psrl.d" => "__builtin_ia32_psrld256", - "avx2.psrl.dq" => "__builtin_ia32_psrldqi256", - "avx2.psrl.dq.bs" => "__builtin_ia32_psrldqi256_byteshift", "avx2.psrl.q" => "__builtin_ia32_psrlq256", "avx2.psrl.w" => "__builtin_ia32_psrlw256", "avx2.psrli.d" => "__builtin_ia32_psrldi256", @@ -8367,15 +8067,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.psrlv.d.256" => "__builtin_ia32_psrlv8si", "avx2.psrlv.q" => "__builtin_ia32_psrlv2di", "avx2.psrlv.q.256" => "__builtin_ia32_psrlv4di", - "avx2.psubs.b" => "__builtin_ia32_psubsb256", - "avx2.psubs.w" => "__builtin_ia32_psubsw256", - "avx2.psubus.b" => "__builtin_ia32_psubusb256", - "avx2.psubus.w" => "__builtin_ia32_psubusw256", - "avx2.vbroadcast.sd.pd.256" => "__builtin_ia32_vbroadcastsd_pd256", - "avx2.vbroadcast.ss.ps" => "__builtin_ia32_vbroadcastss_ps", - "avx2.vbroadcast.ss.ps.256" => "__builtin_ia32_vbroadcastss_ps256", - "avx2.vextracti128" => "__builtin_ia32_extract128i256", - "avx2.vinserti128" => "__builtin_ia32_insert128i256", "avx2.vpdpbssd.128" => "__builtin_ia32_vpdpbssd128", "avx2.vpdpbssd.256" => "__builtin_ia32_vpdpbssd256", "avx2.vpdpbssds.128" => "__builtin_ia32_vpdpbssds128", @@ -8400,7 +8091,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.vpdpwuud.256" => "__builtin_ia32_vpdpwuud256", "avx2.vpdpwuuds.128" => "__builtin_ia32_vpdpwuuds128", "avx2.vpdpwuuds.256" => "__builtin_ia32_vpdpwuuds256", - "avx2.vperm2i128" => "__builtin_ia32_permti256", "avx512.add.pd.512" => "__builtin_ia32_addpd512", "avx512.add.ps.512" => "__builtin_ia32_addps512", "avx512.broadcastmb.128" => "__builtin_ia32_broadcastmb128", @@ -8415,194 +8105,32 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.conflict.q.128" => "__builtin_ia32_vpconflictdi_128", "avx512.conflict.q.256" => "__builtin_ia32_vpconflictdi_256", "avx512.conflict.q.512" => "__builtin_ia32_vpconflictdi_512", - "avx512.cvtb2mask.128" => "__builtin_ia32_cvtb2mask128", - "avx512.cvtb2mask.256" => "__builtin_ia32_cvtb2mask256", - "avx512.cvtb2mask.512" => "__builtin_ia32_cvtb2mask512", - "avx512.cvtd2mask.128" => "__builtin_ia32_cvtd2mask128", - "avx512.cvtd2mask.256" => "__builtin_ia32_cvtd2mask256", - "avx512.cvtd2mask.512" => "__builtin_ia32_cvtd2mask512", - "avx512.cvtmask2b.128" => "__builtin_ia32_cvtmask2b128", - "avx512.cvtmask2b.256" => "__builtin_ia32_cvtmask2b256", - "avx512.cvtmask2b.512" => "__builtin_ia32_cvtmask2b512", - "avx512.cvtmask2d.128" => "__builtin_ia32_cvtmask2d128", - "avx512.cvtmask2d.256" => "__builtin_ia32_cvtmask2d256", - "avx512.cvtmask2d.512" => "__builtin_ia32_cvtmask2d512", - "avx512.cvtmask2q.128" => "__builtin_ia32_cvtmask2q128", - "avx512.cvtmask2q.256" => "__builtin_ia32_cvtmask2q256", - "avx512.cvtmask2q.512" => "__builtin_ia32_cvtmask2q512", - "avx512.cvtmask2w.128" => "__builtin_ia32_cvtmask2w128", - "avx512.cvtmask2w.256" => "__builtin_ia32_cvtmask2w256", - "avx512.cvtmask2w.512" => "__builtin_ia32_cvtmask2w512", - "avx512.cvtq2mask.128" => "__builtin_ia32_cvtq2mask128", - "avx512.cvtq2mask.256" => "__builtin_ia32_cvtq2mask256", - "avx512.cvtq2mask.512" => "__builtin_ia32_cvtq2mask512", - "avx512.cvtsd2usi" => "__builtin_ia32_cvtsd2usi", - "avx512.cvtsd2usi64" => "__builtin_ia32_cvtsd2usi64", - "avx512.cvtsi2sd32" => "__builtin_ia32_cvtsi2sd32", "avx512.cvtsi2sd64" => "__builtin_ia32_cvtsi2sd64", "avx512.cvtsi2ss32" => "__builtin_ia32_cvtsi2ss32", "avx512.cvtsi2ss64" => "__builtin_ia32_cvtsi2ss64", - "avx512.cvtss2usi" => "__builtin_ia32_cvtss2usi", - "avx512.cvtss2usi64" => "__builtin_ia32_cvtss2usi64", "avx512.cvttsd2si" => "__builtin_ia32_vcvttsd2si32", "avx512.cvttsd2si64" => "__builtin_ia32_vcvttsd2si64", "avx512.cvttsd2usi" => "__builtin_ia32_vcvttsd2usi32", - // [DUPLICATE]: "avx512.cvttsd2usi" => "__builtin_ia32_cvttsd2usi", "avx512.cvttsd2usi64" => "__builtin_ia32_vcvttsd2usi64", - // [DUPLICATE]: "avx512.cvttsd2usi64" => "__builtin_ia32_cvttsd2usi64", "avx512.cvttss2si" => "__builtin_ia32_vcvttss2si32", "avx512.cvttss2si64" => "__builtin_ia32_vcvttss2si64", "avx512.cvttss2usi" => "__builtin_ia32_vcvttss2usi32", - // [DUPLICATE]: "avx512.cvttss2usi" => "__builtin_ia32_cvttss2usi", "avx512.cvttss2usi64" => "__builtin_ia32_vcvttss2usi64", - // [DUPLICATE]: "avx512.cvttss2usi64" => "__builtin_ia32_cvttss2usi64", - "avx512.cvtusi2sd" => "__builtin_ia32_cvtusi2sd", - // [DUPLICATE]: "avx512.cvtusi2sd" => "__builtin_ia32_cvtusi2sd32", "avx512.cvtusi2ss" => "__builtin_ia32_cvtusi2ss32", - // [DUPLICATE]: "avx512.cvtusi2ss" => "__builtin_ia32_cvtusi2ss", "avx512.cvtusi642sd" => "__builtin_ia32_cvtusi2sd64", - // [DUPLICATE]: "avx512.cvtusi642sd" => "__builtin_ia32_cvtusi642sd", "avx512.cvtusi642ss" => "__builtin_ia32_cvtusi2ss64", - // [DUPLICATE]: "avx512.cvtusi642ss" => "__builtin_ia32_cvtusi642ss", - "avx512.cvtw2mask.128" => "__builtin_ia32_cvtw2mask128", - "avx512.cvtw2mask.256" => "__builtin_ia32_cvtw2mask256", - "avx512.cvtw2mask.512" => "__builtin_ia32_cvtw2mask512", "avx512.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128", "avx512.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256", "avx512.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512", "avx512.div.pd.512" => "__builtin_ia32_divpd512", "avx512.div.ps.512" => "__builtin_ia32_divps512", - "avx512.exp2.pd" => "__builtin_ia32_exp2pd_mask", - "avx512.exp2.ps" => "__builtin_ia32_exp2ps_mask", - "avx512.gather.dpd.512" => "__builtin_ia32_gathersiv8df", - "avx512.gather.dpi.512" => "__builtin_ia32_gathersiv16si", - "avx512.gather.dpq.512" => "__builtin_ia32_gathersiv8di", - "avx512.gather.dps.512" => "__builtin_ia32_gathersiv16sf", - "avx512.gather.qpd.512" => "__builtin_ia32_gatherdiv8df", - "avx512.gather.qpi.512" => "__builtin_ia32_gatherdiv16si", - "avx512.gather.qpq.512" => "__builtin_ia32_gatherdiv8di", - "avx512.gather.qps.512" => "__builtin_ia32_gatherdiv16sf", - "avx512.gather3div2.df" => "__builtin_ia32_gather3div2df", - "avx512.gather3div2.di" => "__builtin_ia32_gather3div2di", - "avx512.gather3div4.df" => "__builtin_ia32_gather3div4df", - "avx512.gather3div4.di" => "__builtin_ia32_gather3div4di", - "avx512.gather3div4.sf" => "__builtin_ia32_gather3div4sf", - "avx512.gather3div4.si" => "__builtin_ia32_gather3div4si", - "avx512.gather3div8.sf" => "__builtin_ia32_gather3div8sf", - "avx512.gather3div8.si" => "__builtin_ia32_gather3div8si", - "avx512.gather3siv2.df" => "__builtin_ia32_gather3siv2df", - "avx512.gather3siv2.di" => "__builtin_ia32_gather3siv2di", - "avx512.gather3siv4.df" => "__builtin_ia32_gather3siv4df", - "avx512.gather3siv4.di" => "__builtin_ia32_gather3siv4di", - "avx512.gather3siv4.sf" => "__builtin_ia32_gather3siv4sf", - "avx512.gather3siv4.si" => "__builtin_ia32_gather3siv4si", - "avx512.gather3siv8.sf" => "__builtin_ia32_gather3siv8sf", - "avx512.gather3siv8.si" => "__builtin_ia32_gather3siv8si", - "avx512.gatherpf.dpd.512" => "__builtin_ia32_gatherpfdpd", - "avx512.gatherpf.dps.512" => "__builtin_ia32_gatherpfdps", - "avx512.gatherpf.qpd.512" => "__builtin_ia32_gatherpfqpd", - "avx512.gatherpf.qps.512" => "__builtin_ia32_gatherpfqps", - "avx512.kand.w" => "__builtin_ia32_kandhi", - "avx512.kandn.w" => "__builtin_ia32_kandnhi", - "avx512.knot.w" => "__builtin_ia32_knothi", - "avx512.kor.w" => "__builtin_ia32_korhi", - "avx512.kortestc.w" => "__builtin_ia32_kortestchi", - "avx512.kortestz.w" => "__builtin_ia32_kortestzhi", - "avx512.kunpck.bw" => "__builtin_ia32_kunpckhi", - "avx512.kunpck.dq" => "__builtin_ia32_kunpckdi", - "avx512.kunpck.wd" => "__builtin_ia32_kunpcksi", - "avx512.kxnor.w" => "__builtin_ia32_kxnorhi", - "avx512.kxor.w" => "__builtin_ia32_kxorhi", - "avx512.mask.add.pd.128" => "__builtin_ia32_addpd128_mask", - "avx512.mask.add.pd.256" => "__builtin_ia32_addpd256_mask", - "avx512.mask.add.pd.512" => "__builtin_ia32_addpd512_mask", - "avx512.mask.add.ps.128" => "__builtin_ia32_addps128_mask", - "avx512.mask.add.ps.256" => "__builtin_ia32_addps256_mask", - "avx512.mask.add.ps.512" => "__builtin_ia32_addps512_mask", // [INVALID CONVERSION]: "avx512.mask.add.sd.round" => "__builtin_ia32_addsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.add.ss.round" => "__builtin_ia32_addss_round_mask", - "avx512.mask.and.pd.128" => "__builtin_ia32_andpd128_mask", - "avx512.mask.and.pd.256" => "__builtin_ia32_andpd256_mask", - "avx512.mask.and.pd.512" => "__builtin_ia32_andpd512_mask", - "avx512.mask.and.ps.128" => "__builtin_ia32_andps128_mask", - "avx512.mask.and.ps.256" => "__builtin_ia32_andps256_mask", - "avx512.mask.and.ps.512" => "__builtin_ia32_andps512_mask", - "avx512.mask.andn.pd.128" => "__builtin_ia32_andnpd128_mask", - "avx512.mask.andn.pd.256" => "__builtin_ia32_andnpd256_mask", - "avx512.mask.andn.pd.512" => "__builtin_ia32_andnpd512_mask", - "avx512.mask.andn.ps.128" => "__builtin_ia32_andnps128_mask", - "avx512.mask.andn.ps.256" => "__builtin_ia32_andnps256_mask", - "avx512.mask.andn.ps.512" => "__builtin_ia32_andnps512_mask", - "avx512.mask.blend.d.512" => "__builtin_ia32_blendmd_512_mask", - "avx512.mask.blend.pd.512" => "__builtin_ia32_blendmpd_512_mask", - "avx512.mask.blend.ps.512" => "__builtin_ia32_blendmps_512_mask", - "avx512.mask.blend.q.512" => "__builtin_ia32_blendmq_512_mask", - "avx512.mask.broadcastf32x2.256" => "__builtin_ia32_broadcastf32x2_256_mask", - "avx512.mask.broadcastf32x2.512" => "__builtin_ia32_broadcastf32x2_512_mask", - "avx512.mask.broadcastf32x4.256" => "__builtin_ia32_broadcastf32x4_256_mask", - "avx512.mask.broadcastf32x4.512" => "__builtin_ia32_broadcastf32x4_512", - "avx512.mask.broadcastf32x8.512" => "__builtin_ia32_broadcastf32x8_512_mask", - "avx512.mask.broadcastf64x2.256" => "__builtin_ia32_broadcastf64x2_256_mask", - "avx512.mask.broadcastf64x2.512" => "__builtin_ia32_broadcastf64x2_512_mask", - "avx512.mask.broadcastf64x4.512" => "__builtin_ia32_broadcastf64x4_512", - "avx512.mask.broadcasti32x2.128" => "__builtin_ia32_broadcasti32x2_128_mask", - "avx512.mask.broadcasti32x2.256" => "__builtin_ia32_broadcasti32x2_256_mask", - "avx512.mask.broadcasti32x2.512" => "__builtin_ia32_broadcasti32x2_512_mask", - "avx512.mask.broadcasti32x4.256" => "__builtin_ia32_broadcasti32x4_256_mask", - "avx512.mask.broadcasti32x4.512" => "__builtin_ia32_broadcasti32x4_512", - "avx512.mask.broadcasti32x8.512" => "__builtin_ia32_broadcasti32x8_512_mask", - "avx512.mask.broadcasti64x2.256" => "__builtin_ia32_broadcasti64x2_256_mask", - "avx512.mask.broadcasti64x2.512" => "__builtin_ia32_broadcasti64x2_512_mask", - "avx512.mask.broadcasti64x4.512" => "__builtin_ia32_broadcasti64x4_512", - "avx512.mask.cmp.pd.128" => "__builtin_ia32_cmppd128_mask", - "avx512.mask.cmp.pd.256" => "__builtin_ia32_cmppd256_mask", - "avx512.mask.cmp.pd.512" => "__builtin_ia32_cmppd512_mask", - "avx512.mask.cmp.ps.128" => "__builtin_ia32_cmpps128_mask", - "avx512.mask.cmp.ps.256" => "__builtin_ia32_cmpps256_mask", - "avx512.mask.cmp.ps.512" => "__builtin_ia32_cmpps512_mask", "avx512.mask.cmp.sd" => "__builtin_ia32_cmpsd_mask", "avx512.mask.cmp.ss" => "__builtin_ia32_cmpss_mask", - "avx512.mask.compress.d.128" => "__builtin_ia32_compresssi128_mask", - "avx512.mask.compress.d.256" => "__builtin_ia32_compresssi256_mask", - "avx512.mask.compress.d.512" => "__builtin_ia32_compresssi512_mask", - "avx512.mask.compress.pd.128" => "__builtin_ia32_compressdf128_mask", - "avx512.mask.compress.pd.256" => "__builtin_ia32_compressdf256_mask", - "avx512.mask.compress.pd.512" => "__builtin_ia32_compressdf512_mask", - "avx512.mask.compress.ps.128" => "__builtin_ia32_compresssf128_mask", - "avx512.mask.compress.ps.256" => "__builtin_ia32_compresssf256_mask", - "avx512.mask.compress.ps.512" => "__builtin_ia32_compresssf512_mask", - "avx512.mask.compress.q.128" => "__builtin_ia32_compressdi128_mask", - "avx512.mask.compress.q.256" => "__builtin_ia32_compressdi256_mask", - "avx512.mask.compress.q.512" => "__builtin_ia32_compressdi512_mask", - "avx512.mask.compress.store.d.128" => "__builtin_ia32_compressstoresi128_mask", - "avx512.mask.compress.store.d.256" => "__builtin_ia32_compressstoresi256_mask", - "avx512.mask.compress.store.d.512" => "__builtin_ia32_compressstoresi512_mask", - "avx512.mask.compress.store.pd.128" => "__builtin_ia32_compressstoredf128_mask", - "avx512.mask.compress.store.pd.256" => "__builtin_ia32_compressstoredf256_mask", - "avx512.mask.compress.store.pd.512" => "__builtin_ia32_compressstoredf512_mask", - "avx512.mask.compress.store.ps.128" => "__builtin_ia32_compressstoresf128_mask", - "avx512.mask.compress.store.ps.256" => "__builtin_ia32_compressstoresf256_mask", - "avx512.mask.compress.store.ps.512" => "__builtin_ia32_compressstoresf512_mask", - "avx512.mask.compress.store.q.128" => "__builtin_ia32_compressstoredi128_mask", - "avx512.mask.compress.store.q.256" => "__builtin_ia32_compressstoredi256_mask", - "avx512.mask.compress.store.q.512" => "__builtin_ia32_compressstoredi512_mask", - "avx512.mask.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", - "avx512.mask.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", - "avx512.mask.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", - "avx512.mask.conflict.q.128" => "__builtin_ia32_vpconflictdi_128_mask", - "avx512.mask.conflict.q.256" => "__builtin_ia32_vpconflictdi_256_mask", - "avx512.mask.conflict.q.512" => "__builtin_ia32_vpconflictdi_512_mask", - "avx512.mask.cvtdq2pd.128" => "__builtin_ia32_cvtdq2pd128_mask", - "avx512.mask.cvtdq2pd.256" => "__builtin_ia32_cvtdq2pd256_mask", - "avx512.mask.cvtdq2pd.512" => "__builtin_ia32_cvtdq2pd512_mask", - "avx512.mask.cvtdq2ps.128" => "__builtin_ia32_cvtdq2ps128_mask", - "avx512.mask.cvtdq2ps.256" => "__builtin_ia32_cvtdq2ps256_mask", - "avx512.mask.cvtdq2ps.512" => "__builtin_ia32_cvtdq2ps512_mask", "avx512.mask.cvtpd2dq.128" => "__builtin_ia32_cvtpd2dq128_mask", - "avx512.mask.cvtpd2dq.256" => "__builtin_ia32_cvtpd2dq256_mask", "avx512.mask.cvtpd2dq.512" => "__builtin_ia32_cvtpd2dq512_mask", "avx512.mask.cvtpd2ps" => "__builtin_ia32_cvtpd2ps_mask", - "avx512.mask.cvtpd2ps.256" => "__builtin_ia32_cvtpd2ps256_mask", "avx512.mask.cvtpd2ps.512" => "__builtin_ia32_cvtpd2ps512_mask", "avx512.mask.cvtpd2qq.128" => "__builtin_ia32_cvtpd2qq128_mask", "avx512.mask.cvtpd2qq.256" => "__builtin_ia32_cvtpd2qq256_mask", @@ -8616,8 +8144,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvtps2dq.128" => "__builtin_ia32_cvtps2dq128_mask", "avx512.mask.cvtps2dq.256" => "__builtin_ia32_cvtps2dq256_mask", "avx512.mask.cvtps2dq.512" => "__builtin_ia32_cvtps2dq512_mask", - "avx512.mask.cvtps2pd.128" => "__builtin_ia32_cvtps2pd128_mask", - "avx512.mask.cvtps2pd.256" => "__builtin_ia32_cvtps2pd256_mask", "avx512.mask.cvtps2pd.512" => "__builtin_ia32_cvtps2pd512_mask", "avx512.mask.cvtps2qq.128" => "__builtin_ia32_cvtps2qq128_mask", "avx512.mask.cvtps2qq.256" => "__builtin_ia32_cvtps2qq256_mask", @@ -8628,16 +8154,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvtps2uqq.128" => "__builtin_ia32_cvtps2uqq128_mask", "avx512.mask.cvtps2uqq.256" => "__builtin_ia32_cvtps2uqq256_mask", "avx512.mask.cvtps2uqq.512" => "__builtin_ia32_cvtps2uqq512_mask", - "avx512.mask.cvtqq2pd.128" => "__builtin_ia32_cvtqq2pd128_mask", - "avx512.mask.cvtqq2pd.256" => "__builtin_ia32_cvtqq2pd256_mask", - "avx512.mask.cvtqq2pd.512" => "__builtin_ia32_cvtqq2pd512_mask", "avx512.mask.cvtqq2ps.128" => "__builtin_ia32_cvtqq2ps128_mask", - "avx512.mask.cvtqq2ps.256" => "__builtin_ia32_cvtqq2ps256_mask", - "avx512.mask.cvtqq2ps.512" => "__builtin_ia32_cvtqq2ps512_mask", // [INVALID CONVERSION]: "avx512.mask.cvtsd2ss.round" => "__builtin_ia32_cvtsd2ss_round_mask", // [INVALID CONVERSION]: "avx512.mask.cvtss2sd.round" => "__builtin_ia32_cvtss2sd_round_mask", "avx512.mask.cvttpd2dq.128" => "__builtin_ia32_cvttpd2dq128_mask", - "avx512.mask.cvttpd2dq.256" => "__builtin_ia32_cvttpd2dq256_mask", "avx512.mask.cvttpd2dq.512" => "__builtin_ia32_cvttpd2dq512_mask", "avx512.mask.cvttpd2qq.128" => "__builtin_ia32_cvttpd2qq128_mask", "avx512.mask.cvttpd2qq.256" => "__builtin_ia32_cvttpd2qq256_mask", @@ -8648,8 +8168,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvttpd2uqq.128" => "__builtin_ia32_cvttpd2uqq128_mask", "avx512.mask.cvttpd2uqq.256" => "__builtin_ia32_cvttpd2uqq256_mask", "avx512.mask.cvttpd2uqq.512" => "__builtin_ia32_cvttpd2uqq512_mask", - "avx512.mask.cvttps2dq.128" => "__builtin_ia32_cvttps2dq128_mask", - "avx512.mask.cvttps2dq.256" => "__builtin_ia32_cvttps2dq256_mask", "avx512.mask.cvttps2dq.512" => "__builtin_ia32_cvttps2dq512_mask", "avx512.mask.cvttps2qq.128" => "__builtin_ia32_cvttps2qq128_mask", "avx512.mask.cvttps2qq.256" => "__builtin_ia32_cvttps2qq256_mask", @@ -8660,53 +8178,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvttps2uqq.128" => "__builtin_ia32_cvttps2uqq128_mask", "avx512.mask.cvttps2uqq.256" => "__builtin_ia32_cvttps2uqq256_mask", "avx512.mask.cvttps2uqq.512" => "__builtin_ia32_cvttps2uqq512_mask", - "avx512.mask.cvtudq2pd.128" => "__builtin_ia32_cvtudq2pd128_mask", - "avx512.mask.cvtudq2pd.256" => "__builtin_ia32_cvtudq2pd256_mask", - "avx512.mask.cvtudq2pd.512" => "__builtin_ia32_cvtudq2pd512_mask", - "avx512.mask.cvtudq2ps.128" => "__builtin_ia32_cvtudq2ps128_mask", - "avx512.mask.cvtudq2ps.256" => "__builtin_ia32_cvtudq2ps256_mask", - "avx512.mask.cvtudq2ps.512" => "__builtin_ia32_cvtudq2ps512_mask", - "avx512.mask.cvtuqq2pd.128" => "__builtin_ia32_cvtuqq2pd128_mask", - "avx512.mask.cvtuqq2pd.256" => "__builtin_ia32_cvtuqq2pd256_mask", - "avx512.mask.cvtuqq2pd.512" => "__builtin_ia32_cvtuqq2pd512_mask", "avx512.mask.cvtuqq2ps.128" => "__builtin_ia32_cvtuqq2ps128_mask", - "avx512.mask.cvtuqq2ps.256" => "__builtin_ia32_cvtuqq2ps256_mask", - "avx512.mask.cvtuqq2ps.512" => "__builtin_ia32_cvtuqq2ps512_mask", - "avx512.mask.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128_mask", - "avx512.mask.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256_mask", - "avx512.mask.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512_mask", - "avx512.mask.div.pd.128" => "__builtin_ia32_divpd_mask", - "avx512.mask.div.pd.256" => "__builtin_ia32_divpd256_mask", - "avx512.mask.div.pd.512" => "__builtin_ia32_divpd512_mask", - "avx512.mask.div.ps.128" => "__builtin_ia32_divps_mask", - "avx512.mask.div.ps.256" => "__builtin_ia32_divps256_mask", - "avx512.mask.div.ps.512" => "__builtin_ia32_divps512_mask", // [INVALID CONVERSION]: "avx512.mask.div.sd.round" => "__builtin_ia32_divsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.div.ss.round" => "__builtin_ia32_divss_round_mask", - "avx512.mask.expand.d.128" => "__builtin_ia32_expandsi128_mask", - "avx512.mask.expand.d.256" => "__builtin_ia32_expandsi256_mask", - "avx512.mask.expand.d.512" => "__builtin_ia32_expandsi512_mask", - "avx512.mask.expand.load.d.128" => "__builtin_ia32_expandloadsi128_mask", - "avx512.mask.expand.load.d.256" => "__builtin_ia32_expandloadsi256_mask", - "avx512.mask.expand.load.d.512" => "__builtin_ia32_expandloadsi512_mask", - "avx512.mask.expand.load.pd.128" => "__builtin_ia32_expandloaddf128_mask", - "avx512.mask.expand.load.pd.256" => "__builtin_ia32_expandloaddf256_mask", - "avx512.mask.expand.load.pd.512" => "__builtin_ia32_expandloaddf512_mask", - "avx512.mask.expand.load.ps.128" => "__builtin_ia32_expandloadsf128_mask", - "avx512.mask.expand.load.ps.256" => "__builtin_ia32_expandloadsf256_mask", - "avx512.mask.expand.load.ps.512" => "__builtin_ia32_expandloadsf512_mask", - "avx512.mask.expand.load.q.128" => "__builtin_ia32_expandloaddi128_mask", - "avx512.mask.expand.load.q.256" => "__builtin_ia32_expandloaddi256_mask", - "avx512.mask.expand.load.q.512" => "__builtin_ia32_expandloaddi512_mask", - "avx512.mask.expand.pd.128" => "__builtin_ia32_expanddf128_mask", - "avx512.mask.expand.pd.256" => "__builtin_ia32_expanddf256_mask", - "avx512.mask.expand.pd.512" => "__builtin_ia32_expanddf512_mask", - "avx512.mask.expand.ps.128" => "__builtin_ia32_expandsf128_mask", - "avx512.mask.expand.ps.256" => "__builtin_ia32_expandsf256_mask", - "avx512.mask.expand.ps.512" => "__builtin_ia32_expandsf512_mask", - "avx512.mask.expand.q.128" => "__builtin_ia32_expanddi128_mask", - "avx512.mask.expand.q.256" => "__builtin_ia32_expanddi256_mask", - "avx512.mask.expand.q.512" => "__builtin_ia32_expanddi512_mask", "avx512.mask.fixupimm.pd.128" => "__builtin_ia32_fixupimmpd128_mask", "avx512.mask.fixupimm.pd.256" => "__builtin_ia32_fixupimmpd256_mask", "avx512.mask.fixupimm.pd.512" => "__builtin_ia32_fixupimmpd512_mask", @@ -8715,12 +8189,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.fixupimm.ps.512" => "__builtin_ia32_fixupimmps512_mask", "avx512.mask.fixupimm.sd" => "__builtin_ia32_fixupimmsd_mask", "avx512.mask.fixupimm.ss" => "__builtin_ia32_fixupimmss_mask", - "avx512.mask.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", - "avx512.mask.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", - "avx512.mask.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", - "avx512.mask.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", - "avx512.mask.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", - "avx512.mask.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", "avx512.mask.fpclass.sd" => "__builtin_ia32_fpclasssd_mask", "avx512.mask.fpclass.ss" => "__builtin_ia32_fpclassss_mask", "avx512.mask.getexp.pd.128" => "__builtin_ia32_getexppd128_mask", @@ -8739,226 +8207,19 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.getmant.ps.512" => "__builtin_ia32_getmantps512_mask", // [INVALID CONVERSION]: "avx512.mask.getmant.sd" => "__builtin_ia32_getmantsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.getmant.ss" => "__builtin_ia32_getmantss_round_mask", - "avx512.mask.insertf32x4.256" => "__builtin_ia32_insertf32x4_256_mask", - "avx512.mask.insertf32x4.512" => "__builtin_ia32_insertf32x4_mask", - "avx512.mask.insertf32x8.512" => "__builtin_ia32_insertf32x8_mask", - "avx512.mask.insertf64x2.256" => "__builtin_ia32_insertf64x2_256_mask", - "avx512.mask.insertf64x2.512" => "__builtin_ia32_insertf64x2_512_mask", - "avx512.mask.insertf64x4.512" => "__builtin_ia32_insertf64x4_mask", - "avx512.mask.inserti32x4.256" => "__builtin_ia32_inserti32x4_256_mask", - "avx512.mask.inserti32x4.512" => "__builtin_ia32_inserti32x4_mask", - "avx512.mask.inserti32x8.512" => "__builtin_ia32_inserti32x8_mask", - "avx512.mask.inserti64x2.256" => "__builtin_ia32_inserti64x2_256_mask", - "avx512.mask.inserti64x2.512" => "__builtin_ia32_inserti64x2_512_mask", - "avx512.mask.inserti64x4.512" => "__builtin_ia32_inserti64x4_mask", - "avx512.mask.loadu.d.512" => "__builtin_ia32_loaddqusi512_mask", - "avx512.mask.loadu.pd.512" => "__builtin_ia32_loadupd512_mask", - "avx512.mask.loadu.ps.512" => "__builtin_ia32_loadups512_mask", - "avx512.mask.loadu.q.512" => "__builtin_ia32_loaddqudi512_mask", - "avx512.mask.lzcnt.d.512" => "__builtin_ia32_vplzcntd_512_mask", - "avx512.mask.lzcnt.q.512" => "__builtin_ia32_vplzcntq_512_mask", - "avx512.mask.max.pd.128" => "__builtin_ia32_maxpd_mask", - "avx512.mask.max.pd.256" => "__builtin_ia32_maxpd256_mask", - "avx512.mask.max.pd.512" => "__builtin_ia32_maxpd512_mask", - "avx512.mask.max.ps.128" => "__builtin_ia32_maxps_mask", - "avx512.mask.max.ps.256" => "__builtin_ia32_maxps256_mask", - "avx512.mask.max.ps.512" => "__builtin_ia32_maxps512_mask", // [INVALID CONVERSION]: "avx512.mask.max.sd.round" => "__builtin_ia32_maxsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.max.ss.round" => "__builtin_ia32_maxss_round_mask", - "avx512.mask.min.pd.128" => "__builtin_ia32_minpd_mask", - "avx512.mask.min.pd.256" => "__builtin_ia32_minpd256_mask", - "avx512.mask.min.pd.512" => "__builtin_ia32_minpd512_mask", - "avx512.mask.min.ps.128" => "__builtin_ia32_minps_mask", - "avx512.mask.min.ps.256" => "__builtin_ia32_minps256_mask", - "avx512.mask.min.ps.512" => "__builtin_ia32_minps512_mask", // [INVALID CONVERSION]: "avx512.mask.min.sd.round" => "__builtin_ia32_minsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.min.ss.round" => "__builtin_ia32_minss_round_mask", - "avx512.mask.move.sd" => "__builtin_ia32_movsd_mask", - "avx512.mask.move.ss" => "__builtin_ia32_movss_mask", - "avx512.mask.mul.pd.128" => "__builtin_ia32_mulpd_mask", - "avx512.mask.mul.pd.256" => "__builtin_ia32_mulpd256_mask", - "avx512.mask.mul.pd.512" => "__builtin_ia32_mulpd512_mask", - "avx512.mask.mul.ps.128" => "__builtin_ia32_mulps_mask", - "avx512.mask.mul.ps.256" => "__builtin_ia32_mulps256_mask", - "avx512.mask.mul.ps.512" => "__builtin_ia32_mulps512_mask", // [INVALID CONVERSION]: "avx512.mask.mul.sd.round" => "__builtin_ia32_mulsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.mul.ss.round" => "__builtin_ia32_mulss_round_mask", - "avx512.mask.or.pd.128" => "__builtin_ia32_orpd128_mask", - "avx512.mask.or.pd.256" => "__builtin_ia32_orpd256_mask", - "avx512.mask.or.pd.512" => "__builtin_ia32_orpd512_mask", - "avx512.mask.or.ps.128" => "__builtin_ia32_orps128_mask", - "avx512.mask.or.ps.256" => "__builtin_ia32_orps256_mask", - "avx512.mask.or.ps.512" => "__builtin_ia32_orps512_mask", - "avx512.mask.pabs.b.128" => "__builtin_ia32_pabsb128_mask", - "avx512.mask.pabs.b.256" => "__builtin_ia32_pabsb256_mask", - "avx512.mask.pabs.b.512" => "__builtin_ia32_pabsb512_mask", - "avx512.mask.pabs.d.128" => "__builtin_ia32_pabsd128_mask", - "avx512.mask.pabs.d.256" => "__builtin_ia32_pabsd256_mask", - "avx512.mask.pabs.d.512" => "__builtin_ia32_pabsd512_mask", - "avx512.mask.pabs.q.128" => "__builtin_ia32_pabsq128_mask", - "avx512.mask.pabs.q.256" => "__builtin_ia32_pabsq256_mask", - "avx512.mask.pabs.q.512" => "__builtin_ia32_pabsq512_mask", - "avx512.mask.pabs.w.128" => "__builtin_ia32_pabsw128_mask", - "avx512.mask.pabs.w.256" => "__builtin_ia32_pabsw256_mask", - "avx512.mask.pabs.w.512" => "__builtin_ia32_pabsw512_mask", - "avx512.mask.packssdw.128" => "__builtin_ia32_packssdw128_mask", - "avx512.mask.packssdw.256" => "__builtin_ia32_packssdw256_mask", - "avx512.mask.packssdw.512" => "__builtin_ia32_packssdw512_mask", - "avx512.mask.packsswb.128" => "__builtin_ia32_packsswb128_mask", - "avx512.mask.packsswb.256" => "__builtin_ia32_packsswb256_mask", - "avx512.mask.packsswb.512" => "__builtin_ia32_packsswb512_mask", - "avx512.mask.packusdw.128" => "__builtin_ia32_packusdw128_mask", - "avx512.mask.packusdw.256" => "__builtin_ia32_packusdw256_mask", - "avx512.mask.packusdw.512" => "__builtin_ia32_packusdw512_mask", - "avx512.mask.packuswb.128" => "__builtin_ia32_packuswb128_mask", - "avx512.mask.packuswb.256" => "__builtin_ia32_packuswb256_mask", - "avx512.mask.packuswb.512" => "__builtin_ia32_packuswb512_mask", - "avx512.mask.padd.b.128" => "__builtin_ia32_paddb128_mask", - "avx512.mask.padd.b.256" => "__builtin_ia32_paddb256_mask", - "avx512.mask.padd.b.512" => "__builtin_ia32_paddb512_mask", - "avx512.mask.padd.d.128" => "__builtin_ia32_paddd128_mask", - "avx512.mask.padd.d.256" => "__builtin_ia32_paddd256_mask", - "avx512.mask.padd.d.512" => "__builtin_ia32_paddd512_mask", - "avx512.mask.padd.q.128" => "__builtin_ia32_paddq128_mask", - "avx512.mask.padd.q.256" => "__builtin_ia32_paddq256_mask", - "avx512.mask.padd.q.512" => "__builtin_ia32_paddq512_mask", - "avx512.mask.padd.w.128" => "__builtin_ia32_paddw128_mask", - "avx512.mask.padd.w.256" => "__builtin_ia32_paddw256_mask", - "avx512.mask.padd.w.512" => "__builtin_ia32_paddw512_mask", - "avx512.mask.padds.b.128" => "__builtin_ia32_paddsb128_mask", - "avx512.mask.padds.b.256" => "__builtin_ia32_paddsb256_mask", - "avx512.mask.padds.b.512" => "__builtin_ia32_paddsb512_mask", - "avx512.mask.padds.w.128" => "__builtin_ia32_paddsw128_mask", - "avx512.mask.padds.w.256" => "__builtin_ia32_paddsw256_mask", - "avx512.mask.padds.w.512" => "__builtin_ia32_paddsw512_mask", - "avx512.mask.paddus.b.128" => "__builtin_ia32_paddusb128_mask", - "avx512.mask.paddus.b.256" => "__builtin_ia32_paddusb256_mask", - "avx512.mask.paddus.b.512" => "__builtin_ia32_paddusb512_mask", - "avx512.mask.paddus.w.128" => "__builtin_ia32_paddusw128_mask", - "avx512.mask.paddus.w.256" => "__builtin_ia32_paddusw256_mask", - "avx512.mask.paddus.w.512" => "__builtin_ia32_paddusw512_mask", - "avx512.mask.pand.d.512" => "__builtin_ia32_pandd512_mask", - "avx512.mask.pand.q.512" => "__builtin_ia32_pandq512_mask", - "avx512.mask.pavg.b.128" => "__builtin_ia32_pavgb128_mask", - "avx512.mask.pavg.b.256" => "__builtin_ia32_pavgb256_mask", - "avx512.mask.pavg.b.512" => "__builtin_ia32_pavgb512_mask", - "avx512.mask.pavg.w.128" => "__builtin_ia32_pavgw128_mask", - "avx512.mask.pavg.w.256" => "__builtin_ia32_pavgw256_mask", - "avx512.mask.pavg.w.512" => "__builtin_ia32_pavgw512_mask", - "avx512.mask.pbroadcast.b.gpr.128" => "__builtin_ia32_pbroadcastb128_gpr_mask", - "avx512.mask.pbroadcast.b.gpr.256" => "__builtin_ia32_pbroadcastb256_gpr_mask", - "avx512.mask.pbroadcast.b.gpr.512" => "__builtin_ia32_pbroadcastb512_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.128" => "__builtin_ia32_pbroadcastd128_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.256" => "__builtin_ia32_pbroadcastd256_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.512" => "__builtin_ia32_pbroadcastd512_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.128" => "__builtin_ia32_pbroadcastq128_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.256" => "__builtin_ia32_pbroadcastq256_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.512" => "__builtin_ia32_pbroadcastq512_gpr_mask", - "avx512.mask.pbroadcast.q.mem.512" => "__builtin_ia32_pbroadcastq512_mem_mask", - "avx512.mask.pbroadcast.w.gpr.128" => "__builtin_ia32_pbroadcastw128_gpr_mask", - "avx512.mask.pbroadcast.w.gpr.256" => "__builtin_ia32_pbroadcastw256_gpr_mask", - "avx512.mask.pbroadcast.w.gpr.512" => "__builtin_ia32_pbroadcastw512_gpr_mask", - "avx512.mask.pcmpeq.b.128" => "__builtin_ia32_pcmpeqb128_mask", - "avx512.mask.pcmpeq.b.256" => "__builtin_ia32_pcmpeqb256_mask", - "avx512.mask.pcmpeq.b.512" => "__builtin_ia32_pcmpeqb512_mask", - "avx512.mask.pcmpeq.d.128" => "__builtin_ia32_pcmpeqd128_mask", - "avx512.mask.pcmpeq.d.256" => "__builtin_ia32_pcmpeqd256_mask", - "avx512.mask.pcmpeq.d.512" => "__builtin_ia32_pcmpeqd512_mask", - "avx512.mask.pcmpeq.q.128" => "__builtin_ia32_pcmpeqq128_mask", - "avx512.mask.pcmpeq.q.256" => "__builtin_ia32_pcmpeqq256_mask", - "avx512.mask.pcmpeq.q.512" => "__builtin_ia32_pcmpeqq512_mask", - "avx512.mask.pcmpeq.w.128" => "__builtin_ia32_pcmpeqw128_mask", - "avx512.mask.pcmpeq.w.256" => "__builtin_ia32_pcmpeqw256_mask", - "avx512.mask.pcmpeq.w.512" => "__builtin_ia32_pcmpeqw512_mask", - "avx512.mask.pcmpgt.b.128" => "__builtin_ia32_pcmpgtb128_mask", - "avx512.mask.pcmpgt.b.256" => "__builtin_ia32_pcmpgtb256_mask", - "avx512.mask.pcmpgt.b.512" => "__builtin_ia32_pcmpgtb512_mask", - "avx512.mask.pcmpgt.d.128" => "__builtin_ia32_pcmpgtd128_mask", - "avx512.mask.pcmpgt.d.256" => "__builtin_ia32_pcmpgtd256_mask", - "avx512.mask.pcmpgt.d.512" => "__builtin_ia32_pcmpgtd512_mask", - "avx512.mask.pcmpgt.q.128" => "__builtin_ia32_pcmpgtq128_mask", - "avx512.mask.pcmpgt.q.256" => "__builtin_ia32_pcmpgtq256_mask", - "avx512.mask.pcmpgt.q.512" => "__builtin_ia32_pcmpgtq512_mask", - "avx512.mask.pcmpgt.w.128" => "__builtin_ia32_pcmpgtw128_mask", - "avx512.mask.pcmpgt.w.256" => "__builtin_ia32_pcmpgtw256_mask", - "avx512.mask.pcmpgt.w.512" => "__builtin_ia32_pcmpgtw512_mask", - "avx512.mask.permvar.df.256" => "__builtin_ia32_permvardf256_mask", - "avx512.mask.permvar.df.512" => "__builtin_ia32_permvardf512_mask", - "avx512.mask.permvar.di.256" => "__builtin_ia32_permvardi256_mask", - "avx512.mask.permvar.di.512" => "__builtin_ia32_permvardi512_mask", - "avx512.mask.permvar.hi.128" => "__builtin_ia32_permvarhi128_mask", - "avx512.mask.permvar.hi.256" => "__builtin_ia32_permvarhi256_mask", - "avx512.mask.permvar.hi.512" => "__builtin_ia32_permvarhi512_mask", - "avx512.mask.permvar.qi.128" => "__builtin_ia32_permvarqi128_mask", - "avx512.mask.permvar.qi.256" => "__builtin_ia32_permvarqi256_mask", - "avx512.mask.permvar.qi.512" => "__builtin_ia32_permvarqi512_mask", - "avx512.mask.permvar.sf.256" => "__builtin_ia32_permvarsf256_mask", - "avx512.mask.permvar.sf.512" => "__builtin_ia32_permvarsf512_mask", - "avx512.mask.permvar.si.256" => "__builtin_ia32_permvarsi256_mask", - "avx512.mask.permvar.si.512" => "__builtin_ia32_permvarsi512_mask", - "avx512.mask.pmaddubs.w.128" => "__builtin_ia32_pmaddubsw128_mask", - "avx512.mask.pmaddubs.w.256" => "__builtin_ia32_pmaddubsw256_mask", - "avx512.mask.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512_mask", - "avx512.mask.pmaddw.d.128" => "__builtin_ia32_pmaddwd128_mask", - "avx512.mask.pmaddw.d.256" => "__builtin_ia32_pmaddwd256_mask", - "avx512.mask.pmaddw.d.512" => "__builtin_ia32_pmaddwd512_mask", - "avx512.mask.pmaxs.b.128" => "__builtin_ia32_pmaxsb128_mask", - "avx512.mask.pmaxs.b.256" => "__builtin_ia32_pmaxsb256_mask", - "avx512.mask.pmaxs.b.512" => "__builtin_ia32_pmaxsb512_mask", - "avx512.mask.pmaxs.d.128" => "__builtin_ia32_pmaxsd128_mask", - "avx512.mask.pmaxs.d.256" => "__builtin_ia32_pmaxsd256_mask", - "avx512.mask.pmaxs.d.512" => "__builtin_ia32_pmaxsd512_mask", - "avx512.mask.pmaxs.q.128" => "__builtin_ia32_pmaxsq128_mask", - "avx512.mask.pmaxs.q.256" => "__builtin_ia32_pmaxsq256_mask", - "avx512.mask.pmaxs.q.512" => "__builtin_ia32_pmaxsq512_mask", - "avx512.mask.pmaxs.w.128" => "__builtin_ia32_pmaxsw128_mask", - "avx512.mask.pmaxs.w.256" => "__builtin_ia32_pmaxsw256_mask", - "avx512.mask.pmaxs.w.512" => "__builtin_ia32_pmaxsw512_mask", - "avx512.mask.pmaxu.b.128" => "__builtin_ia32_pmaxub128_mask", - "avx512.mask.pmaxu.b.256" => "__builtin_ia32_pmaxub256_mask", - "avx512.mask.pmaxu.b.512" => "__builtin_ia32_pmaxub512_mask", - "avx512.mask.pmaxu.d.128" => "__builtin_ia32_pmaxud128_mask", - "avx512.mask.pmaxu.d.256" => "__builtin_ia32_pmaxud256_mask", - "avx512.mask.pmaxu.d.512" => "__builtin_ia32_pmaxud512_mask", - "avx512.mask.pmaxu.q.128" => "__builtin_ia32_pmaxuq128_mask", - "avx512.mask.pmaxu.q.256" => "__builtin_ia32_pmaxuq256_mask", - "avx512.mask.pmaxu.q.512" => "__builtin_ia32_pmaxuq512_mask", - "avx512.mask.pmaxu.w.128" => "__builtin_ia32_pmaxuw128_mask", - "avx512.mask.pmaxu.w.256" => "__builtin_ia32_pmaxuw256_mask", - "avx512.mask.pmaxu.w.512" => "__builtin_ia32_pmaxuw512_mask", - "avx512.mask.pmins.b.128" => "__builtin_ia32_pminsb128_mask", - "avx512.mask.pmins.b.256" => "__builtin_ia32_pminsb256_mask", - "avx512.mask.pmins.b.512" => "__builtin_ia32_pminsb512_mask", - "avx512.mask.pmins.d.128" => "__builtin_ia32_pminsd128_mask", - "avx512.mask.pmins.d.256" => "__builtin_ia32_pminsd256_mask", - "avx512.mask.pmins.d.512" => "__builtin_ia32_pminsd512_mask", - "avx512.mask.pmins.q.128" => "__builtin_ia32_pminsq128_mask", - "avx512.mask.pmins.q.256" => "__builtin_ia32_pminsq256_mask", - "avx512.mask.pmins.q.512" => "__builtin_ia32_pminsq512_mask", - "avx512.mask.pmins.w.128" => "__builtin_ia32_pminsw128_mask", - "avx512.mask.pmins.w.256" => "__builtin_ia32_pminsw256_mask", - "avx512.mask.pmins.w.512" => "__builtin_ia32_pminsw512_mask", - "avx512.mask.pminu.b.128" => "__builtin_ia32_pminub128_mask", - "avx512.mask.pminu.b.256" => "__builtin_ia32_pminub256_mask", - "avx512.mask.pminu.b.512" => "__builtin_ia32_pminub512_mask", - "avx512.mask.pminu.d.128" => "__builtin_ia32_pminud128_mask", - "avx512.mask.pminu.d.256" => "__builtin_ia32_pminud256_mask", - "avx512.mask.pminu.d.512" => "__builtin_ia32_pminud512_mask", - "avx512.mask.pminu.q.128" => "__builtin_ia32_pminuq128_mask", - "avx512.mask.pminu.q.256" => "__builtin_ia32_pminuq256_mask", - "avx512.mask.pminu.q.512" => "__builtin_ia32_pminuq512_mask", - "avx512.mask.pminu.w.128" => "__builtin_ia32_pminuw128_mask", - "avx512.mask.pminu.w.256" => "__builtin_ia32_pminuw256_mask", - "avx512.mask.pminu.w.512" => "__builtin_ia32_pminuw512_mask", "avx512.mask.pmov.db.128" => "__builtin_ia32_pmovdb128_mask", "avx512.mask.pmov.db.256" => "__builtin_ia32_pmovdb256_mask", - "avx512.mask.pmov.db.512" => "__builtin_ia32_pmovdb512_mask", "avx512.mask.pmov.db.mem.128" => "__builtin_ia32_pmovdb128mem_mask", "avx512.mask.pmov.db.mem.256" => "__builtin_ia32_pmovdb256mem_mask", "avx512.mask.pmov.db.mem.512" => "__builtin_ia32_pmovdb512mem_mask", "avx512.mask.pmov.dw.128" => "__builtin_ia32_pmovdw128_mask", "avx512.mask.pmov.dw.256" => "__builtin_ia32_pmovdw256_mask", - "avx512.mask.pmov.dw.512" => "__builtin_ia32_pmovdw512_mask", "avx512.mask.pmov.dw.mem.128" => "__builtin_ia32_pmovdw128mem_mask", "avx512.mask.pmov.dw.mem.256" => "__builtin_ia32_pmovdw256mem_mask", "avx512.mask.pmov.dw.mem.512" => "__builtin_ia32_pmovdw512mem_mask", @@ -8969,20 +8230,15 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmov.qb.mem.256" => "__builtin_ia32_pmovqb256mem_mask", "avx512.mask.pmov.qb.mem.512" => "__builtin_ia32_pmovqb512mem_mask", "avx512.mask.pmov.qd.128" => "__builtin_ia32_pmovqd128_mask", - "avx512.mask.pmov.qd.256" => "__builtin_ia32_pmovqd256_mask", - "avx512.mask.pmov.qd.512" => "__builtin_ia32_pmovqd512_mask", "avx512.mask.pmov.qd.mem.128" => "__builtin_ia32_pmovqd128mem_mask", "avx512.mask.pmov.qd.mem.256" => "__builtin_ia32_pmovqd256mem_mask", "avx512.mask.pmov.qd.mem.512" => "__builtin_ia32_pmovqd512mem_mask", "avx512.mask.pmov.qw.128" => "__builtin_ia32_pmovqw128_mask", "avx512.mask.pmov.qw.256" => "__builtin_ia32_pmovqw256_mask", - "avx512.mask.pmov.qw.512" => "__builtin_ia32_pmovqw512_mask", "avx512.mask.pmov.qw.mem.128" => "__builtin_ia32_pmovqw128mem_mask", "avx512.mask.pmov.qw.mem.256" => "__builtin_ia32_pmovqw256mem_mask", "avx512.mask.pmov.qw.mem.512" => "__builtin_ia32_pmovqw512mem_mask", "avx512.mask.pmov.wb.128" => "__builtin_ia32_pmovwb128_mask", - "avx512.mask.pmov.wb.256" => "__builtin_ia32_pmovwb256_mask", - "avx512.mask.pmov.wb.512" => "__builtin_ia32_pmovwb512_mask", "avx512.mask.pmov.wb.mem.128" => "__builtin_ia32_pmovwb128mem_mask", "avx512.mask.pmov.wb.mem.256" => "__builtin_ia32_pmovwb256mem_mask", "avx512.mask.pmov.wb.mem.512" => "__builtin_ia32_pmovwb512mem_mask", @@ -9022,24 +8278,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmovs.wb.mem.128" => "__builtin_ia32_pmovswb128mem_mask", "avx512.mask.pmovs.wb.mem.256" => "__builtin_ia32_pmovswb256mem_mask", "avx512.mask.pmovs.wb.mem.512" => "__builtin_ia32_pmovswb512mem_mask", - "avx512.mask.pmovsxb.d.128" => "__builtin_ia32_pmovsxbd128_mask", - "avx512.mask.pmovsxb.d.256" => "__builtin_ia32_pmovsxbd256_mask", - "avx512.mask.pmovsxb.d.512" => "__builtin_ia32_pmovsxbd512_mask", - "avx512.mask.pmovsxb.q.128" => "__builtin_ia32_pmovsxbq128_mask", - "avx512.mask.pmovsxb.q.256" => "__builtin_ia32_pmovsxbq256_mask", - "avx512.mask.pmovsxb.q.512" => "__builtin_ia32_pmovsxbq512_mask", - "avx512.mask.pmovsxb.w.128" => "__builtin_ia32_pmovsxbw128_mask", - "avx512.mask.pmovsxb.w.256" => "__builtin_ia32_pmovsxbw256_mask", - "avx512.mask.pmovsxb.w.512" => "__builtin_ia32_pmovsxbw512_mask", - "avx512.mask.pmovsxd.q.128" => "__builtin_ia32_pmovsxdq128_mask", - "avx512.mask.pmovsxd.q.256" => "__builtin_ia32_pmovsxdq256_mask", - "avx512.mask.pmovsxd.q.512" => "__builtin_ia32_pmovsxdq512_mask", - "avx512.mask.pmovsxw.d.128" => "__builtin_ia32_pmovsxwd128_mask", - "avx512.mask.pmovsxw.d.256" => "__builtin_ia32_pmovsxwd256_mask", - "avx512.mask.pmovsxw.d.512" => "__builtin_ia32_pmovsxwd512_mask", - "avx512.mask.pmovsxw.q.128" => "__builtin_ia32_pmovsxwq128_mask", - "avx512.mask.pmovsxw.q.256" => "__builtin_ia32_pmovsxwq256_mask", - "avx512.mask.pmovsxw.q.512" => "__builtin_ia32_pmovsxwq512_mask", "avx512.mask.pmovus.db.128" => "__builtin_ia32_pmovusdb128_mask", "avx512.mask.pmovus.db.256" => "__builtin_ia32_pmovusdb256_mask", "avx512.mask.pmovus.db.512" => "__builtin_ia32_pmovusdb512_mask", @@ -9076,191 +8314,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmovus.wb.mem.128" => "__builtin_ia32_pmovuswb128mem_mask", "avx512.mask.pmovus.wb.mem.256" => "__builtin_ia32_pmovuswb256mem_mask", "avx512.mask.pmovus.wb.mem.512" => "__builtin_ia32_pmovuswb512mem_mask", - "avx512.mask.pmovzxb.d.128" => "__builtin_ia32_pmovzxbd128_mask", - "avx512.mask.pmovzxb.d.256" => "__builtin_ia32_pmovzxbd256_mask", - "avx512.mask.pmovzxb.d.512" => "__builtin_ia32_pmovzxbd512_mask", - "avx512.mask.pmovzxb.q.128" => "__builtin_ia32_pmovzxbq128_mask", - "avx512.mask.pmovzxb.q.256" => "__builtin_ia32_pmovzxbq256_mask", - "avx512.mask.pmovzxb.q.512" => "__builtin_ia32_pmovzxbq512_mask", - "avx512.mask.pmovzxb.w.128" => "__builtin_ia32_pmovzxbw128_mask", - "avx512.mask.pmovzxb.w.256" => "__builtin_ia32_pmovzxbw256_mask", - "avx512.mask.pmovzxb.w.512" => "__builtin_ia32_pmovzxbw512_mask", - "avx512.mask.pmovzxd.q.128" => "__builtin_ia32_pmovzxdq128_mask", - "avx512.mask.pmovzxd.q.256" => "__builtin_ia32_pmovzxdq256_mask", - "avx512.mask.pmovzxd.q.512" => "__builtin_ia32_pmovzxdq512_mask", - "avx512.mask.pmovzxw.d.128" => "__builtin_ia32_pmovzxwd128_mask", - "avx512.mask.pmovzxw.d.256" => "__builtin_ia32_pmovzxwd256_mask", - "avx512.mask.pmovzxw.d.512" => "__builtin_ia32_pmovzxwd512_mask", - "avx512.mask.pmovzxw.q.128" => "__builtin_ia32_pmovzxwq128_mask", - "avx512.mask.pmovzxw.q.256" => "__builtin_ia32_pmovzxwq256_mask", - "avx512.mask.pmovzxw.q.512" => "__builtin_ia32_pmovzxwq512_mask", - "avx512.mask.pmul.dq.128" => "__builtin_ia32_pmuldq128_mask", - "avx512.mask.pmul.dq.256" => "__builtin_ia32_pmuldq256_mask", - "avx512.mask.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", - "avx512.mask.pmul.hr.sw.128" => "__builtin_ia32_pmulhrsw128_mask", - "avx512.mask.pmul.hr.sw.256" => "__builtin_ia32_pmulhrsw256_mask", - "avx512.mask.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512_mask", - "avx512.mask.pmulh.w.128" => "__builtin_ia32_pmulhw128_mask", - "avx512.mask.pmulh.w.256" => "__builtin_ia32_pmulhw256_mask", - "avx512.mask.pmulh.w.512" => "__builtin_ia32_pmulhw512_mask", - "avx512.mask.pmulhu.w.128" => "__builtin_ia32_pmulhuw128_mask", - "avx512.mask.pmulhu.w.256" => "__builtin_ia32_pmulhuw256_mask", - "avx512.mask.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", - "avx512.mask.pmull.d.128" => "__builtin_ia32_pmulld128_mask", - "avx512.mask.pmull.d.256" => "__builtin_ia32_pmulld256_mask", - "avx512.mask.pmull.d.512" => "__builtin_ia32_pmulld512_mask", - "avx512.mask.pmull.q.128" => "__builtin_ia32_pmullq128_mask", - "avx512.mask.pmull.q.256" => "__builtin_ia32_pmullq256_mask", - "avx512.mask.pmull.q.512" => "__builtin_ia32_pmullq512_mask", - "avx512.mask.pmull.w.128" => "__builtin_ia32_pmullw128_mask", - "avx512.mask.pmull.w.256" => "__builtin_ia32_pmullw256_mask", - "avx512.mask.pmull.w.512" => "__builtin_ia32_pmullw512_mask", - "avx512.mask.pmultishift.qb.128" => "__builtin_ia32_vpmultishiftqb128_mask", - "avx512.mask.pmultishift.qb.256" => "__builtin_ia32_vpmultishiftqb256_mask", - "avx512.mask.pmultishift.qb.512" => "__builtin_ia32_vpmultishiftqb512_mask", - "avx512.mask.pmulu.dq.128" => "__builtin_ia32_pmuludq128_mask", - "avx512.mask.pmulu.dq.256" => "__builtin_ia32_pmuludq256_mask", - "avx512.mask.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", - "avx512.mask.prol.d.128" => "__builtin_ia32_prold128_mask", - "avx512.mask.prol.d.256" => "__builtin_ia32_prold256_mask", - "avx512.mask.prol.d.512" => "__builtin_ia32_prold512_mask", - "avx512.mask.prol.q.128" => "__builtin_ia32_prolq128_mask", - "avx512.mask.prol.q.256" => "__builtin_ia32_prolq256_mask", - "avx512.mask.prol.q.512" => "__builtin_ia32_prolq512_mask", - "avx512.mask.prolv.d.128" => "__builtin_ia32_prolvd128_mask", - "avx512.mask.prolv.d.256" => "__builtin_ia32_prolvd256_mask", - "avx512.mask.prolv.d.512" => "__builtin_ia32_prolvd512_mask", - "avx512.mask.prolv.q.128" => "__builtin_ia32_prolvq128_mask", - "avx512.mask.prolv.q.256" => "__builtin_ia32_prolvq256_mask", - "avx512.mask.prolv.q.512" => "__builtin_ia32_prolvq512_mask", - "avx512.mask.pror.d.128" => "__builtin_ia32_prord128_mask", - "avx512.mask.pror.d.256" => "__builtin_ia32_prord256_mask", - "avx512.mask.pror.d.512" => "__builtin_ia32_prord512_mask", - "avx512.mask.pror.q.128" => "__builtin_ia32_prorq128_mask", - "avx512.mask.pror.q.256" => "__builtin_ia32_prorq256_mask", - "avx512.mask.pror.q.512" => "__builtin_ia32_prorq512_mask", - "avx512.mask.prorv.d.128" => "__builtin_ia32_prorvd128_mask", - "avx512.mask.prorv.d.256" => "__builtin_ia32_prorvd256_mask", - "avx512.mask.prorv.d.512" => "__builtin_ia32_prorvd512_mask", - "avx512.mask.prorv.q.128" => "__builtin_ia32_prorvq128_mask", - "avx512.mask.prorv.q.256" => "__builtin_ia32_prorvq256_mask", - "avx512.mask.prorv.q.512" => "__builtin_ia32_prorvq512_mask", - "avx512.mask.pshuf.b.128" => "__builtin_ia32_pshufb128_mask", - "avx512.mask.pshuf.b.256" => "__builtin_ia32_pshufb256_mask", - "avx512.mask.pshuf.b.512" => "__builtin_ia32_pshufb512_mask", - "avx512.mask.psll.d" => "__builtin_ia32_pslld512_mask", - "avx512.mask.psll.d.128" => "__builtin_ia32_pslld128_mask", - "avx512.mask.psll.d.256" => "__builtin_ia32_pslld256_mask", - "avx512.mask.psll.di.128" => "__builtin_ia32_pslldi128_mask", - "avx512.mask.psll.di.256" => "__builtin_ia32_pslldi256_mask", - "avx512.mask.psll.di.512" => "__builtin_ia32_pslldi512_mask", - "avx512.mask.psll.q" => "__builtin_ia32_psllq512_mask", - "avx512.mask.psll.q.128" => "__builtin_ia32_psllq128_mask", - "avx512.mask.psll.q.256" => "__builtin_ia32_psllq256_mask", - "avx512.mask.psll.qi.128" => "__builtin_ia32_psllqi128_mask", - "avx512.mask.psll.qi.256" => "__builtin_ia32_psllqi256_mask", - "avx512.mask.psll.qi.512" => "__builtin_ia32_psllqi512_mask", - "avx512.mask.psll.w.128" => "__builtin_ia32_psllw128_mask", - "avx512.mask.psll.w.256" => "__builtin_ia32_psllw256_mask", - "avx512.mask.psll.w.512" => "__builtin_ia32_psllw512_mask", - "avx512.mask.psll.wi.128" => "__builtin_ia32_psllwi128_mask", - "avx512.mask.psll.wi.256" => "__builtin_ia32_psllwi256_mask", - "avx512.mask.psll.wi.512" => "__builtin_ia32_psllwi512_mask", - "avx512.mask.psllv.d" => "__builtin_ia32_psllv16si_mask", - "avx512.mask.psllv.q" => "__builtin_ia32_psllv8di_mask", - "avx512.mask.psllv16.hi" => "__builtin_ia32_psllv16hi_mask", - "avx512.mask.psllv2.di" => "__builtin_ia32_psllv2di_mask", - "avx512.mask.psllv32hi" => "__builtin_ia32_psllv32hi_mask", - "avx512.mask.psllv4.di" => "__builtin_ia32_psllv4di_mask", - "avx512.mask.psllv4.si" => "__builtin_ia32_psllv4si_mask", - "avx512.mask.psllv8.hi" => "__builtin_ia32_psllv8hi_mask", - "avx512.mask.psllv8.si" => "__builtin_ia32_psllv8si_mask", - "avx512.mask.psra.d" => "__builtin_ia32_psrad512_mask", - "avx512.mask.psra.d.128" => "__builtin_ia32_psrad128_mask", - "avx512.mask.psra.d.256" => "__builtin_ia32_psrad256_mask", - "avx512.mask.psra.di.128" => "__builtin_ia32_psradi128_mask", - "avx512.mask.psra.di.256" => "__builtin_ia32_psradi256_mask", - "avx512.mask.psra.di.512" => "__builtin_ia32_psradi512_mask", - "avx512.mask.psra.q" => "__builtin_ia32_psraq512_mask", - "avx512.mask.psra.q.128" => "__builtin_ia32_psraq128_mask", - "avx512.mask.psra.q.256" => "__builtin_ia32_psraq256_mask", - "avx512.mask.psra.qi.128" => "__builtin_ia32_psraqi128_mask", - "avx512.mask.psra.qi.256" => "__builtin_ia32_psraqi256_mask", - "avx512.mask.psra.qi.512" => "__builtin_ia32_psraqi512_mask", - "avx512.mask.psra.w.128" => "__builtin_ia32_psraw128_mask", - "avx512.mask.psra.w.256" => "__builtin_ia32_psraw256_mask", - "avx512.mask.psra.w.512" => "__builtin_ia32_psraw512_mask", - "avx512.mask.psra.wi.128" => "__builtin_ia32_psrawi128_mask", - "avx512.mask.psra.wi.256" => "__builtin_ia32_psrawi256_mask", - "avx512.mask.psra.wi.512" => "__builtin_ia32_psrawi512_mask", - "avx512.mask.psrav.d" => "__builtin_ia32_psrav16si_mask", - "avx512.mask.psrav.q" => "__builtin_ia32_psrav8di_mask", - "avx512.mask.psrav.q.128" => "__builtin_ia32_psravq128_mask", - "avx512.mask.psrav.q.256" => "__builtin_ia32_psravq256_mask", - "avx512.mask.psrav16.hi" => "__builtin_ia32_psrav16hi_mask", - "avx512.mask.psrav32.hi" => "__builtin_ia32_psrav32hi_mask", - "avx512.mask.psrav4.si" => "__builtin_ia32_psrav4si_mask", - "avx512.mask.psrav8.hi" => "__builtin_ia32_psrav8hi_mask", - "avx512.mask.psrav8.si" => "__builtin_ia32_psrav8si_mask", - "avx512.mask.psrl.d" => "__builtin_ia32_psrld512_mask", - "avx512.mask.psrl.d.128" => "__builtin_ia32_psrld128_mask", - "avx512.mask.psrl.d.256" => "__builtin_ia32_psrld256_mask", - "avx512.mask.psrl.di.128" => "__builtin_ia32_psrldi128_mask", - "avx512.mask.psrl.di.256" => "__builtin_ia32_psrldi256_mask", - "avx512.mask.psrl.di.512" => "__builtin_ia32_psrldi512_mask", - "avx512.mask.psrl.q" => "__builtin_ia32_psrlq512_mask", - "avx512.mask.psrl.q.128" => "__builtin_ia32_psrlq128_mask", - "avx512.mask.psrl.q.256" => "__builtin_ia32_psrlq256_mask", - "avx512.mask.psrl.qi.128" => "__builtin_ia32_psrlqi128_mask", - "avx512.mask.psrl.qi.256" => "__builtin_ia32_psrlqi256_mask", - "avx512.mask.psrl.qi.512" => "__builtin_ia32_psrlqi512_mask", - "avx512.mask.psrl.w.128" => "__builtin_ia32_psrlw128_mask", - "avx512.mask.psrl.w.256" => "__builtin_ia32_psrlw256_mask", - "avx512.mask.psrl.w.512" => "__builtin_ia32_psrlw512_mask", - "avx512.mask.psrl.wi.128" => "__builtin_ia32_psrlwi128_mask", - "avx512.mask.psrl.wi.256" => "__builtin_ia32_psrlwi256_mask", - "avx512.mask.psrl.wi.512" => "__builtin_ia32_psrlwi512_mask", - "avx512.mask.psrlv.d" => "__builtin_ia32_psrlv16si_mask", - "avx512.mask.psrlv.q" => "__builtin_ia32_psrlv8di_mask", - "avx512.mask.psrlv16.hi" => "__builtin_ia32_psrlv16hi_mask", - "avx512.mask.psrlv2.di" => "__builtin_ia32_psrlv2di_mask", - "avx512.mask.psrlv32hi" => "__builtin_ia32_psrlv32hi_mask", - "avx512.mask.psrlv4.di" => "__builtin_ia32_psrlv4di_mask", - "avx512.mask.psrlv4.si" => "__builtin_ia32_psrlv4si_mask", - "avx512.mask.psrlv8.hi" => "__builtin_ia32_psrlv8hi_mask", - "avx512.mask.psrlv8.si" => "__builtin_ia32_psrlv8si_mask", - "avx512.mask.psub.b.128" => "__builtin_ia32_psubb128_mask", - "avx512.mask.psub.b.256" => "__builtin_ia32_psubb256_mask", - "avx512.mask.psub.b.512" => "__builtin_ia32_psubb512_mask", - "avx512.mask.psub.d.128" => "__builtin_ia32_psubd128_mask", - "avx512.mask.psub.d.256" => "__builtin_ia32_psubd256_mask", - "avx512.mask.psub.d.512" => "__builtin_ia32_psubd512_mask", - "avx512.mask.psub.q.128" => "__builtin_ia32_psubq128_mask", - "avx512.mask.psub.q.256" => "__builtin_ia32_psubq256_mask", - "avx512.mask.psub.q.512" => "__builtin_ia32_psubq512_mask", - "avx512.mask.psub.w.128" => "__builtin_ia32_psubw128_mask", - "avx512.mask.psub.w.256" => "__builtin_ia32_psubw256_mask", - "avx512.mask.psub.w.512" => "__builtin_ia32_psubw512_mask", - "avx512.mask.psubs.b.128" => "__builtin_ia32_psubsb128_mask", - "avx512.mask.psubs.b.256" => "__builtin_ia32_psubsb256_mask", - "avx512.mask.psubs.b.512" => "__builtin_ia32_psubsb512_mask", - "avx512.mask.psubs.w.128" => "__builtin_ia32_psubsw128_mask", - "avx512.mask.psubs.w.256" => "__builtin_ia32_psubsw256_mask", - "avx512.mask.psubs.w.512" => "__builtin_ia32_psubsw512_mask", - "avx512.mask.psubus.b.128" => "__builtin_ia32_psubusb128_mask", - "avx512.mask.psubus.b.256" => "__builtin_ia32_psubusb256_mask", - "avx512.mask.psubus.b.512" => "__builtin_ia32_psubusb512_mask", - "avx512.mask.psubus.w.128" => "__builtin_ia32_psubusw128_mask", - "avx512.mask.psubus.w.256" => "__builtin_ia32_psubusw256_mask", - "avx512.mask.psubus.w.512" => "__builtin_ia32_psubusw512_mask", - "avx512.mask.pternlog.d.128" => "__builtin_ia32_pternlogd128_mask", - "avx512.mask.pternlog.d.256" => "__builtin_ia32_pternlogd256_mask", - "avx512.mask.pternlog.d.512" => "__builtin_ia32_pternlogd512_mask", - "avx512.mask.pternlog.q.128" => "__builtin_ia32_pternlogq128_mask", - "avx512.mask.pternlog.q.256" => "__builtin_ia32_pternlogq256_mask", - "avx512.mask.pternlog.q.512" => "__builtin_ia32_pternlogq512_mask", - "avx512.mask.ptestm.d.512" => "__builtin_ia32_ptestmd512", - "avx512.mask.ptestm.q.512" => "__builtin_ia32_ptestmq512", "avx512.mask.range.pd.128" => "__builtin_ia32_rangepd128_mask", "avx512.mask.range.pd.256" => "__builtin_ia32_rangepd256_mask", "avx512.mask.range.pd.512" => "__builtin_ia32_rangepd512_mask", @@ -9293,181 +8346,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.scalef.ps.512" => "__builtin_ia32_scalefps512_mask", // [INVALID CONVERSION]: "avx512.mask.scalef.sd" => "__builtin_ia32_scalefsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.scalef.ss" => "__builtin_ia32_scalefss_round_mask", - "avx512.mask.shuf.f32x4" => "__builtin_ia32_shuf_f32x4_mask", - "avx512.mask.shuf.f32x4.256" => "__builtin_ia32_shuf_f32x4_256_mask", - "avx512.mask.shuf.f64x2" => "__builtin_ia32_shuf_f64x2_mask", - "avx512.mask.shuf.f64x2.256" => "__builtin_ia32_shuf_f64x2_256_mask", - "avx512.mask.shuf.i32x4" => "__builtin_ia32_shuf_i32x4_mask", - "avx512.mask.shuf.i32x4.256" => "__builtin_ia32_shuf_i32x4_256_mask", - "avx512.mask.shuf.i64x2" => "__builtin_ia32_shuf_i64x2_mask", - "avx512.mask.shuf.i64x2.256" => "__builtin_ia32_shuf_i64x2_256_mask", - "avx512.mask.shuf.pd.128" => "__builtin_ia32_shufpd128_mask", - "avx512.mask.shuf.pd.256" => "__builtin_ia32_shufpd256_mask", - "avx512.mask.shuf.pd.512" => "__builtin_ia32_shufpd512_mask", - "avx512.mask.shuf.ps.128" => "__builtin_ia32_shufps128_mask", - "avx512.mask.shuf.ps.256" => "__builtin_ia32_shufps256_mask", - "avx512.mask.shuf.ps.512" => "__builtin_ia32_shufps512_mask", - "avx512.mask.sqrt.pd.128" => "__builtin_ia32_sqrtpd128_mask", - "avx512.mask.sqrt.pd.256" => "__builtin_ia32_sqrtpd256_mask", - "avx512.mask.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", - "avx512.mask.sqrt.ps.128" => "__builtin_ia32_sqrtps128_mask", - "avx512.mask.sqrt.ps.256" => "__builtin_ia32_sqrtps256_mask", - "avx512.mask.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", - // [INVALID CONVERSION]: "avx512.mask.sqrt.sd" => "__builtin_ia32_sqrtsd_round_mask", - // [INVALID CONVERSION]: "avx512.mask.sqrt.ss" => "__builtin_ia32_sqrtss_round_mask", - "avx512.mask.store.ss" => "__builtin_ia32_storess_mask", - "avx512.mask.storeu.d.512" => "__builtin_ia32_storedqusi512_mask", - "avx512.mask.storeu.pd.512" => "__builtin_ia32_storeupd512_mask", - "avx512.mask.storeu.ps.512" => "__builtin_ia32_storeups512_mask", - "avx512.mask.storeu.q.512" => "__builtin_ia32_storedqudi512_mask", - "avx512.mask.sub.pd.128" => "__builtin_ia32_subpd128_mask", - "avx512.mask.sub.pd.256" => "__builtin_ia32_subpd256_mask", - "avx512.mask.sub.pd.512" => "__builtin_ia32_subpd512_mask", - "avx512.mask.sub.ps.128" => "__builtin_ia32_subps128_mask", - "avx512.mask.sub.ps.256" => "__builtin_ia32_subps256_mask", - "avx512.mask.sub.ps.512" => "__builtin_ia32_subps512_mask", // [INVALID CONVERSION]: "avx512.mask.sub.sd.round" => "__builtin_ia32_subsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.sub.ss.round" => "__builtin_ia32_subss_round_mask", - "avx512.mask.valign.d.128" => "__builtin_ia32_alignd128_mask", - "avx512.mask.valign.d.256" => "__builtin_ia32_alignd256_mask", - "avx512.mask.valign.d.512" => "__builtin_ia32_alignd512_mask", - "avx512.mask.valign.q.128" => "__builtin_ia32_alignq128_mask", - "avx512.mask.valign.q.256" => "__builtin_ia32_alignq256_mask", - "avx512.mask.valign.q.512" => "__builtin_ia32_alignq512_mask", - "avx512.mask.vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps_mask", - "avx512.mask.vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256_mask", - "avx512.mask.vcvtph2ps.512" => "__builtin_ia32_vcvtph2ps512_mask", "avx512.mask.vcvtps2ph.128" => "__builtin_ia32_vcvtps2ph_mask", "avx512.mask.vcvtps2ph.256" => "__builtin_ia32_vcvtps2ph256_mask", "avx512.mask.vcvtps2ph.512" => "__builtin_ia32_vcvtps2ph512_mask", - "avx512.mask.vextractf32x4.256" => "__builtin_ia32_extractf32x4_256_mask", - "avx512.mask.vextractf32x4.512" => "__builtin_ia32_extractf32x4_mask", - "avx512.mask.vextractf32x8.512" => "__builtin_ia32_extractf32x8_mask", - "avx512.mask.vextractf64x2.256" => "__builtin_ia32_extractf64x2_256_mask", - "avx512.mask.vextractf64x2.512" => "__builtin_ia32_extractf64x2_512_mask", - "avx512.mask.vextractf64x4.512" => "__builtin_ia32_extractf64x4_mask", - "avx512.mask.vextracti32x4.256" => "__builtin_ia32_extracti32x4_256_mask", - "avx512.mask.vextracti32x4.512" => "__builtin_ia32_extracti32x4_mask", - "avx512.mask.vextracti32x8.512" => "__builtin_ia32_extracti32x8_mask", - "avx512.mask.vextracti64x2.256" => "__builtin_ia32_extracti64x2_256_mask", - "avx512.mask.vextracti64x2.512" => "__builtin_ia32_extracti64x2_512_mask", - "avx512.mask.vextracti64x4.512" => "__builtin_ia32_extracti64x4_mask", - "avx512.mask.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask", - "avx512.mask.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask", - "avx512.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", - "avx512.mask.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask", - "avx512.mask.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask", - "avx512.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", - "avx512.mask.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask", - "avx512.mask.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask", - "avx512.mask.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask", - "avx512.mask.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask", - "avx512.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", - "avx512.mask.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask", - "avx512.mask.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask", - "avx512.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", - "avx512.mask.vfnmadd.pd.128" => "__builtin_ia32_vfnmaddpd128_mask", - "avx512.mask.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256_mask", - "avx512.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", - "avx512.mask.vfnmadd.ps.128" => "__builtin_ia32_vfnmaddps128_mask", - "avx512.mask.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256_mask", - "avx512.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", - "avx512.mask.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask", - "avx512.mask.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask", - "avx512.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", - "avx512.mask.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask", - "avx512.mask.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask", - "avx512.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", - "avx512.mask.vpermi2var.d.128" => "__builtin_ia32_vpermi2vard128_mask", - "avx512.mask.vpermi2var.d.256" => "__builtin_ia32_vpermi2vard256_mask", - "avx512.mask.vpermi2var.d.512" => "__builtin_ia32_vpermi2vard512_mask", - "avx512.mask.vpermi2var.hi.128" => "__builtin_ia32_vpermi2varhi128_mask", - "avx512.mask.vpermi2var.hi.256" => "__builtin_ia32_vpermi2varhi256_mask", - "avx512.mask.vpermi2var.hi.512" => "__builtin_ia32_vpermi2varhi512_mask", - "avx512.mask.vpermi2var.pd.128" => "__builtin_ia32_vpermi2varpd128_mask", - "avx512.mask.vpermi2var.pd.256" => "__builtin_ia32_vpermi2varpd256_mask", - "avx512.mask.vpermi2var.pd.512" => "__builtin_ia32_vpermi2varpd512_mask", - "avx512.mask.vpermi2var.ps.128" => "__builtin_ia32_vpermi2varps128_mask", - "avx512.mask.vpermi2var.ps.256" => "__builtin_ia32_vpermi2varps256_mask", - "avx512.mask.vpermi2var.ps.512" => "__builtin_ia32_vpermi2varps512_mask", - "avx512.mask.vpermi2var.q.128" => "__builtin_ia32_vpermi2varq128_mask", - "avx512.mask.vpermi2var.q.256" => "__builtin_ia32_vpermi2varq256_mask", - "avx512.mask.vpermi2var.q.512" => "__builtin_ia32_vpermi2varq512_mask", - "avx512.mask.vpermi2var.qi.128" => "__builtin_ia32_vpermi2varqi128_mask", - "avx512.mask.vpermi2var.qi.256" => "__builtin_ia32_vpermi2varqi256_mask", - "avx512.mask.vpermi2var.qi.512" => "__builtin_ia32_vpermi2varqi512_mask", - "avx512.mask.vpermilvar.pd.128" => "__builtin_ia32_vpermilvarpd_mask", - "avx512.mask.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256_mask", - "avx512.mask.vpermilvar.pd.512" => "__builtin_ia32_vpermilvarpd512_mask", - "avx512.mask.vpermilvar.ps.128" => "__builtin_ia32_vpermilvarps_mask", - "avx512.mask.vpermilvar.ps.256" => "__builtin_ia32_vpermilvarps256_mask", - "avx512.mask.vpermilvar.ps.512" => "__builtin_ia32_vpermilvarps512_mask", - "avx512.mask.vpermt.d.512" => "__builtin_ia32_vpermt2vard512_mask", - "avx512.mask.vpermt.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", - "avx512.mask.vpermt.ps.512" => "__builtin_ia32_vpermt2varps512_mask", - "avx512.mask.vpermt.q.512" => "__builtin_ia32_vpermt2varq512_mask", - "avx512.mask.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_mask", - "avx512.mask.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_mask", - "avx512.mask.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_mask", - "avx512.mask.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_mask", - "avx512.mask.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_mask", - "avx512.mask.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_mask", - "avx512.mask.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_mask", - "avx512.mask.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_mask", - "avx512.mask.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", - "avx512.mask.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_mask", - "avx512.mask.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_mask", - "avx512.mask.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_mask", - "avx512.mask.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_mask", - "avx512.mask.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_mask", - "avx512.mask.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_mask", - "avx512.mask.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_mask", - "avx512.mask.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_mask", - "avx512.mask.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_mask", - "avx512.mask.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_mask", - "avx512.mask.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_mask", - "avx512.mask.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_mask", - "avx512.mask.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_mask", - "avx512.mask.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_mask", - "avx512.mask.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_mask", - "avx512.mask.xor.pd.128" => "__builtin_ia32_xorpd128_mask", - "avx512.mask.xor.pd.256" => "__builtin_ia32_xorpd256_mask", - "avx512.mask.xor.pd.512" => "__builtin_ia32_xorpd512_mask", - "avx512.mask.xor.ps.128" => "__builtin_ia32_xorps128_mask", - "avx512.mask.xor.ps.256" => "__builtin_ia32_xorps256_mask", - "avx512.mask.xor.ps.512" => "__builtin_ia32_xorps512_mask", - "avx512.mask3.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask3", - "avx512.mask3.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask3", - "avx512.mask3.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask3", - "avx512.mask3.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask3", - "avx512.mask3.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask3", - "avx512.mask3.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask3", - "avx512.mask3.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask3", - "avx512.mask3.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask3", - "avx512.mask3.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask3", - "avx512.mask3.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask3", - "avx512.mask3.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask3", - "avx512.mask3.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask3", - "avx512.mask3.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask3", - "avx512.mask3.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask3", - "avx512.mask3.vfmsub.pd.128" => "__builtin_ia32_vfmsubpd128_mask3", - "avx512.mask3.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256_mask3", - "avx512.mask3.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask3", - "avx512.mask3.vfmsub.ps.128" => "__builtin_ia32_vfmsubps128_mask3", - "avx512.mask3.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256_mask3", - "avx512.mask3.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask3", - "avx512.mask3.vfmsubadd.pd.128" => "__builtin_ia32_vfmsubaddpd128_mask3", - "avx512.mask3.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256_mask3", - "avx512.mask3.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask3", - "avx512.mask3.vfmsubadd.ps.128" => "__builtin_ia32_vfmsubaddps128_mask3", - "avx512.mask3.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256_mask3", - "avx512.mask3.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask3", - "avx512.mask3.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask3", - "avx512.mask3.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask3", - "avx512.mask3.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask3", - "avx512.mask3.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask3", - "avx512.mask3.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask3", - "avx512.mask3.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask3", "avx512.maskz.fixupimm.pd.128" => "__builtin_ia32_fixupimmpd128_maskz", "avx512.maskz.fixupimm.pd.256" => "__builtin_ia32_fixupimmpd256_maskz", "avx512.maskz.fixupimm.pd.512" => "__builtin_ia32_fixupimmpd512_maskz", @@ -9476,55 +8359,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.maskz.fixupimm.ps.512" => "__builtin_ia32_fixupimmps512_maskz", "avx512.maskz.fixupimm.sd" => "__builtin_ia32_fixupimmsd_maskz", "avx512.maskz.fixupimm.ss" => "__builtin_ia32_fixupimmss_maskz", - "avx512.maskz.pternlog.d.128" => "__builtin_ia32_pternlogd128_maskz", - "avx512.maskz.pternlog.d.256" => "__builtin_ia32_pternlogd256_maskz", - "avx512.maskz.pternlog.d.512" => "__builtin_ia32_pternlogd512_maskz", - "avx512.maskz.pternlog.q.128" => "__builtin_ia32_pternlogq128_maskz", - "avx512.maskz.pternlog.q.256" => "__builtin_ia32_pternlogq256_maskz", - "avx512.maskz.pternlog.q.512" => "__builtin_ia32_pternlogq512_maskz", - "avx512.maskz.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_maskz", - "avx512.maskz.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_maskz", - "avx512.maskz.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_maskz", - "avx512.maskz.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_maskz", - "avx512.maskz.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_maskz", - "avx512.maskz.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_maskz", - "avx512.maskz.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_maskz", - "avx512.maskz.vfmadd.ss" => "__builtin_ia32_vfmaddss3_maskz", - "avx512.maskz.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_maskz", - "avx512.maskz.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_maskz", - "avx512.maskz.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_maskz", - "avx512.maskz.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_maskz", - "avx512.maskz.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_maskz", - "avx512.maskz.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_maskz", - "avx512.maskz.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_maskz", - "avx512.maskz.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_maskz", - "avx512.maskz.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_maskz", - "avx512.maskz.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_maskz", - "avx512.maskz.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_maskz", - "avx512.maskz.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_maskz", - "avx512.maskz.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_maskz", - "avx512.maskz.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_maskz", - "avx512.maskz.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_maskz", - "avx512.maskz.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_maskz", - "avx512.maskz.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_maskz", - "avx512.maskz.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_maskz", - "avx512.maskz.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_maskz", - "avx512.maskz.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_maskz", - "avx512.maskz.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_maskz", - "avx512.maskz.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_maskz", - "avx512.maskz.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_maskz", - "avx512.maskz.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_maskz", - "avx512.maskz.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_maskz", - "avx512.maskz.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_maskz", - "avx512.maskz.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_maskz", - "avx512.maskz.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_maskz", - "avx512.maskz.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_maskz", - "avx512.maskz.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_maskz", "avx512.max.pd.512" => "__builtin_ia32_maxpd512", "avx512.max.ps.512" => "__builtin_ia32_maxps512", "avx512.min.pd.512" => "__builtin_ia32_minpd512", "avx512.min.ps.512" => "__builtin_ia32_minps512", - "avx512.movntdqa" => "__builtin_ia32_movntdqa512", "avx512.mul.pd.512" => "__builtin_ia32_mulpd512", "avx512.mul.ps.512" => "__builtin_ia32_mulps512", "avx512.packssdw.512" => "__builtin_ia32_packssdw512", @@ -9533,8 +8371,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.packuswb.512" => "__builtin_ia32_packuswb512", "avx512.pavg.b.512" => "__builtin_ia32_pavgb512", "avx512.pavg.w.512" => "__builtin_ia32_pavgw512", - "avx512.pbroadcastd.512" => "__builtin_ia32_pbroadcastd512", - "avx512.pbroadcastq.512" => "__builtin_ia32_pbroadcastq512", "avx512.permvar.df.256" => "__builtin_ia32_permvardf256", "avx512.permvar.df.512" => "__builtin_ia32_permvardf512", "avx512.permvar.di.256" => "__builtin_ia32_permvardi256", @@ -9549,11 +8385,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.permvar.si.512" => "__builtin_ia32_permvarsi512", "avx512.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512", "avx512.pmaddw.d.512" => "__builtin_ia32_pmaddwd512", - "avx512.pmovzxbd" => "__builtin_ia32_pmovzxbd512", - "avx512.pmovzxbq" => "__builtin_ia32_pmovzxbq512", - "avx512.pmovzxdq" => "__builtin_ia32_pmovzxdq512", - "avx512.pmovzxwd" => "__builtin_ia32_pmovzxwd512", - "avx512.pmovzxwq" => "__builtin_ia32_pmovzxwq512", "avx512.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512", "avx512.pmulh.w.512" => "__builtin_ia32_pmulhw512", "avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512", @@ -9563,8 +8394,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.psad.bw.512" => "__builtin_ia32_psadbw512", "avx512.pshuf.b.512" => "__builtin_ia32_pshufb512", "avx512.psll.d.512" => "__builtin_ia32_pslld512", - "avx512.psll.dq" => "__builtin_ia32_pslldqi512", - "avx512.psll.dq.bs" => "__builtin_ia32_pslldqi512_byteshift", "avx512.psll.q.512" => "__builtin_ia32_psllq512", "avx512.psll.w.512" => "__builtin_ia32_psllw512", "avx512.pslli.d.512" => "__builtin_ia32_pslldi512", @@ -9593,8 +8422,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.psrav.w.256" => "__builtin_ia32_psrav16hi", "avx512.psrav.w.512" => "__builtin_ia32_psrav32hi", "avx512.psrl.d.512" => "__builtin_ia32_psrld512", - "avx512.psrl.dq" => "__builtin_ia32_psrldqi512", - "avx512.psrl.dq.bs" => "__builtin_ia32_psrldqi512_byteshift", "avx512.psrl.q.512" => "__builtin_ia32_psrlq512", "avx512.psrl.w.512" => "__builtin_ia32_psrlw512", "avx512.psrli.d.512" => "__builtin_ia32_psrldi512", @@ -9611,30 +8438,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.pternlog.q.128" => "__builtin_ia32_pternlogq128", "avx512.pternlog.q.256" => "__builtin_ia32_pternlogq256", "avx512.pternlog.q.512" => "__builtin_ia32_pternlogq512", - "avx512.ptestm.b.128" => "__builtin_ia32_ptestmb128", - "avx512.ptestm.b.256" => "__builtin_ia32_ptestmb256", - "avx512.ptestm.b.512" => "__builtin_ia32_ptestmb512", - "avx512.ptestm.d.128" => "__builtin_ia32_ptestmd128", - "avx512.ptestm.d.256" => "__builtin_ia32_ptestmd256", - "avx512.ptestm.d.512" => "__builtin_ia32_ptestmd512", - "avx512.ptestm.q.128" => "__builtin_ia32_ptestmq128", - "avx512.ptestm.q.256" => "__builtin_ia32_ptestmq256", - "avx512.ptestm.q.512" => "__builtin_ia32_ptestmq512", - "avx512.ptestm.w.128" => "__builtin_ia32_ptestmw128", - "avx512.ptestm.w.256" => "__builtin_ia32_ptestmw256", - "avx512.ptestm.w.512" => "__builtin_ia32_ptestmw512", - "avx512.ptestnm.b.128" => "__builtin_ia32_ptestnmb128", - "avx512.ptestnm.b.256" => "__builtin_ia32_ptestnmb256", - "avx512.ptestnm.b.512" => "__builtin_ia32_ptestnmb512", - "avx512.ptestnm.d.128" => "__builtin_ia32_ptestnmd128", - "avx512.ptestnm.d.256" => "__builtin_ia32_ptestnmd256", - "avx512.ptestnm.d.512" => "__builtin_ia32_ptestnmd512", - "avx512.ptestnm.q.128" => "__builtin_ia32_ptestnmq128", - "avx512.ptestnm.q.256" => "__builtin_ia32_ptestnmq256", - "avx512.ptestnm.q.512" => "__builtin_ia32_ptestnmq512", - "avx512.ptestnm.w.128" => "__builtin_ia32_ptestnmw128", - "avx512.ptestnm.w.256" => "__builtin_ia32_ptestnmw256", - "avx512.ptestnm.w.512" => "__builtin_ia32_ptestnmw512", "avx512.rcp14.pd.128" => "__builtin_ia32_rcp14pd128_mask", "avx512.rcp14.pd.256" => "__builtin_ia32_rcp14pd256_mask", "avx512.rcp14.pd.512" => "__builtin_ia32_rcp14pd512_mask", @@ -9643,14 +8446,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.rcp14.ps.512" => "__builtin_ia32_rcp14ps512_mask", "avx512.rcp14.sd" => "__builtin_ia32_rcp14sd_mask", "avx512.rcp14.ss" => "__builtin_ia32_rcp14ss_mask", - "avx512.rcp28.pd" => "__builtin_ia32_rcp28pd_mask", - "avx512.rcp28.ps" => "__builtin_ia32_rcp28ps_mask", - "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", - // [DUPLICATE]: "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_round_mask", - "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", - // [DUPLICATE]: "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_round_mask", - "avx512.rndscale.sd" => "__builtin_ia32_rndscalesd", - "avx512.rndscale.ss" => "__builtin_ia32_rndscaless", "avx512.rsqrt14.pd.128" => "__builtin_ia32_rsqrt14pd128_mask", "avx512.rsqrt14.pd.256" => "__builtin_ia32_rsqrt14pd256_mask", "avx512.rsqrt14.pd.512" => "__builtin_ia32_rsqrt14pd512_mask", @@ -9659,50 +8454,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.rsqrt14.ps.512" => "__builtin_ia32_rsqrt14ps512_mask", "avx512.rsqrt14.sd" => "__builtin_ia32_rsqrt14sd_mask", "avx512.rsqrt14.ss" => "__builtin_ia32_rsqrt14ss_mask", - "avx512.rsqrt28.pd" => "__builtin_ia32_rsqrt28pd_mask", - "avx512.rsqrt28.ps" => "__builtin_ia32_rsqrt28ps_mask", - "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", - // [DUPLICATE]: "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_round_mask", - "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", - // [DUPLICATE]: "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_round_mask", - "avx512.scatter.dpd.512" => "__builtin_ia32_scattersiv8df", - "avx512.scatter.dpi.512" => "__builtin_ia32_scattersiv16si", - "avx512.scatter.dpq.512" => "__builtin_ia32_scattersiv8di", - "avx512.scatter.dps.512" => "__builtin_ia32_scattersiv16sf", - "avx512.scatter.qpd.512" => "__builtin_ia32_scatterdiv8df", - "avx512.scatter.qpi.512" => "__builtin_ia32_scatterdiv16si", - "avx512.scatter.qpq.512" => "__builtin_ia32_scatterdiv8di", - "avx512.scatter.qps.512" => "__builtin_ia32_scatterdiv16sf", - "avx512.scatterdiv2.df" => "__builtin_ia32_scatterdiv2df", - "avx512.scatterdiv2.di" => "__builtin_ia32_scatterdiv2di", - "avx512.scatterdiv4.df" => "__builtin_ia32_scatterdiv4df", - "avx512.scatterdiv4.di" => "__builtin_ia32_scatterdiv4di", - "avx512.scatterdiv4.sf" => "__builtin_ia32_scatterdiv4sf", - "avx512.scatterdiv4.si" => "__builtin_ia32_scatterdiv4si", - "avx512.scatterdiv8.sf" => "__builtin_ia32_scatterdiv8sf", - "avx512.scatterdiv8.si" => "__builtin_ia32_scatterdiv8si", - "avx512.scatterpf.dpd.512" => "__builtin_ia32_scatterpfdpd", - "avx512.scatterpf.dps.512" => "__builtin_ia32_scatterpfdps", - "avx512.scatterpf.qpd.512" => "__builtin_ia32_scatterpfqpd", - "avx512.scatterpf.qps.512" => "__builtin_ia32_scatterpfqps", - "avx512.scattersiv2.df" => "__builtin_ia32_scattersiv2df", - "avx512.scattersiv2.di" => "__builtin_ia32_scattersiv2di", - "avx512.scattersiv4.df" => "__builtin_ia32_scattersiv4df", - "avx512.scattersiv4.di" => "__builtin_ia32_scattersiv4di", - "avx512.scattersiv4.sf" => "__builtin_ia32_scattersiv4sf", - "avx512.scattersiv4.si" => "__builtin_ia32_scattersiv4si", - "avx512.scattersiv8.sf" => "__builtin_ia32_scattersiv8sf", - "avx512.scattersiv8.si" => "__builtin_ia32_scattersiv8si", - "avx512.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", - "avx512.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", - "avx512.sqrt.sd" => "__builtin_ia32_sqrtrndsd", - "avx512.sqrt.ss" => "__builtin_ia32_sqrtrndss", "avx512.sub.pd.512" => "__builtin_ia32_subpd512", "avx512.sub.ps.512" => "__builtin_ia32_subps512", - "avx512.vbroadcast.sd.512" => "__builtin_ia32_vbroadcastsd512", - "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", - "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", - "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", "avx512.vcomi.sd" => "__builtin_ia32_vcomisd", "avx512.vcomi.ss" => "__builtin_ia32_vcomiss", "avx512.vcvtsd2si32" => "__builtin_ia32_vcvtsd2si32", @@ -9928,50 +8681,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "flags.read.u64" => "__builtin_ia32_readeflags_u64", "flags.write.u32" => "__builtin_ia32_writeeflags_u32", "flags.write.u64" => "__builtin_ia32_writeeflags_u64", - "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", - "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", - "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", - "fma.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", - "fma.mask.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask", - "fma.mask.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask", - "fma.mask.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask", - "fma.mask.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask", - "fma.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", - "fma.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", - "fma.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", - "fma.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", - "fma.vfmadd.pd" => "__builtin_ia32_vfmaddpd", - "fma.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256", - "fma.vfmadd.ps" => "__builtin_ia32_vfmaddps", - "fma.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256", - "fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd", - "fma.vfmadd.ss" => "__builtin_ia32_vfmaddss", "fma.vfmaddsub.pd" => "__builtin_ia32_vfmaddsubpd", "fma.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256", "fma.vfmaddsub.ps" => "__builtin_ia32_vfmaddsubps", "fma.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256", - "fma.vfmsub.pd" => "__builtin_ia32_vfmsubpd", - "fma.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256", - "fma.vfmsub.ps" => "__builtin_ia32_vfmsubps", - "fma.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256", - "fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd", - "fma.vfmsub.ss" => "__builtin_ia32_vfmsubss", - "fma.vfmsubadd.pd" => "__builtin_ia32_vfmsubaddpd", - "fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256", - "fma.vfmsubadd.ps" => "__builtin_ia32_vfmsubaddps", - "fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256", - "fma.vfnmadd.pd" => "__builtin_ia32_vfnmaddpd", - "fma.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256", - "fma.vfnmadd.ps" => "__builtin_ia32_vfnmaddps", - "fma.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256", - "fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd", - "fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss", - "fma.vfnmsub.pd" => "__builtin_ia32_vfnmsubpd", - "fma.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256", - "fma.vfnmsub.ps" => "__builtin_ia32_vfnmsubps", - "fma.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256", - "fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd", - "fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss", "fxrstor" => "__builtin_ia32_fxrstor", "fxrstor64" => "__builtin_ia32_fxrstor64", "fxsave" => "__builtin_ia32_fxsave", @@ -9988,7 +8701,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "lwpval32" => "__builtin_ia32_lwpval32", "lwpval64" => "__builtin_ia32_lwpval64", "mmx.emms" => "__builtin_ia32_emms", - "mmx.femms" => "__builtin_ia32_femms", "monitorx" => "__builtin_ia32_monitorx", "movdir64b" => "__builtin_ia32_movdir64b", "movrsdi" => "__builtin_ia32_movrsdi", @@ -10013,7 +8725,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "rdsspd" => "__builtin_ia32_rdsspd", "rdsspq" => "__builtin_ia32_rdsspq", "rdtsc" => "__builtin_ia32_rdtsc", - "rdtscp" => "__builtin_ia32_rdtscp", "rstorssp" => "__builtin_ia32_rstorssp", "saveprevssp" => "__builtin_ia32_saveprevssp", "senduipi" => "__builtin_ia32_senduipi", @@ -10027,8 +8738,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sha256msg2" => "__builtin_ia32_sha256msg2", "sha256rnds2" => "__builtin_ia32_sha256rnds2", "slwpcb" => "__builtin_ia32_slwpcb", - "sse.add.ss" => "__builtin_ia32_addss", - "sse.cmp.ps" => "__builtin_ia32_cmpps", "sse.cmp.ss" => "__builtin_ia32_cmpss", "sse.comieq.ss" => "__builtin_ia32_comieq", "sse.comige.ss" => "__builtin_ia32_comige", @@ -10036,37 +8745,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse.comile.ss" => "__builtin_ia32_comile", "sse.comilt.ss" => "__builtin_ia32_comilt", "sse.comineq.ss" => "__builtin_ia32_comineq", - "sse.cvtsi2ss" => "__builtin_ia32_cvtsi2ss", - "sse.cvtsi642ss" => "__builtin_ia32_cvtsi642ss", "sse.cvtss2si" => "__builtin_ia32_cvtss2si", "sse.cvtss2si64" => "__builtin_ia32_cvtss2si64", "sse.cvttss2si" => "__builtin_ia32_cvttss2si", "sse.cvttss2si64" => "__builtin_ia32_cvttss2si64", - "sse.div.ss" => "__builtin_ia32_divss", "sse.max.ps" => "__builtin_ia32_maxps", "sse.max.ss" => "__builtin_ia32_maxss", "sse.min.ps" => "__builtin_ia32_minps", "sse.min.ss" => "__builtin_ia32_minss", "sse.movmsk.ps" => "__builtin_ia32_movmskps", - "sse.mul.ss" => "__builtin_ia32_mulss", "sse.rcp.ps" => "__builtin_ia32_rcpps", "sse.rcp.ss" => "__builtin_ia32_rcpss", "sse.rsqrt.ps" => "__builtin_ia32_rsqrtps", "sse.rsqrt.ss" => "__builtin_ia32_rsqrtss", "sse.sfence" => "__builtin_ia32_sfence", - "sse.sqrt.ps" => "__builtin_ia32_sqrtps", - "sse.sqrt.ss" => "__builtin_ia32_sqrtss", - "sse.storeu.ps" => "__builtin_ia32_storeups", - "sse.sub.ss" => "__builtin_ia32_subss", "sse.ucomieq.ss" => "__builtin_ia32_ucomieq", "sse.ucomige.ss" => "__builtin_ia32_ucomige", "sse.ucomigt.ss" => "__builtin_ia32_ucomigt", "sse.ucomile.ss" => "__builtin_ia32_ucomile", "sse.ucomilt.ss" => "__builtin_ia32_ucomilt", "sse.ucomineq.ss" => "__builtin_ia32_ucomineq", - "sse2.add.sd" => "__builtin_ia32_addsd", "sse2.clflush" => "__builtin_ia32_clflush", - "sse2.cmp.pd" => "__builtin_ia32_cmppd", "sse2.cmp.sd" => "__builtin_ia32_cmpsd", "sse2.comieq.sd" => "__builtin_ia32_comisdeq", "sse2.comige.sd" => "__builtin_ia32_comisdge", @@ -10074,23 +8773,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.comile.sd" => "__builtin_ia32_comisdle", "sse2.comilt.sd" => "__builtin_ia32_comisdlt", "sse2.comineq.sd" => "__builtin_ia32_comisdneq", - "sse2.cvtdq2pd" => "__builtin_ia32_cvtdq2pd", - "sse2.cvtdq2ps" => "__builtin_ia32_cvtdq2ps", "sse2.cvtpd2dq" => "__builtin_ia32_cvtpd2dq", "sse2.cvtpd2ps" => "__builtin_ia32_cvtpd2ps", "sse2.cvtps2dq" => "__builtin_ia32_cvtps2dq", - "sse2.cvtps2pd" => "__builtin_ia32_cvtps2pd", "sse2.cvtsd2si" => "__builtin_ia32_cvtsd2si", "sse2.cvtsd2si64" => "__builtin_ia32_cvtsd2si64", "sse2.cvtsd2ss" => "__builtin_ia32_cvtsd2ss", - "sse2.cvtsi2sd" => "__builtin_ia32_cvtsi2sd", - "sse2.cvtsi642sd" => "__builtin_ia32_cvtsi642sd", - "sse2.cvtss2sd" => "__builtin_ia32_cvtss2sd", "sse2.cvttpd2dq" => "__builtin_ia32_cvttpd2dq", "sse2.cvttps2dq" => "__builtin_ia32_cvttps2dq", "sse2.cvttsd2si" => "__builtin_ia32_cvttsd2si", "sse2.cvttsd2si64" => "__builtin_ia32_cvttsd2si64", - "sse2.div.sd" => "__builtin_ia32_divsd", "sse2.lfence" => "__builtin_ia32_lfence", "sse2.maskmov.dqu" => "__builtin_ia32_maskmovdqu", "sse2.max.pd" => "__builtin_ia32_maxpd", @@ -10099,33 +8791,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.min.pd" => "__builtin_ia32_minpd", "sse2.min.sd" => "__builtin_ia32_minsd", "sse2.movmsk.pd" => "__builtin_ia32_movmskpd", - "sse2.mul.sd" => "__builtin_ia32_mulsd", "sse2.packssdw.128" => "__builtin_ia32_packssdw128", "sse2.packsswb.128" => "__builtin_ia32_packsswb128", "sse2.packuswb.128" => "__builtin_ia32_packuswb128", - "sse2.padds.b" => "__builtin_ia32_paddsb128", - "sse2.padds.w" => "__builtin_ia32_paddsw128", - "sse2.paddus.b" => "__builtin_ia32_paddusb128", - "sse2.paddus.w" => "__builtin_ia32_paddusw128", "sse2.pause" => "__builtin_ia32_pause", "sse2.pavg.b" => "__builtin_ia32_pavgb128", "sse2.pavg.w" => "__builtin_ia32_pavgw128", "sse2.pmadd.wd" => "__builtin_ia32_pmaddwd128", - "sse2.pmaxs.w" => "__builtin_ia32_pmaxsw128", - "sse2.pmaxu.b" => "__builtin_ia32_pmaxub128", - "sse2.pmins.w" => "__builtin_ia32_pminsw128", - "sse2.pminu.b" => "__builtin_ia32_pminub128", "sse2.pmovmskb.128" => "__builtin_ia32_pmovmskb128", "sse2.pmulh.w" => "__builtin_ia32_pmulhw128", "sse2.pmulhu.w" => "__builtin_ia32_pmulhuw128", - "sse2.pmulu.dq" => "__builtin_ia32_pmuludq128", "sse2.psad.bw" => "__builtin_ia32_psadbw128", - "sse2.pshuf.d" => "__builtin_ia32_pshufd", - "sse2.pshufh.w" => "__builtin_ia32_pshufhw", - "sse2.pshufl.w" => "__builtin_ia32_pshuflw", "sse2.psll.d" => "__builtin_ia32_pslld128", - "sse2.psll.dq" => "__builtin_ia32_pslldqi128", - "sse2.psll.dq.bs" => "__builtin_ia32_pslldqi128_byteshift", "sse2.psll.q" => "__builtin_ia32_psllq128", "sse2.psll.w" => "__builtin_ia32_psllw128", "sse2.pslli.d" => "__builtin_ia32_pslldi128", @@ -10136,23 +8813,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.psrai.d" => "__builtin_ia32_psradi128", "sse2.psrai.w" => "__builtin_ia32_psrawi128", "sse2.psrl.d" => "__builtin_ia32_psrld128", - "sse2.psrl.dq" => "__builtin_ia32_psrldqi128", - "sse2.psrl.dq.bs" => "__builtin_ia32_psrldqi128_byteshift", "sse2.psrl.q" => "__builtin_ia32_psrlq128", "sse2.psrl.w" => "__builtin_ia32_psrlw128", "sse2.psrli.d" => "__builtin_ia32_psrldi128", "sse2.psrli.q" => "__builtin_ia32_psrlqi128", "sse2.psrli.w" => "__builtin_ia32_psrlwi128", - "sse2.psubs.b" => "__builtin_ia32_psubsb128", - "sse2.psubs.w" => "__builtin_ia32_psubsw128", - "sse2.psubus.b" => "__builtin_ia32_psubusb128", - "sse2.psubus.w" => "__builtin_ia32_psubusw128", - "sse2.sqrt.pd" => "__builtin_ia32_sqrtpd", - "sse2.sqrt.sd" => "__builtin_ia32_sqrtsd", - "sse2.storel.dq" => "__builtin_ia32_storelv4si", - "sse2.storeu.dq" => "__builtin_ia32_storedqu", - "sse2.storeu.pd" => "__builtin_ia32_storeupd", - "sse2.sub.sd" => "__builtin_ia32_subsd", "sse2.ucomieq.sd" => "__builtin_ia32_ucomisdeq", "sse2.ucomige.sd" => "__builtin_ia32_ucomisdge", "sse2.ucomigt.sd" => "__builtin_ia32_ucomisdgt", @@ -10168,48 +8833,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse3.ldu.dq" => "__builtin_ia32_lddqu", "sse3.monitor" => "__builtin_ia32_monitor", "sse3.mwait" => "__builtin_ia32_mwait", - "sse41.blendpd" => "__builtin_ia32_blendpd", - "sse41.blendps" => "__builtin_ia32_blendps", "sse41.blendvpd" => "__builtin_ia32_blendvpd", "sse41.blendvps" => "__builtin_ia32_blendvps", "sse41.dppd" => "__builtin_ia32_dppd", "sse41.dpps" => "__builtin_ia32_dpps", - "sse41.extractps" => "__builtin_ia32_extractps128", "sse41.insertps" => "__builtin_ia32_insertps128", - "sse41.movntdqa" => "__builtin_ia32_movntdqa", "sse41.mpsadbw" => "__builtin_ia32_mpsadbw128", "sse41.packusdw" => "__builtin_ia32_packusdw128", "sse41.pblendvb" => "__builtin_ia32_pblendvb128", - "sse41.pblendw" => "__builtin_ia32_pblendw128", "sse41.phminposuw" => "__builtin_ia32_phminposuw128", - "sse41.pmaxsb" => "__builtin_ia32_pmaxsb128", - "sse41.pmaxsd" => "__builtin_ia32_pmaxsd128", - "sse41.pmaxud" => "__builtin_ia32_pmaxud128", - "sse41.pmaxuw" => "__builtin_ia32_pmaxuw128", - "sse41.pminsb" => "__builtin_ia32_pminsb128", - "sse41.pminsd" => "__builtin_ia32_pminsd128", - "sse41.pminud" => "__builtin_ia32_pminud128", - "sse41.pminuw" => "__builtin_ia32_pminuw128", - "sse41.pmovsxbd" => "__builtin_ia32_pmovsxbd128", - "sse41.pmovsxbq" => "__builtin_ia32_pmovsxbq128", - "sse41.pmovsxbw" => "__builtin_ia32_pmovsxbw128", - "sse41.pmovsxdq" => "__builtin_ia32_pmovsxdq128", - "sse41.pmovsxwd" => "__builtin_ia32_pmovsxwd128", - "sse41.pmovsxwq" => "__builtin_ia32_pmovsxwq128", - "sse41.pmovzxbd" => "__builtin_ia32_pmovzxbd128", - "sse41.pmovzxbq" => "__builtin_ia32_pmovzxbq128", - "sse41.pmovzxbw" => "__builtin_ia32_pmovzxbw128", - "sse41.pmovzxdq" => "__builtin_ia32_pmovzxdq128", - "sse41.pmovzxwd" => "__builtin_ia32_pmovzxwd128", - "sse41.pmovzxwq" => "__builtin_ia32_pmovzxwq128", - "sse41.pmuldq" => "__builtin_ia32_pmuldq128", "sse41.ptestc" => "__builtin_ia32_ptestc128", "sse41.ptestnzc" => "__builtin_ia32_ptestnzc128", "sse41.ptestz" => "__builtin_ia32_ptestz128", - "sse41.round.pd" => "__builtin_ia32_roundpd", - "sse41.round.ps" => "__builtin_ia32_roundps", - "sse41.round.sd" => "__builtin_ia32_roundsd", - "sse41.round.ss" => "__builtin_ia32_roundss", "sse42.crc32.32.16" => "__builtin_ia32_crc32hi", "sse42.crc32.32.32" => "__builtin_ia32_crc32si", "sse42.crc32.32.8" => "__builtin_ia32_crc32qi", @@ -10232,11 +8867,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse4a.extrqi" => "__builtin_ia32_extrqi", "sse4a.insertq" => "__builtin_ia32_insertq", "sse4a.insertqi" => "__builtin_ia32_insertqi", - "sse4a.movnt.sd" => "__builtin_ia32_movntsd", - "sse4a.movnt.ss" => "__builtin_ia32_movntss", - "ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", - "ssse3.pabs.d.128" => "__builtin_ia32_pabsd128", - "ssse3.pabs.w.128" => "__builtin_ia32_pabsw128", "ssse3.phadd.d.128" => "__builtin_ia32_phaddd128", "ssse3.phadd.sw.128" => "__builtin_ia32_phaddsw128", "ssse3.phadd.w.128" => "__builtin_ia32_phaddw128", @@ -10251,12 +8881,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ssse3.psign.w.128" => "__builtin_ia32_psignw128", "sttilecfg" => "__builtin_ia32_tile_storeconfig", "stui" => "__builtin_ia32_stui", - "subborrow.u32" => "__builtin_ia32_subborrow_u32", - "subborrow.u64" => "__builtin_ia32_subborrow_u64", - "t2rpntlvwz0rs" => "__builtin_ia32_t2rpntlvwz0rs", - "t2rpntlvwz0rst1" => "__builtin_ia32_t2rpntlvwz0rst1", - "t2rpntlvwz1rs" => "__builtin_ia32_t2rpntlvwz1rs", - "t2rpntlvwz1rst1" => "__builtin_ia32_t2rpntlvwz1rst1", "tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "tbm.bextri.u64" => "__builtin_ia32_bextri_u64", "tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", @@ -10265,14 +8889,19 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", "tcvtrowd2ps" => "__builtin_ia32_tcvtrowd2ps", "tcvtrowd2ps.internal" => "__builtin_ia32_tcvtrowd2ps_internal", + "tcvtrowd2psi" => "__builtin_ia32_tcvtrowd2psi", "tcvtrowps2bf16h" => "__builtin_ia32_tcvtrowps2bf16h", "tcvtrowps2bf16h.internal" => "__builtin_ia32_tcvtrowps2bf16h_internal", + "tcvtrowps2bf16hi" => "__builtin_ia32_tcvtrowps2bf16hi", "tcvtrowps2bf16l" => "__builtin_ia32_tcvtrowps2bf16l", "tcvtrowps2bf16l.internal" => "__builtin_ia32_tcvtrowps2bf16l_internal", + "tcvtrowps2bf16li" => "__builtin_ia32_tcvtrowps2bf16li", "tcvtrowps2phh" => "__builtin_ia32_tcvtrowps2phh", "tcvtrowps2phh.internal" => "__builtin_ia32_tcvtrowps2phh_internal", + "tcvtrowps2phhi" => "__builtin_ia32_tcvtrowps2phhi", "tcvtrowps2phl" => "__builtin_ia32_tcvtrowps2phl", "tcvtrowps2phl.internal" => "__builtin_ia32_tcvtrowps2phl_internal", + "tcvtrowps2phli" => "__builtin_ia32_tcvtrowps2phli", "tdpbf16ps" => "__builtin_ia32_tdpbf16ps", "tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal", "tdpbf8ps" => "__builtin_ia32_tdpbf8ps", @@ -10304,6 +8933,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tileloaddt164.internal" => "__builtin_ia32_tileloaddt164_internal", "tilemovrow" => "__builtin_ia32_tilemovrow", "tilemovrow.internal" => "__builtin_ia32_tilemovrow_internal", + "tilemovrowi" => "__builtin_ia32_tilemovrowi", "tilerelease" => "__builtin_ia32_tilerelease", "tilestored64" => "__builtin_ia32_tilestored64", "tilestored64.internal" => "__builtin_ia32_tilestored64_internal", @@ -10330,8 +8960,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vcvtneoph2ps256" => "__builtin_ia32_vcvtneoph2ps256", "vcvtneps2bf16128" => "__builtin_ia32_vcvtneps2bf16128", "vcvtneps2bf16256" => "__builtin_ia32_vcvtneps2bf16256", - "vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps", - "vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256", "vcvtps2ph.128" => "__builtin_ia32_vcvtps2ph", "vcvtps2ph.256" => "__builtin_ia32_vcvtps2ph256", "vgf2p8affineinvqb.128" => "__builtin_ia32_vgf2p8affineinvqb_v16qi", @@ -10375,16 +9003,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "xop.vfrcz.ps.256" => "__builtin_ia32_vfrczps256", "xop.vfrcz.sd" => "__builtin_ia32_vfrczsd", "xop.vfrcz.ss" => "__builtin_ia32_vfrczss", - "xop.vpcmov" => "__builtin_ia32_vpcmov", - "xop.vpcmov.256" => "__builtin_ia32_vpcmov_256", - "xop.vpcomb" => "__builtin_ia32_vpcomb", - "xop.vpcomd" => "__builtin_ia32_vpcomd", - "xop.vpcomq" => "__builtin_ia32_vpcomq", - "xop.vpcomub" => "__builtin_ia32_vpcomub", - "xop.vpcomud" => "__builtin_ia32_vpcomud", - "xop.vpcomuq" => "__builtin_ia32_vpcomuq", - "xop.vpcomuw" => "__builtin_ia32_vpcomuw", - "xop.vpcomw" => "__builtin_ia32_vpcomw", "xop.vpermil2pd" => "__builtin_ia32_vpermil2pd", "xop.vpermil2pd.256" => "__builtin_ia32_vpermil2pd256", "xop.vpermil2ps" => "__builtin_ia32_vpermil2ps", @@ -10417,14 +9035,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "xop.vpmadcsswd" => "__builtin_ia32_vpmadcsswd", "xop.vpmadcswd" => "__builtin_ia32_vpmadcswd", "xop.vpperm" => "__builtin_ia32_vpperm", - "xop.vprotb" => "__builtin_ia32_vprotb", - "xop.vprotbi" => "__builtin_ia32_vprotbi", - "xop.vprotd" => "__builtin_ia32_vprotd", - "xop.vprotdi" => "__builtin_ia32_vprotdi", - "xop.vprotq" => "__builtin_ia32_vprotq", - "xop.vprotqi" => "__builtin_ia32_vprotqi", - "xop.vprotw" => "__builtin_ia32_vprotw", - "xop.vprotwi" => "__builtin_ia32_vprotwi", "xop.vpshab" => "__builtin_ia32_vpshab", "xop.vpshad" => "__builtin_ia32_vpshad", "xop.vpshaq" => "__builtin_ia32_vpshaq", @@ -10454,6 +9064,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } xcore(name, full_name) } - _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"), + _ => match old_arch_res { + ArchCheckResult::UnknownIntrinsic => { + unimplemented!("***** unsupported LLVM intrinsic {full_name}") + } + ArchCheckResult::UnknownArch => { + unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}") + } + ArchCheckResult::Ok(_) => unreachable!(), + }, } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs index e3d189c95ced..11a69acdde42 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -4,7 +4,7 @@ use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, new_array_type}; fn encode_key_128_type<'a, 'gcc, 'tcx>( builder: &Builder<'a, 'gcc, 'tcx>, @@ -585,7 +585,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( "__builtin_ia32_encodekey128_u32" => { let mut new_args = args.to_vec(); let m128i = builder.context.new_vector_type(builder.i64_type, 2); - let array_type = builder.context.new_array_type(None, m128i, 6); + let array_type = new_array_type(builder.context, None, m128i, 6); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); args = new_args.into(); @@ -593,7 +593,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( "__builtin_ia32_encodekey256_u32" => { let mut new_args = args.to_vec(); let m128i = builder.context.new_vector_type(builder.i64_type, 2); - let array_type = builder.context.new_array_type(None, m128i, 7); + let array_type = new_array_type(builder.context, None, m128i, 7); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); args = new_args.into(); @@ -620,7 +620,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let first_value = old_args.swap_remove(0); let element_type = first_value.get_type(); - let array_type = builder.context.new_array_type(None, element_type, 8); + let array_type = new_array_type(builder.context, None, element_type, 8); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); @@ -869,7 +869,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 6); + let array_type = new_array_type(builder.context, None, field2_type, 6); let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); @@ -891,7 +891,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 7); + let array_type = new_array_type(builder.context, None, field2_type, 7); let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); @@ -937,7 +937,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 8); + let array_type = new_array_type(builder.context, None, field2_type, 8); let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); @@ -1061,7 +1061,18 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.xgetbv" => "__builtin_ia32_xgetbv", // NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html + // FIXME: Should handle other targets than `ia32`. "llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd", + // FIXME: Should handle other targets than `ia32`. + "llvm.sqrt.v4f32" => "__builtin_ia32_sqrtps", + "llvm.sqrt.f32" => { + let gcc_name = "__builtin_sqrtf"; + let func = cx.context.get_builtin_function(gcc_name); + cx.functions.borrow_mut().insert(gcc_name.to_string(), func); + return func; + } + // FIXME: Should handle other targets than `ia32`. + "llvm.smax.v4i32" => "__builtin_ia32_pmaxsd128", "llvm.x86.avx512.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", "llvm.x86.avx512.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", "llvm.x86.avx512.max.ps.512" => "__builtin_ia32_maxps512_mask", @@ -1604,5 +1615,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function func } +#[cfg(feature = "master")] +include!("old_archs.rs"); #[cfg(feature = "master")] include!("archs.rs"); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 553e4d3d2fe0..7e15a5eeaa5e 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -22,13 +22,18 @@ use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +#[cfg(feature = "master")] +use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGccExt, GccType}; +#[cfg(feature = "master")] +use crate::abi::FnAbiGccExt; +use crate::abi::GccType; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -203,6 +208,7 @@ fn get_simple_function_f128<'gcc, 'tcx>( let f128_type = cx.type_f128(); let func_name = match name { sym::ceilf128 => "ceilf128", + sym::fabsf128 => "fabsf128", sym::floorf128 => "floorf128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", @@ -257,6 +263,7 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", + sym::fabsf16 => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", sym::maxnumf16 => "__builtin_fmaxf", @@ -323,6 +330,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 + | sym::fabsf16 | sym::floorf16 | sym::fmaf16 | sym::maxnumf16 @@ -617,8 +625,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc *func } else { self.linkage.set(FunctionType::Extern); - let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ty = fn_abi.gcc_type(self); let func = match sym { "llvm.fma.f16" => { @@ -631,13 +637,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.intrinsics.borrow_mut().insert(sym.to_string(), func); - self.on_stack_function_params - .borrow_mut() - .insert(func, fn_ty.on_stack_param_indices); - #[cfg(feature = "master")] - for fn_attr in fn_ty.fn_attributes { - func.add_attribute(fn_attr); - } + self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); crate::attributes::from_fn_attrs(self, func, instance); @@ -651,15 +651,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let fn_ptr = func.get_address(None); let fn_ty = fn_ptr.get_type(); - let mut llargs = vec![]; + let mut call_args = vec![]; for arg in args { match arg.val { OperandValue::ZeroSized => {} - OperandValue::Immediate(_) => llargs.push(arg.immediate()), + OperandValue::Immediate(_) => call_args.push(arg.immediate()), OperandValue::Pair(a, b) => { - llargs.push(a); - llargs.push(b); + call_args.push(a); + call_args.push(b); } OperandValue::Ref(op_place_val) => { let mut llval = op_place_val.llval; @@ -676,13 +676,13 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc // We store bools as `i8` so we need to truncate to `i1`. llval = self.to_immediate_scalar(llval, scalar); } - llargs.push(llval); + call_args.push(llval); } } } // FIXME directly use the llvm intrinsic adjustment functions here - let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None); + let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None); if is_cleanup { self.apply_attrs_to_cleanup_callsite(llret); } @@ -723,7 +723,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } fn va_end(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { - unimplemented!(); + // TODO(antoyo): implement. + self.context.new_rvalue_from_int(self.int_type, 0) } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs new file mode 100644 index 000000000000..8d3e3487b5cb --- /dev/null +++ b/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs @@ -0,0 +1,1390 @@ +// All these translations used to be automatically generated in the past. However, since they never +// changed, we decided to simplify the translation generation script to move them directly into this +// file. +// +// So in short: avoid editing this file. + +pub(crate) enum ArchCheckResult { + Ok(&'static str), + UnknownIntrinsic, + UnknownArch, +} + +pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { + ArchCheckResult::Ok(match arch { + "AMDGPU" => match name { + "div.fixup.f32" => "__builtin_amdgpu_div_fixup", + "div.fixup.f64" => "__builtin_amdgpu_div_fixup", + "div.fixup.v2f64" => "__builtin_amdgpu_div_fixup", + "div.fixup.v4f32" => "__builtin_amdgpu_div_fixup", + "div.fmas.f32" => "__builtin_amdgpu_div_fmas", + "div.fmas.f64" => "__builtin_amdgpu_div_fmas", + "div.fmas.v2f64" => "__builtin_amdgpu_div_fmas", + "div.fmas.v4f32" => "__builtin_amdgpu_div_fmas", + "ldexp.f32" => "__builtin_amdgpu_ldexp", + "ldexp.f64" => "__builtin_amdgpu_ldexp", + "ldexp.v2f64" => "__builtin_amdgpu_ldexp", + "ldexp.v4f32" => "__builtin_amdgpu_ldexp", + "rcp.f32" => "__builtin_amdgpu_rcp", + "rcp.f64" => "__builtin_amdgpu_rcp", + "rcp.v2f64" => "__builtin_amdgpu_rcp", + "rcp.v4f32" => "__builtin_amdgpu_rcp", + "rsq.clamped.f32" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.f64" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.v2f64" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.v4f32" => "__builtin_amdgpu_rsq_clamped", + "rsq.f32" => "__builtin_amdgpu_rsq", + "rsq.f64" => "__builtin_amdgpu_rsq", + "rsq.v2f64" => "__builtin_amdgpu_rsq", + "rsq.v4f32" => "__builtin_amdgpu_rsq", + "trig.preop.f32" => "__builtin_amdgpu_trig_preop", + "trig.preop.f64" => "__builtin_amdgpu_trig_preop", + "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", + "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "arm" => match name { + "mcrr" => "__builtin_arm_mcrr", + "mcrr2" => "__builtin_arm_mcrr2", + "thread.pointer" => "__builtin_thread_pointer", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "cuda" => match name { + "syncthreads" => "__syncthreads", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "hexagon" => match name { + "F2.dffixupd" => "__builtin_HEXAGON_F2_dffixupd", + "F2.dffixupn" => "__builtin_HEXAGON_F2_dffixupn", + "F2.dffixupr" => "__builtin_HEXAGON_F2_dffixupr", + "F2.dffma" => "__builtin_HEXAGON_F2_dffma", + "F2.dffma.lib" => "__builtin_HEXAGON_F2_dffma_lib", + "F2.dffma.sc" => "__builtin_HEXAGON_F2_dffma_sc", + "F2.dffms" => "__builtin_HEXAGON_F2_dffms", + "F2.dffms.lib" => "__builtin_HEXAGON_F2_dffms_lib", + "F2.dfmpy" => "__builtin_HEXAGON_F2_dfmpy", + "S2.cabacencbin" => "__builtin_HEXAGON_S2_cabacencbin", + "SI.to.SXTHI.asrh" => "__builtin_SI_to_SXTHI_asrh", + "V6.vlutb" => "__builtin_HEXAGON_V6_vlutb", + "V6.vlutb.128B" => "__builtin_HEXAGON_V6_vlutb_128B", + "V6.vlutb.acc" => "__builtin_HEXAGON_V6_vlutb_acc", + "V6.vlutb.acc.128B" => "__builtin_HEXAGON_V6_vlutb_acc_128B", + "V6.vlutb.dv" => "__builtin_HEXAGON_V6_vlutb_dv", + "V6.vlutb.dv.128B" => "__builtin_HEXAGON_V6_vlutb_dv_128B", + "V6.vlutb.dv.acc" => "__builtin_HEXAGON_V6_vlutb_dv_acc", + "V6.vlutb.dv.acc.128B" => "__builtin_HEXAGON_V6_vlutb_dv_acc_128B", + "brev.ldb" => "__builtin_brev_ldb", + "brev.ldd" => "__builtin_brev_ldd", + "brev.ldh" => "__builtin_brev_ldh", + "brev.ldub" => "__builtin_brev_ldub", + "brev.lduh" => "__builtin_brev_lduh", + "brev.ldw" => "__builtin_brev_ldw", + "brev.stb" => "__builtin_brev_stb", + "brev.std" => "__builtin_brev_std", + "brev.sth" => "__builtin_brev_sth", + "brev.sthhi" => "__builtin_brev_sthhi", + "brev.stw" => "__builtin_brev_stw", + "mm256i.vaddw" => "__builtin__mm256i_vaddw", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "nvvm" => match name { + "abs.i" => "__nvvm_abs_i", + "abs.ll" => "__nvvm_abs_ll", + "bar.sync" => "__nvvm_bar_sync", + "barrier0" => "__nvvm_bar0", + "bitcast.d2ll" => "__nvvm_bitcast_d2ll", + "bitcast.f2i" => "__nvvm_bitcast_f2i", + "bitcast.i2f" => "__nvvm_bitcast_i2f", + "bitcast.ll2d" => "__nvvm_bitcast_ll2d", + "brev32" => "__nvvm_brev32", + "brev64" => "__nvvm_brev64", + "clz.i" => "__nvvm_clz_i", + "clz.ll" => "__nvvm_clz_ll", + "ex2.approx.d" => "__nvvm_ex2_approx_d", + "ex2.approx.f" => "__nvvm_ex2_approx_f", + "ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", + "fabs.d" => "__nvvm_fabs_d", + "fabs.f" => "__nvvm_fabs_f", + "fabs.ftz.f" => "__nvvm_fabs_ftz_f", + "h2f" => "__nvvm_h2f", + "max.i" => "__nvvm_max_i", + "max.ll" => "__nvvm_max_ll", + "max.ui" => "__nvvm_max_ui", + "max.ull" => "__nvvm_max_ull", + "min.i" => "__nvvm_min_i", + "min.ll" => "__nvvm_min_ll", + "min.ui" => "__nvvm_min_ui", + "min.ull" => "__nvvm_min_ull", + "popc.i" => "__nvvm_popc_i", + "popc.ll" => "__nvvm_popc_ll", + "rotate.b32" => "__nvvm_rotate_b32", + "rotate.b64" => "__nvvm_rotate_b64", + "rotate.right.b64" => "__nvvm_rotate_right_b64", + "swap.lo.hi.b64" => "__nvvm_swap_lo_hi_b64", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "ppc" => match name { + "qpx.qvfabs" => "__builtin_qpx_qvfabs", + "qpx.qvfadd" => "__builtin_qpx_qvfadd", + "qpx.qvfadds" => "__builtin_qpx_qvfadds", + "qpx.qvfcfid" => "__builtin_qpx_qvfcfid", + "qpx.qvfcfids" => "__builtin_qpx_qvfcfids", + "qpx.qvfcfidu" => "__builtin_qpx_qvfcfidu", + "qpx.qvfcfidus" => "__builtin_qpx_qvfcfidus", + "qpx.qvfcmpeq" => "__builtin_qpx_qvfcmpeq", + "qpx.qvfcmpgt" => "__builtin_qpx_qvfcmpgt", + "qpx.qvfcmplt" => "__builtin_qpx_qvfcmplt", + "qpx.qvfcpsgn" => "__builtin_qpx_qvfcpsgn", + "qpx.qvfctid" => "__builtin_qpx_qvfctid", + "qpx.qvfctidu" => "__builtin_qpx_qvfctidu", + "qpx.qvfctiduz" => "__builtin_qpx_qvfctiduz", + "qpx.qvfctidz" => "__builtin_qpx_qvfctidz", + "qpx.qvfctiw" => "__builtin_qpx_qvfctiw", + "qpx.qvfctiwu" => "__builtin_qpx_qvfctiwu", + "qpx.qvfctiwuz" => "__builtin_qpx_qvfctiwuz", + "qpx.qvfctiwz" => "__builtin_qpx_qvfctiwz", + "qpx.qvflogical" => "__builtin_qpx_qvflogical", + "qpx.qvfmadd" => "__builtin_qpx_qvfmadd", + "qpx.qvfmadds" => "__builtin_qpx_qvfmadds", + "qpx.qvfmsub" => "__builtin_qpx_qvfmsub", + "qpx.qvfmsubs" => "__builtin_qpx_qvfmsubs", + "qpx.qvfmul" => "__builtin_qpx_qvfmul", + "qpx.qvfmuls" => "__builtin_qpx_qvfmuls", + "qpx.qvfnabs" => "__builtin_qpx_qvfnabs", + "qpx.qvfneg" => "__builtin_qpx_qvfneg", + "qpx.qvfnmadd" => "__builtin_qpx_qvfnmadd", + "qpx.qvfnmadds" => "__builtin_qpx_qvfnmadds", + "qpx.qvfnmsub" => "__builtin_qpx_qvfnmsub", + "qpx.qvfnmsubs" => "__builtin_qpx_qvfnmsubs", + "qpx.qvfperm" => "__builtin_qpx_qvfperm", + "qpx.qvfre" => "__builtin_qpx_qvfre", + "qpx.qvfres" => "__builtin_qpx_qvfres", + "qpx.qvfrim" => "__builtin_qpx_qvfrim", + "qpx.qvfrin" => "__builtin_qpx_qvfrin", + "qpx.qvfrip" => "__builtin_qpx_qvfrip", + "qpx.qvfriz" => "__builtin_qpx_qvfriz", + "qpx.qvfrsp" => "__builtin_qpx_qvfrsp", + "qpx.qvfrsqrte" => "__builtin_qpx_qvfrsqrte", + "qpx.qvfrsqrtes" => "__builtin_qpx_qvfrsqrtes", + "qpx.qvfsel" => "__builtin_qpx_qvfsel", + "qpx.qvfsub" => "__builtin_qpx_qvfsub", + "qpx.qvfsubs" => "__builtin_qpx_qvfsubs", + "qpx.qvftstnan" => "__builtin_qpx_qvftstnan", + "qpx.qvfxmadd" => "__builtin_qpx_qvfxmadd", + "qpx.qvfxmadds" => "__builtin_qpx_qvfxmadds", + "qpx.qvfxmul" => "__builtin_qpx_qvfxmul", + "qpx.qvfxmuls" => "__builtin_qpx_qvfxmuls", + "qpx.qvfxxcpnmadd" => "__builtin_qpx_qvfxxcpnmadd", + "qpx.qvfxxcpnmadds" => "__builtin_qpx_qvfxxcpnmadds", + "qpx.qvfxxmadd" => "__builtin_qpx_qvfxxmadd", + "qpx.qvfxxmadds" => "__builtin_qpx_qvfxxmadds", + "qpx.qvfxxnpmadd" => "__builtin_qpx_qvfxxnpmadd", + "qpx.qvfxxnpmadds" => "__builtin_qpx_qvfxxnpmadds", + "qpx.qvgpci" => "__builtin_qpx_qvgpci", + "qpx.qvlfcd" => "__builtin_qpx_qvlfcd", + "qpx.qvlfcda" => "__builtin_qpx_qvlfcda", + "qpx.qvlfcs" => "__builtin_qpx_qvlfcs", + "qpx.qvlfcsa" => "__builtin_qpx_qvlfcsa", + "qpx.qvlfd" => "__builtin_qpx_qvlfd", + "qpx.qvlfda" => "__builtin_qpx_qvlfda", + "qpx.qvlfiwa" => "__builtin_qpx_qvlfiwa", + "qpx.qvlfiwaa" => "__builtin_qpx_qvlfiwaa", + "qpx.qvlfiwz" => "__builtin_qpx_qvlfiwz", + "qpx.qvlfiwza" => "__builtin_qpx_qvlfiwza", + "qpx.qvlfs" => "__builtin_qpx_qvlfs", + "qpx.qvlfsa" => "__builtin_qpx_qvlfsa", + "qpx.qvlpcld" => "__builtin_qpx_qvlpcld", + "qpx.qvlpcls" => "__builtin_qpx_qvlpcls", + "qpx.qvlpcrd" => "__builtin_qpx_qvlpcrd", + "qpx.qvlpcrs" => "__builtin_qpx_qvlpcrs", + "qpx.qvstfcd" => "__builtin_qpx_qvstfcd", + "qpx.qvstfcda" => "__builtin_qpx_qvstfcda", + "qpx.qvstfcs" => "__builtin_qpx_qvstfcs", + "qpx.qvstfcsa" => "__builtin_qpx_qvstfcsa", + "qpx.qvstfd" => "__builtin_qpx_qvstfd", + "qpx.qvstfda" => "__builtin_qpx_qvstfda", + "qpx.qvstfiw" => "__builtin_qpx_qvstfiw", + "qpx.qvstfiwa" => "__builtin_qpx_qvstfiwa", + "qpx.qvstfs" => "__builtin_qpx_qvstfs", + "qpx.qvstfsa" => "__builtin_qpx_qvstfsa", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "ptx" => match name { + "bar.sync" => "__builtin_ptx_bar_sync", + "read.clock" => "__builtin_ptx_read_clock", + "read.clock64" => "__builtin_ptx_read_clock64", + "read.gridid" => "__builtin_ptx_read_gridid", + "read.laneid" => "__builtin_ptx_read_laneid", + "read.lanemask.eq" => "__builtin_ptx_read_lanemask_eq", + "read.lanemask.ge" => "__builtin_ptx_read_lanemask_ge", + "read.lanemask.gt" => "__builtin_ptx_read_lanemask_gt", + "read.lanemask.le" => "__builtin_ptx_read_lanemask_le", + "read.lanemask.lt" => "__builtin_ptx_read_lanemask_lt", + "read.nsmid" => "__builtin_ptx_read_nsmid", + "read.nwarpid" => "__builtin_ptx_read_nwarpid", + "read.pm0" => "__builtin_ptx_read_pm0", + "read.pm1" => "__builtin_ptx_read_pm1", + "read.pm2" => "__builtin_ptx_read_pm2", + "read.pm3" => "__builtin_ptx_read_pm3", + "read.smid" => "__builtin_ptx_read_smid", + "read.warpid" => "__builtin_ptx_read_warpid", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "x86" => match name { + "addcarry.u32" => "__builtin_ia32_addcarry_u32", + "addcarry.u64" => "__builtin_ia32_addcarry_u64", + "addcarryx.u32" => "__builtin_ia32_addcarryx_u32", + "addcarryx.u64" => "__builtin_ia32_addcarryx_u64", + "avx.blend.pd.256" => "__builtin_ia32_blendpd256", + "avx.blend.ps.256" => "__builtin_ia32_blendps256", + "avx.cmp.pd.256" => "__builtin_ia32_cmppd256", + "avx.cmp.ps.256" => "__builtin_ia32_cmpps256", + "avx.cvt.ps2.pd.256" => "__builtin_ia32_cvtps2pd256", + "avx.cvtdq2.pd.256" => "__builtin_ia32_cvtdq2pd256", + "avx.cvtdq2.ps.256" => "__builtin_ia32_cvtdq2ps256", + "avx.round.pd.256" => "__builtin_ia32_roundpd256", + "avx.round.ps.256" => "__builtin_ia32_roundps256", + "avx.sqrt.pd.256" => "__builtin_ia32_sqrtpd256", + "avx.sqrt.ps.256" => "__builtin_ia32_sqrtps256", + "avx.storeu.dq.256" => "__builtin_ia32_storedqu256", + "avx.storeu.pd.256" => "__builtin_ia32_storeupd256", + "avx.storeu.ps.256" => "__builtin_ia32_storeups256", + "avx.vbroadcastf128.pd.256" => "__builtin_ia32_vbroadcastf128_pd256", + "avx.vbroadcastf128.ps.256" => "__builtin_ia32_vbroadcastf128_ps256", + "avx.vextractf128.pd.256" => "__builtin_ia32_vextractf128_pd256", + "avx.vextractf128.ps.256" => "__builtin_ia32_vextractf128_ps256", + "avx.vextractf128.si.256" => "__builtin_ia32_vextractf128_si256", + "avx.vinsertf128.pd.256" => "__builtin_ia32_vinsertf128_pd256", + "avx.vinsertf128.ps.256" => "__builtin_ia32_vinsertf128_ps256", + "avx.vinsertf128.si.256" => "__builtin_ia32_vinsertf128_si256", + "avx.vperm2f128.pd.256" => "__builtin_ia32_vperm2f128_pd256", + "avx.vperm2f128.ps.256" => "__builtin_ia32_vperm2f128_ps256", + "avx.vperm2f128.si.256" => "__builtin_ia32_vperm2f128_si256", + "avx2.movntdqa" => "__builtin_ia32_movntdqa256", + "avx2.pabs.b" => "__builtin_ia32_pabsb256", + "avx2.pabs.d" => "__builtin_ia32_pabsd256", + "avx2.pabs.w" => "__builtin_ia32_pabsw256", + "avx2.padds.b" => "__builtin_ia32_paddsb256", + "avx2.padds.w" => "__builtin_ia32_paddsw256", + "avx2.paddus.b" => "__builtin_ia32_paddusb256", + "avx2.paddus.w" => "__builtin_ia32_paddusw256", + "avx2.pblendd.128" => "__builtin_ia32_pblendd128", + "avx2.pblendd.256" => "__builtin_ia32_pblendd256", + "avx2.pblendw" => "__builtin_ia32_pblendw256", + "avx2.pbroadcastb.128" => "__builtin_ia32_pbroadcastb128", + "avx2.pbroadcastb.256" => "__builtin_ia32_pbroadcastb256", + "avx2.pbroadcastd.128" => "__builtin_ia32_pbroadcastd128", + "avx2.pbroadcastd.256" => "__builtin_ia32_pbroadcastd256", + "avx2.pbroadcastq.128" => "__builtin_ia32_pbroadcastq128", + "avx2.pbroadcastq.256" => "__builtin_ia32_pbroadcastq256", + "avx2.pbroadcastw.128" => "__builtin_ia32_pbroadcastw128", + "avx2.pbroadcastw.256" => "__builtin_ia32_pbroadcastw256", + "avx2.pmaxs.b" => "__builtin_ia32_pmaxsb256", + "avx2.pmaxs.d" => "__builtin_ia32_pmaxsd256", + "avx2.pmaxs.w" => "__builtin_ia32_pmaxsw256", + "avx2.pmaxu.b" => "__builtin_ia32_pmaxub256", + "avx2.pmaxu.d" => "__builtin_ia32_pmaxud256", + "avx2.pmaxu.w" => "__builtin_ia32_pmaxuw256", + "avx2.pmins.b" => "__builtin_ia32_pminsb256", + "avx2.pmins.d" => "__builtin_ia32_pminsd256", + "avx2.pmins.w" => "__builtin_ia32_pminsw256", + "avx2.pminu.b" => "__builtin_ia32_pminub256", + "avx2.pminu.d" => "__builtin_ia32_pminud256", + "avx2.pminu.w" => "__builtin_ia32_pminuw256", + "avx2.pmovsxbd" => "__builtin_ia32_pmovsxbd256", + "avx2.pmovsxbq" => "__builtin_ia32_pmovsxbq256", + "avx2.pmovsxbw" => "__builtin_ia32_pmovsxbw256", + "avx2.pmovsxdq" => "__builtin_ia32_pmovsxdq256", + "avx2.pmovsxwd" => "__builtin_ia32_pmovsxwd256", + "avx2.pmovsxwq" => "__builtin_ia32_pmovsxwq256", + "avx2.pmovzxbd" => "__builtin_ia32_pmovzxbd256", + "avx2.pmovzxbq" => "__builtin_ia32_pmovzxbq256", + "avx2.pmovzxbw" => "__builtin_ia32_pmovzxbw256", + "avx2.pmovzxdq" => "__builtin_ia32_pmovzxdq256", + "avx2.pmovzxwd" => "__builtin_ia32_pmovzxwd256", + "avx2.pmovzxwq" => "__builtin_ia32_pmovzxwq256", + "avx2.pmul.dq" => "__builtin_ia32_pmuldq256", + "avx2.pmulu.dq" => "__builtin_ia32_pmuludq256", + "avx2.psll.dq" => "__builtin_ia32_pslldqi256", + "avx2.psll.dq.bs" => "__builtin_ia32_pslldqi256_byteshift", + "avx2.psrl.dq" => "__builtin_ia32_psrldqi256", + "avx2.psrl.dq.bs" => "__builtin_ia32_psrldqi256_byteshift", + "avx2.psubs.b" => "__builtin_ia32_psubsb256", + "avx2.psubs.w" => "__builtin_ia32_psubsw256", + "avx2.psubus.b" => "__builtin_ia32_psubusb256", + "avx2.psubus.w" => "__builtin_ia32_psubusw256", + "avx2.vbroadcast.sd.pd.256" => "__builtin_ia32_vbroadcastsd_pd256", + "avx2.vbroadcast.ss.ps" => "__builtin_ia32_vbroadcastss_ps", + "avx2.vbroadcast.ss.ps.256" => "__builtin_ia32_vbroadcastss_ps256", + "avx2.vextracti128" => "__builtin_ia32_extract128i256", + "avx2.vinserti128" => "__builtin_ia32_insert128i256", + "avx2.vperm2i128" => "__builtin_ia32_permti256", + "avx512.cvtb2mask.128" => "__builtin_ia32_cvtb2mask128", + "avx512.cvtb2mask.256" => "__builtin_ia32_cvtb2mask256", + "avx512.cvtb2mask.512" => "__builtin_ia32_cvtb2mask512", + "avx512.cvtd2mask.128" => "__builtin_ia32_cvtd2mask128", + "avx512.cvtd2mask.256" => "__builtin_ia32_cvtd2mask256", + "avx512.cvtd2mask.512" => "__builtin_ia32_cvtd2mask512", + "avx512.cvtmask2b.128" => "__builtin_ia32_cvtmask2b128", + "avx512.cvtmask2b.256" => "__builtin_ia32_cvtmask2b256", + "avx512.cvtmask2b.512" => "__builtin_ia32_cvtmask2b512", + "avx512.cvtmask2d.128" => "__builtin_ia32_cvtmask2d128", + "avx512.cvtmask2d.256" => "__builtin_ia32_cvtmask2d256", + "avx512.cvtmask2d.512" => "__builtin_ia32_cvtmask2d512", + "avx512.cvtmask2q.128" => "__builtin_ia32_cvtmask2q128", + "avx512.cvtmask2q.256" => "__builtin_ia32_cvtmask2q256", + "avx512.cvtmask2q.512" => "__builtin_ia32_cvtmask2q512", + "avx512.cvtmask2w.128" => "__builtin_ia32_cvtmask2w128", + "avx512.cvtmask2w.256" => "__builtin_ia32_cvtmask2w256", + "avx512.cvtmask2w.512" => "__builtin_ia32_cvtmask2w512", + "avx512.cvtq2mask.128" => "__builtin_ia32_cvtq2mask128", + "avx512.cvtq2mask.256" => "__builtin_ia32_cvtq2mask256", + "avx512.cvtq2mask.512" => "__builtin_ia32_cvtq2mask512", + "avx512.cvtsd2usi" => "__builtin_ia32_cvtsd2usi", + "avx512.cvtsd2usi64" => "__builtin_ia32_cvtsd2usi64", + "avx512.cvtsi2sd32" => "__builtin_ia32_cvtsi2sd32", + "avx512.cvtss2usi" => "__builtin_ia32_cvtss2usi", + "avx512.cvtss2usi64" => "__builtin_ia32_cvtss2usi64", + "avx512.cvtw2mask.128" => "__builtin_ia32_cvtw2mask128", + "avx512.cvtw2mask.256" => "__builtin_ia32_cvtw2mask256", + "avx512.cvtw2mask.512" => "__builtin_ia32_cvtw2mask512", + "avx512.exp2.pd" => "__builtin_ia32_exp2pd_mask", + "avx512.exp2.ps" => "__builtin_ia32_exp2ps_mask", + "avx512.gather.dpd.512" => "__builtin_ia32_gathersiv8df", + "avx512.gather.dpi.512" => "__builtin_ia32_gathersiv16si", + "avx512.gather.dpq.512" => "__builtin_ia32_gathersiv8di", + "avx512.gather.dps.512" => "__builtin_ia32_gathersiv16sf", + "avx512.gather.qpd.512" => "__builtin_ia32_gatherdiv8df", + "avx512.gather.qpi.512" => "__builtin_ia32_gatherdiv16si", + "avx512.gather.qpq.512" => "__builtin_ia32_gatherdiv8di", + "avx512.gather.qps.512" => "__builtin_ia32_gatherdiv16sf", + "avx512.gather3div2.df" => "__builtin_ia32_gather3div2df", + "avx512.gather3div2.di" => "__builtin_ia32_gather3div2di", + "avx512.gather3div4.df" => "__builtin_ia32_gather3div4df", + "avx512.gather3div4.di" => "__builtin_ia32_gather3div4di", + "avx512.gather3div4.sf" => "__builtin_ia32_gather3div4sf", + "avx512.gather3div4.si" => "__builtin_ia32_gather3div4si", + "avx512.gather3div8.sf" => "__builtin_ia32_gather3div8sf", + "avx512.gather3div8.si" => "__builtin_ia32_gather3div8si", + "avx512.gather3siv2.df" => "__builtin_ia32_gather3siv2df", + "avx512.gather3siv2.di" => "__builtin_ia32_gather3siv2di", + "avx512.gather3siv4.df" => "__builtin_ia32_gather3siv4df", + "avx512.gather3siv4.di" => "__builtin_ia32_gather3siv4di", + "avx512.gather3siv4.sf" => "__builtin_ia32_gather3siv4sf", + "avx512.gather3siv4.si" => "__builtin_ia32_gather3siv4si", + "avx512.gather3siv8.sf" => "__builtin_ia32_gather3siv8sf", + "avx512.gather3siv8.si" => "__builtin_ia32_gather3siv8si", + "avx512.gatherpf.dpd.512" => "__builtin_ia32_gatherpfdpd", + "avx512.gatherpf.dps.512" => "__builtin_ia32_gatherpfdps", + "avx512.gatherpf.qpd.512" => "__builtin_ia32_gatherpfqpd", + "avx512.gatherpf.qps.512" => "__builtin_ia32_gatherpfqps", + "avx512.kand.w" => "__builtin_ia32_kandhi", + "avx512.kandn.w" => "__builtin_ia32_kandnhi", + "avx512.knot.w" => "__builtin_ia32_knothi", + "avx512.kor.w" => "__builtin_ia32_korhi", + "avx512.kortestc.w" => "__builtin_ia32_kortestchi", + "avx512.kortestz.w" => "__builtin_ia32_kortestzhi", + "avx512.kunpck.bw" => "__builtin_ia32_kunpckhi", + "avx512.kunpck.dq" => "__builtin_ia32_kunpckdi", + "avx512.kunpck.wd" => "__builtin_ia32_kunpcksi", + "avx512.kxnor.w" => "__builtin_ia32_kxnorhi", + "avx512.kxor.w" => "__builtin_ia32_kxorhi", + "avx512.mask.add.pd.128" => "__builtin_ia32_addpd128_mask", + "avx512.mask.add.pd.256" => "__builtin_ia32_addpd256_mask", + "avx512.mask.add.pd.512" => "__builtin_ia32_addpd512_mask", + "avx512.mask.add.ps.128" => "__builtin_ia32_addps128_mask", + "avx512.mask.add.ps.256" => "__builtin_ia32_addps256_mask", + "avx512.mask.add.ps.512" => "__builtin_ia32_addps512_mask", + "avx512.mask.and.pd.128" => "__builtin_ia32_andpd128_mask", + "avx512.mask.and.pd.256" => "__builtin_ia32_andpd256_mask", + "avx512.mask.and.pd.512" => "__builtin_ia32_andpd512_mask", + "avx512.mask.and.ps.128" => "__builtin_ia32_andps128_mask", + "avx512.mask.and.ps.256" => "__builtin_ia32_andps256_mask", + "avx512.mask.and.ps.512" => "__builtin_ia32_andps512_mask", + "avx512.mask.andn.pd.128" => "__builtin_ia32_andnpd128_mask", + "avx512.mask.andn.pd.256" => "__builtin_ia32_andnpd256_mask", + "avx512.mask.andn.pd.512" => "__builtin_ia32_andnpd512_mask", + "avx512.mask.andn.ps.128" => "__builtin_ia32_andnps128_mask", + "avx512.mask.andn.ps.256" => "__builtin_ia32_andnps256_mask", + "avx512.mask.andn.ps.512" => "__builtin_ia32_andnps512_mask", + "avx512.mask.blend.d.512" => "__builtin_ia32_blendmd_512_mask", + "avx512.mask.blend.pd.512" => "__builtin_ia32_blendmpd_512_mask", + "avx512.mask.blend.ps.512" => "__builtin_ia32_blendmps_512_mask", + "avx512.mask.blend.q.512" => "__builtin_ia32_blendmq_512_mask", + "avx512.mask.broadcastf32x2.256" => "__builtin_ia32_broadcastf32x2_256_mask", + "avx512.mask.broadcastf32x2.512" => "__builtin_ia32_broadcastf32x2_512_mask", + "avx512.mask.broadcastf32x4.256" => "__builtin_ia32_broadcastf32x4_256_mask", + "avx512.mask.broadcastf32x4.512" => "__builtin_ia32_broadcastf32x4_512", + "avx512.mask.broadcastf32x8.512" => "__builtin_ia32_broadcastf32x8_512_mask", + "avx512.mask.broadcastf64x2.256" => "__builtin_ia32_broadcastf64x2_256_mask", + "avx512.mask.broadcastf64x2.512" => "__builtin_ia32_broadcastf64x2_512_mask", + "avx512.mask.broadcastf64x4.512" => "__builtin_ia32_broadcastf64x4_512", + "avx512.mask.broadcasti32x2.128" => "__builtin_ia32_broadcasti32x2_128_mask", + "avx512.mask.broadcasti32x2.256" => "__builtin_ia32_broadcasti32x2_256_mask", + "avx512.mask.broadcasti32x2.512" => "__builtin_ia32_broadcasti32x2_512_mask", + "avx512.mask.broadcasti32x4.256" => "__builtin_ia32_broadcasti32x4_256_mask", + "avx512.mask.broadcasti32x4.512" => "__builtin_ia32_broadcasti32x4_512", + "avx512.mask.broadcasti32x8.512" => "__builtin_ia32_broadcasti32x8_512_mask", + "avx512.mask.broadcasti64x2.256" => "__builtin_ia32_broadcasti64x2_256_mask", + "avx512.mask.broadcasti64x2.512" => "__builtin_ia32_broadcasti64x2_512_mask", + "avx512.mask.broadcasti64x4.512" => "__builtin_ia32_broadcasti64x4_512", + "avx512.mask.cmp.pd.128" => "__builtin_ia32_cmppd128_mask", + "avx512.mask.cmp.pd.256" => "__builtin_ia32_cmppd256_mask", + "avx512.mask.cmp.pd.512" => "__builtin_ia32_cmppd512_mask", + "avx512.mask.cmp.ps.128" => "__builtin_ia32_cmpps128_mask", + "avx512.mask.cmp.ps.256" => "__builtin_ia32_cmpps256_mask", + "avx512.mask.cmp.ps.512" => "__builtin_ia32_cmpps512_mask", + "avx512.mask.compress.d.128" => "__builtin_ia32_compresssi128_mask", + "avx512.mask.compress.d.256" => "__builtin_ia32_compresssi256_mask", + "avx512.mask.compress.d.512" => "__builtin_ia32_compresssi512_mask", + "avx512.mask.compress.pd.128" => "__builtin_ia32_compressdf128_mask", + "avx512.mask.compress.pd.256" => "__builtin_ia32_compressdf256_mask", + "avx512.mask.compress.pd.512" => "__builtin_ia32_compressdf512_mask", + "avx512.mask.compress.ps.128" => "__builtin_ia32_compresssf128_mask", + "avx512.mask.compress.ps.256" => "__builtin_ia32_compresssf256_mask", + "avx512.mask.compress.ps.512" => "__builtin_ia32_compresssf512_mask", + "avx512.mask.compress.q.128" => "__builtin_ia32_compressdi128_mask", + "avx512.mask.compress.q.256" => "__builtin_ia32_compressdi256_mask", + "avx512.mask.compress.q.512" => "__builtin_ia32_compressdi512_mask", + "avx512.mask.compress.store.d.128" => "__builtin_ia32_compressstoresi128_mask", + "avx512.mask.compress.store.d.256" => "__builtin_ia32_compressstoresi256_mask", + "avx512.mask.compress.store.d.512" => "__builtin_ia32_compressstoresi512_mask", + "avx512.mask.compress.store.pd.128" => "__builtin_ia32_compressstoredf128_mask", + "avx512.mask.compress.store.pd.256" => "__builtin_ia32_compressstoredf256_mask", + "avx512.mask.compress.store.pd.512" => "__builtin_ia32_compressstoredf512_mask", + "avx512.mask.compress.store.ps.128" => "__builtin_ia32_compressstoresf128_mask", + "avx512.mask.compress.store.ps.256" => "__builtin_ia32_compressstoresf256_mask", + "avx512.mask.compress.store.ps.512" => "__builtin_ia32_compressstoresf512_mask", + "avx512.mask.compress.store.q.128" => "__builtin_ia32_compressstoredi128_mask", + "avx512.mask.compress.store.q.256" => "__builtin_ia32_compressstoredi256_mask", + "avx512.mask.compress.store.q.512" => "__builtin_ia32_compressstoredi512_mask", + "avx512.mask.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", + "avx512.mask.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", + "avx512.mask.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", + "avx512.mask.conflict.q.128" => "__builtin_ia32_vpconflictdi_128_mask", + "avx512.mask.conflict.q.256" => "__builtin_ia32_vpconflictdi_256_mask", + "avx512.mask.conflict.q.512" => "__builtin_ia32_vpconflictdi_512_mask", + "avx512.mask.cvtdq2pd.128" => "__builtin_ia32_cvtdq2pd128_mask", + "avx512.mask.cvtdq2pd.256" => "__builtin_ia32_cvtdq2pd256_mask", + "avx512.mask.cvtdq2pd.512" => "__builtin_ia32_cvtdq2pd512_mask", + "avx512.mask.cvtdq2ps.128" => "__builtin_ia32_cvtdq2ps128_mask", + "avx512.mask.cvtdq2ps.256" => "__builtin_ia32_cvtdq2ps256_mask", + "avx512.mask.cvtdq2ps.512" => "__builtin_ia32_cvtdq2ps512_mask", + "avx512.mask.cvtpd2dq.256" => "__builtin_ia32_cvtpd2dq256_mask", + "avx512.mask.cvtps2pd.128" => "__builtin_ia32_cvtps2pd128_mask", + "avx512.mask.cvtps2pd.256" => "__builtin_ia32_cvtps2pd256_mask", + "avx512.mask.cvtqq2pd.128" => "__builtin_ia32_cvtqq2pd128_mask", + "avx512.mask.cvtqq2pd.256" => "__builtin_ia32_cvtqq2pd256_mask", + "avx512.mask.cvtqq2pd.512" => "__builtin_ia32_cvtqq2pd512_mask", + "avx512.mask.cvtqq2ps.256" => "__builtin_ia32_cvtqq2ps256_mask", + "avx512.mask.cvtqq2ps.512" => "__builtin_ia32_cvtqq2ps512_mask", + "avx512.mask.cvttpd2dq.256" => "__builtin_ia32_cvttpd2dq256_mask", + "avx512.mask.cvttps2dq.128" => "__builtin_ia32_cvttps2dq128_mask", + "avx512.mask.cvttps2dq.256" => "__builtin_ia32_cvttps2dq256_mask", + "avx512.mask.cvtudq2pd.128" => "__builtin_ia32_cvtudq2pd128_mask", + "avx512.mask.cvtudq2pd.256" => "__builtin_ia32_cvtudq2pd256_mask", + "avx512.mask.cvtudq2pd.512" => "__builtin_ia32_cvtudq2pd512_mask", + "avx512.mask.cvtudq2ps.128" => "__builtin_ia32_cvtudq2ps128_mask", + "avx512.mask.cvtudq2ps.256" => "__builtin_ia32_cvtudq2ps256_mask", + "avx512.mask.cvtudq2ps.512" => "__builtin_ia32_cvtudq2ps512_mask", + "avx512.mask.cvtuqq2pd.128" => "__builtin_ia32_cvtuqq2pd128_mask", + "avx512.mask.cvtuqq2pd.256" => "__builtin_ia32_cvtuqq2pd256_mask", + "avx512.mask.cvtuqq2pd.512" => "__builtin_ia32_cvtuqq2pd512_mask", + "avx512.mask.cvtuqq2ps.256" => "__builtin_ia32_cvtuqq2ps256_mask", + "avx512.mask.cvtuqq2ps.512" => "__builtin_ia32_cvtuqq2ps512_mask", + "avx512.mask.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128_mask", + "avx512.mask.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256_mask", + "avx512.mask.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512_mask", + "avx512.mask.div.pd.128" => "__builtin_ia32_divpd_mask", + "avx512.mask.div.pd.256" => "__builtin_ia32_divpd256_mask", + "avx512.mask.div.pd.512" => "__builtin_ia32_divpd512_mask", + "avx512.mask.div.ps.128" => "__builtin_ia32_divps_mask", + "avx512.mask.div.ps.256" => "__builtin_ia32_divps256_mask", + "avx512.mask.div.ps.512" => "__builtin_ia32_divps512_mask", + "avx512.mask.expand.d.128" => "__builtin_ia32_expandsi128_mask", + "avx512.mask.expand.d.256" => "__builtin_ia32_expandsi256_mask", + "avx512.mask.expand.d.512" => "__builtin_ia32_expandsi512_mask", + "avx512.mask.expand.load.d.128" => "__builtin_ia32_expandloadsi128_mask", + "avx512.mask.expand.load.d.256" => "__builtin_ia32_expandloadsi256_mask", + "avx512.mask.expand.load.d.512" => "__builtin_ia32_expandloadsi512_mask", + "avx512.mask.expand.load.pd.128" => "__builtin_ia32_expandloaddf128_mask", + "avx512.mask.expand.load.pd.256" => "__builtin_ia32_expandloaddf256_mask", + "avx512.mask.expand.load.pd.512" => "__builtin_ia32_expandloaddf512_mask", + "avx512.mask.expand.load.ps.128" => "__builtin_ia32_expandloadsf128_mask", + "avx512.mask.expand.load.ps.256" => "__builtin_ia32_expandloadsf256_mask", + "avx512.mask.expand.load.ps.512" => "__builtin_ia32_expandloadsf512_mask", + "avx512.mask.expand.load.q.128" => "__builtin_ia32_expandloaddi128_mask", + "avx512.mask.expand.load.q.256" => "__builtin_ia32_expandloaddi256_mask", + "avx512.mask.expand.load.q.512" => "__builtin_ia32_expandloaddi512_mask", + "avx512.mask.expand.pd.128" => "__builtin_ia32_expanddf128_mask", + "avx512.mask.expand.pd.256" => "__builtin_ia32_expanddf256_mask", + "avx512.mask.expand.pd.512" => "__builtin_ia32_expanddf512_mask", + "avx512.mask.expand.ps.128" => "__builtin_ia32_expandsf128_mask", + "avx512.mask.expand.ps.256" => "__builtin_ia32_expandsf256_mask", + "avx512.mask.expand.ps.512" => "__builtin_ia32_expandsf512_mask", + "avx512.mask.expand.q.128" => "__builtin_ia32_expanddi128_mask", + "avx512.mask.expand.q.256" => "__builtin_ia32_expanddi256_mask", + "avx512.mask.expand.q.512" => "__builtin_ia32_expanddi512_mask", + "avx512.mask.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "avx512.mask.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "avx512.mask.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "avx512.mask.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "avx512.mask.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "avx512.mask.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", + "avx512.mask.insertf32x4.256" => "__builtin_ia32_insertf32x4_256_mask", + "avx512.mask.insertf32x4.512" => "__builtin_ia32_insertf32x4_mask", + "avx512.mask.insertf32x8.512" => "__builtin_ia32_insertf32x8_mask", + "avx512.mask.insertf64x2.256" => "__builtin_ia32_insertf64x2_256_mask", + "avx512.mask.insertf64x2.512" => "__builtin_ia32_insertf64x2_512_mask", + "avx512.mask.insertf64x4.512" => "__builtin_ia32_insertf64x4_mask", + "avx512.mask.inserti32x4.256" => "__builtin_ia32_inserti32x4_256_mask", + "avx512.mask.inserti32x4.512" => "__builtin_ia32_inserti32x4_mask", + "avx512.mask.inserti32x8.512" => "__builtin_ia32_inserti32x8_mask", + "avx512.mask.inserti64x2.256" => "__builtin_ia32_inserti64x2_256_mask", + "avx512.mask.inserti64x2.512" => "__builtin_ia32_inserti64x2_512_mask", + "avx512.mask.inserti64x4.512" => "__builtin_ia32_inserti64x4_mask", + "avx512.mask.loadu.d.512" => "__builtin_ia32_loaddqusi512_mask", + "avx512.mask.loadu.pd.512" => "__builtin_ia32_loadupd512_mask", + "avx512.mask.loadu.ps.512" => "__builtin_ia32_loadups512_mask", + "avx512.mask.loadu.q.512" => "__builtin_ia32_loaddqudi512_mask", + "avx512.mask.lzcnt.d.512" => "__builtin_ia32_vplzcntd_512_mask", + "avx512.mask.lzcnt.q.512" => "__builtin_ia32_vplzcntq_512_mask", + "avx512.mask.max.pd.128" => "__builtin_ia32_maxpd_mask", + "avx512.mask.max.pd.256" => "__builtin_ia32_maxpd256_mask", + "avx512.mask.max.pd.512" => "__builtin_ia32_maxpd512_mask", + "avx512.mask.max.ps.128" => "__builtin_ia32_maxps_mask", + "avx512.mask.max.ps.256" => "__builtin_ia32_maxps256_mask", + "avx512.mask.max.ps.512" => "__builtin_ia32_maxps512_mask", + "avx512.mask.min.pd.128" => "__builtin_ia32_minpd_mask", + "avx512.mask.min.pd.256" => "__builtin_ia32_minpd256_mask", + "avx512.mask.min.pd.512" => "__builtin_ia32_minpd512_mask", + "avx512.mask.min.ps.128" => "__builtin_ia32_minps_mask", + "avx512.mask.min.ps.256" => "__builtin_ia32_minps256_mask", + "avx512.mask.min.ps.512" => "__builtin_ia32_minps512_mask", + "avx512.mask.move.sd" => "__builtin_ia32_movsd_mask", + "avx512.mask.move.ss" => "__builtin_ia32_movss_mask", + "avx512.mask.mul.pd.128" => "__builtin_ia32_mulpd_mask", + "avx512.mask.mul.pd.256" => "__builtin_ia32_mulpd256_mask", + "avx512.mask.mul.pd.512" => "__builtin_ia32_mulpd512_mask", + "avx512.mask.mul.ps.128" => "__builtin_ia32_mulps_mask", + "avx512.mask.mul.ps.256" => "__builtin_ia32_mulps256_mask", + "avx512.mask.mul.ps.512" => "__builtin_ia32_mulps512_mask", + "avx512.mask.or.pd.128" => "__builtin_ia32_orpd128_mask", + "avx512.mask.or.pd.256" => "__builtin_ia32_orpd256_mask", + "avx512.mask.or.pd.512" => "__builtin_ia32_orpd512_mask", + "avx512.mask.or.ps.128" => "__builtin_ia32_orps128_mask", + "avx512.mask.or.ps.256" => "__builtin_ia32_orps256_mask", + "avx512.mask.or.ps.512" => "__builtin_ia32_orps512_mask", + "avx512.mask.pabs.b.128" => "__builtin_ia32_pabsb128_mask", + "avx512.mask.pabs.b.256" => "__builtin_ia32_pabsb256_mask", + "avx512.mask.pabs.b.512" => "__builtin_ia32_pabsb512_mask", + "avx512.mask.pabs.d.128" => "__builtin_ia32_pabsd128_mask", + "avx512.mask.pabs.d.256" => "__builtin_ia32_pabsd256_mask", + "avx512.mask.pabs.d.512" => "__builtin_ia32_pabsd512_mask", + "avx512.mask.pabs.q.128" => "__builtin_ia32_pabsq128_mask", + "avx512.mask.pabs.q.256" => "__builtin_ia32_pabsq256_mask", + "avx512.mask.pabs.q.512" => "__builtin_ia32_pabsq512_mask", + "avx512.mask.pabs.w.128" => "__builtin_ia32_pabsw128_mask", + "avx512.mask.pabs.w.256" => "__builtin_ia32_pabsw256_mask", + "avx512.mask.pabs.w.512" => "__builtin_ia32_pabsw512_mask", + "avx512.mask.packssdw.128" => "__builtin_ia32_packssdw128_mask", + "avx512.mask.packssdw.256" => "__builtin_ia32_packssdw256_mask", + "avx512.mask.packssdw.512" => "__builtin_ia32_packssdw512_mask", + "avx512.mask.packsswb.128" => "__builtin_ia32_packsswb128_mask", + "avx512.mask.packsswb.256" => "__builtin_ia32_packsswb256_mask", + "avx512.mask.packsswb.512" => "__builtin_ia32_packsswb512_mask", + "avx512.mask.packusdw.128" => "__builtin_ia32_packusdw128_mask", + "avx512.mask.packusdw.256" => "__builtin_ia32_packusdw256_mask", + "avx512.mask.packusdw.512" => "__builtin_ia32_packusdw512_mask", + "avx512.mask.packuswb.128" => "__builtin_ia32_packuswb128_mask", + "avx512.mask.packuswb.256" => "__builtin_ia32_packuswb256_mask", + "avx512.mask.packuswb.512" => "__builtin_ia32_packuswb512_mask", + "avx512.mask.padd.b.128" => "__builtin_ia32_paddb128_mask", + "avx512.mask.padd.b.256" => "__builtin_ia32_paddb256_mask", + "avx512.mask.padd.b.512" => "__builtin_ia32_paddb512_mask", + "avx512.mask.padd.d.128" => "__builtin_ia32_paddd128_mask", + "avx512.mask.padd.d.256" => "__builtin_ia32_paddd256_mask", + "avx512.mask.padd.d.512" => "__builtin_ia32_paddd512_mask", + "avx512.mask.padd.q.128" => "__builtin_ia32_paddq128_mask", + "avx512.mask.padd.q.256" => "__builtin_ia32_paddq256_mask", + "avx512.mask.padd.q.512" => "__builtin_ia32_paddq512_mask", + "avx512.mask.padd.w.128" => "__builtin_ia32_paddw128_mask", + "avx512.mask.padd.w.256" => "__builtin_ia32_paddw256_mask", + "avx512.mask.padd.w.512" => "__builtin_ia32_paddw512_mask", + "avx512.mask.padds.b.128" => "__builtin_ia32_paddsb128_mask", + "avx512.mask.padds.b.256" => "__builtin_ia32_paddsb256_mask", + "avx512.mask.padds.b.512" => "__builtin_ia32_paddsb512_mask", + "avx512.mask.padds.w.128" => "__builtin_ia32_paddsw128_mask", + "avx512.mask.padds.w.256" => "__builtin_ia32_paddsw256_mask", + "avx512.mask.padds.w.512" => "__builtin_ia32_paddsw512_mask", + "avx512.mask.paddus.b.128" => "__builtin_ia32_paddusb128_mask", + "avx512.mask.paddus.b.256" => "__builtin_ia32_paddusb256_mask", + "avx512.mask.paddus.b.512" => "__builtin_ia32_paddusb512_mask", + "avx512.mask.paddus.w.128" => "__builtin_ia32_paddusw128_mask", + "avx512.mask.paddus.w.256" => "__builtin_ia32_paddusw256_mask", + "avx512.mask.paddus.w.512" => "__builtin_ia32_paddusw512_mask", + "avx512.mask.pand.d.512" => "__builtin_ia32_pandd512_mask", + "avx512.mask.pand.q.512" => "__builtin_ia32_pandq512_mask", + "avx512.mask.pavg.b.128" => "__builtin_ia32_pavgb128_mask", + "avx512.mask.pavg.b.256" => "__builtin_ia32_pavgb256_mask", + "avx512.mask.pavg.b.512" => "__builtin_ia32_pavgb512_mask", + "avx512.mask.pavg.w.128" => "__builtin_ia32_pavgw128_mask", + "avx512.mask.pavg.w.256" => "__builtin_ia32_pavgw256_mask", + "avx512.mask.pavg.w.512" => "__builtin_ia32_pavgw512_mask", + "avx512.mask.pbroadcast.b.gpr.128" => "__builtin_ia32_pbroadcastb128_gpr_mask", + "avx512.mask.pbroadcast.b.gpr.256" => "__builtin_ia32_pbroadcastb256_gpr_mask", + "avx512.mask.pbroadcast.b.gpr.512" => "__builtin_ia32_pbroadcastb512_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.128" => "__builtin_ia32_pbroadcastd128_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.256" => "__builtin_ia32_pbroadcastd256_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.512" => "__builtin_ia32_pbroadcastd512_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.128" => "__builtin_ia32_pbroadcastq128_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.256" => "__builtin_ia32_pbroadcastq256_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.512" => "__builtin_ia32_pbroadcastq512_gpr_mask", + "avx512.mask.pbroadcast.q.mem.512" => "__builtin_ia32_pbroadcastq512_mem_mask", + "avx512.mask.pbroadcast.w.gpr.128" => "__builtin_ia32_pbroadcastw128_gpr_mask", + "avx512.mask.pbroadcast.w.gpr.256" => "__builtin_ia32_pbroadcastw256_gpr_mask", + "avx512.mask.pbroadcast.w.gpr.512" => "__builtin_ia32_pbroadcastw512_gpr_mask", + "avx512.mask.pcmpeq.b.128" => "__builtin_ia32_pcmpeqb128_mask", + "avx512.mask.pcmpeq.b.256" => "__builtin_ia32_pcmpeqb256_mask", + "avx512.mask.pcmpeq.b.512" => "__builtin_ia32_pcmpeqb512_mask", + "avx512.mask.pcmpeq.d.128" => "__builtin_ia32_pcmpeqd128_mask", + "avx512.mask.pcmpeq.d.256" => "__builtin_ia32_pcmpeqd256_mask", + "avx512.mask.pcmpeq.d.512" => "__builtin_ia32_pcmpeqd512_mask", + "avx512.mask.pcmpeq.q.128" => "__builtin_ia32_pcmpeqq128_mask", + "avx512.mask.pcmpeq.q.256" => "__builtin_ia32_pcmpeqq256_mask", + "avx512.mask.pcmpeq.q.512" => "__builtin_ia32_pcmpeqq512_mask", + "avx512.mask.pcmpeq.w.128" => "__builtin_ia32_pcmpeqw128_mask", + "avx512.mask.pcmpeq.w.256" => "__builtin_ia32_pcmpeqw256_mask", + "avx512.mask.pcmpeq.w.512" => "__builtin_ia32_pcmpeqw512_mask", + "avx512.mask.pcmpgt.b.128" => "__builtin_ia32_pcmpgtb128_mask", + "avx512.mask.pcmpgt.b.256" => "__builtin_ia32_pcmpgtb256_mask", + "avx512.mask.pcmpgt.b.512" => "__builtin_ia32_pcmpgtb512_mask", + "avx512.mask.pcmpgt.d.128" => "__builtin_ia32_pcmpgtd128_mask", + "avx512.mask.pcmpgt.d.256" => "__builtin_ia32_pcmpgtd256_mask", + "avx512.mask.pcmpgt.d.512" => "__builtin_ia32_pcmpgtd512_mask", + "avx512.mask.pcmpgt.q.128" => "__builtin_ia32_pcmpgtq128_mask", + "avx512.mask.pcmpgt.q.256" => "__builtin_ia32_pcmpgtq256_mask", + "avx512.mask.pcmpgt.q.512" => "__builtin_ia32_pcmpgtq512_mask", + "avx512.mask.pcmpgt.w.128" => "__builtin_ia32_pcmpgtw128_mask", + "avx512.mask.pcmpgt.w.256" => "__builtin_ia32_pcmpgtw256_mask", + "avx512.mask.pcmpgt.w.512" => "__builtin_ia32_pcmpgtw512_mask", + "avx512.mask.permvar.df.256" => "__builtin_ia32_permvardf256_mask", + "avx512.mask.permvar.df.512" => "__builtin_ia32_permvardf512_mask", + "avx512.mask.permvar.di.256" => "__builtin_ia32_permvardi256_mask", + "avx512.mask.permvar.di.512" => "__builtin_ia32_permvardi512_mask", + "avx512.mask.permvar.hi.128" => "__builtin_ia32_permvarhi128_mask", + "avx512.mask.permvar.hi.256" => "__builtin_ia32_permvarhi256_mask", + "avx512.mask.permvar.hi.512" => "__builtin_ia32_permvarhi512_mask", + "avx512.mask.permvar.qi.128" => "__builtin_ia32_permvarqi128_mask", + "avx512.mask.permvar.qi.256" => "__builtin_ia32_permvarqi256_mask", + "avx512.mask.permvar.qi.512" => "__builtin_ia32_permvarqi512_mask", + "avx512.mask.permvar.sf.256" => "__builtin_ia32_permvarsf256_mask", + "avx512.mask.permvar.sf.512" => "__builtin_ia32_permvarsf512_mask", + "avx512.mask.permvar.si.256" => "__builtin_ia32_permvarsi256_mask", + "avx512.mask.permvar.si.512" => "__builtin_ia32_permvarsi512_mask", + "avx512.mask.pmaddubs.w.128" => "__builtin_ia32_pmaddubsw128_mask", + "avx512.mask.pmaddubs.w.256" => "__builtin_ia32_pmaddubsw256_mask", + "avx512.mask.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512_mask", + "avx512.mask.pmaddw.d.128" => "__builtin_ia32_pmaddwd128_mask", + "avx512.mask.pmaddw.d.256" => "__builtin_ia32_pmaddwd256_mask", + "avx512.mask.pmaddw.d.512" => "__builtin_ia32_pmaddwd512_mask", + "avx512.mask.pmaxs.b.128" => "__builtin_ia32_pmaxsb128_mask", + "avx512.mask.pmaxs.b.256" => "__builtin_ia32_pmaxsb256_mask", + "avx512.mask.pmaxs.b.512" => "__builtin_ia32_pmaxsb512_mask", + "avx512.mask.pmaxs.d.128" => "__builtin_ia32_pmaxsd128_mask", + "avx512.mask.pmaxs.d.256" => "__builtin_ia32_pmaxsd256_mask", + "avx512.mask.pmaxs.d.512" => "__builtin_ia32_pmaxsd512_mask", + "avx512.mask.pmaxs.q.128" => "__builtin_ia32_pmaxsq128_mask", + "avx512.mask.pmaxs.q.256" => "__builtin_ia32_pmaxsq256_mask", + "avx512.mask.pmaxs.q.512" => "__builtin_ia32_pmaxsq512_mask", + "avx512.mask.pmaxs.w.128" => "__builtin_ia32_pmaxsw128_mask", + "avx512.mask.pmaxs.w.256" => "__builtin_ia32_pmaxsw256_mask", + "avx512.mask.pmaxs.w.512" => "__builtin_ia32_pmaxsw512_mask", + "avx512.mask.pmaxu.b.128" => "__builtin_ia32_pmaxub128_mask", + "avx512.mask.pmaxu.b.256" => "__builtin_ia32_pmaxub256_mask", + "avx512.mask.pmaxu.b.512" => "__builtin_ia32_pmaxub512_mask", + "avx512.mask.pmaxu.d.128" => "__builtin_ia32_pmaxud128_mask", + "avx512.mask.pmaxu.d.256" => "__builtin_ia32_pmaxud256_mask", + "avx512.mask.pmaxu.d.512" => "__builtin_ia32_pmaxud512_mask", + "avx512.mask.pmaxu.q.128" => "__builtin_ia32_pmaxuq128_mask", + "avx512.mask.pmaxu.q.256" => "__builtin_ia32_pmaxuq256_mask", + "avx512.mask.pmaxu.q.512" => "__builtin_ia32_pmaxuq512_mask", + "avx512.mask.pmaxu.w.128" => "__builtin_ia32_pmaxuw128_mask", + "avx512.mask.pmaxu.w.256" => "__builtin_ia32_pmaxuw256_mask", + "avx512.mask.pmaxu.w.512" => "__builtin_ia32_pmaxuw512_mask", + "avx512.mask.pmins.b.128" => "__builtin_ia32_pminsb128_mask", + "avx512.mask.pmins.b.256" => "__builtin_ia32_pminsb256_mask", + "avx512.mask.pmins.b.512" => "__builtin_ia32_pminsb512_mask", + "avx512.mask.pmins.d.128" => "__builtin_ia32_pminsd128_mask", + "avx512.mask.pmins.d.256" => "__builtin_ia32_pminsd256_mask", + "avx512.mask.pmins.d.512" => "__builtin_ia32_pminsd512_mask", + "avx512.mask.pmins.q.128" => "__builtin_ia32_pminsq128_mask", + "avx512.mask.pmins.q.256" => "__builtin_ia32_pminsq256_mask", + "avx512.mask.pmins.q.512" => "__builtin_ia32_pminsq512_mask", + "avx512.mask.pmins.w.128" => "__builtin_ia32_pminsw128_mask", + "avx512.mask.pmins.w.256" => "__builtin_ia32_pminsw256_mask", + "avx512.mask.pmins.w.512" => "__builtin_ia32_pminsw512_mask", + "avx512.mask.pminu.b.128" => "__builtin_ia32_pminub128_mask", + "avx512.mask.pminu.b.256" => "__builtin_ia32_pminub256_mask", + "avx512.mask.pminu.b.512" => "__builtin_ia32_pminub512_mask", + "avx512.mask.pminu.d.128" => "__builtin_ia32_pminud128_mask", + "avx512.mask.pminu.d.256" => "__builtin_ia32_pminud256_mask", + "avx512.mask.pminu.d.512" => "__builtin_ia32_pminud512_mask", + "avx512.mask.pminu.q.128" => "__builtin_ia32_pminuq128_mask", + "avx512.mask.pminu.q.256" => "__builtin_ia32_pminuq256_mask", + "avx512.mask.pminu.q.512" => "__builtin_ia32_pminuq512_mask", + "avx512.mask.pminu.w.128" => "__builtin_ia32_pminuw128_mask", + "avx512.mask.pminu.w.256" => "__builtin_ia32_pminuw256_mask", + "avx512.mask.pminu.w.512" => "__builtin_ia32_pminuw512_mask", + "avx512.mask.pmov.db.512" => "__builtin_ia32_pmovdb512_mask", + "avx512.mask.pmov.dw.512" => "__builtin_ia32_pmovdw512_mask", + "avx512.mask.pmov.qd.256" => "__builtin_ia32_pmovqd256_mask", + "avx512.mask.pmov.qd.512" => "__builtin_ia32_pmovqd512_mask", + "avx512.mask.pmov.qw.512" => "__builtin_ia32_pmovqw512_mask", + "avx512.mask.pmov.wb.256" => "__builtin_ia32_pmovwb256_mask", + "avx512.mask.pmov.wb.512" => "__builtin_ia32_pmovwb512_mask", + "avx512.mask.pmovsxb.d.128" => "__builtin_ia32_pmovsxbd128_mask", + "avx512.mask.pmovsxb.d.256" => "__builtin_ia32_pmovsxbd256_mask", + "avx512.mask.pmovsxb.d.512" => "__builtin_ia32_pmovsxbd512_mask", + "avx512.mask.pmovsxb.q.128" => "__builtin_ia32_pmovsxbq128_mask", + "avx512.mask.pmovsxb.q.256" => "__builtin_ia32_pmovsxbq256_mask", + "avx512.mask.pmovsxb.q.512" => "__builtin_ia32_pmovsxbq512_mask", + "avx512.mask.pmovsxb.w.128" => "__builtin_ia32_pmovsxbw128_mask", + "avx512.mask.pmovsxb.w.256" => "__builtin_ia32_pmovsxbw256_mask", + "avx512.mask.pmovsxb.w.512" => "__builtin_ia32_pmovsxbw512_mask", + "avx512.mask.pmovsxd.q.128" => "__builtin_ia32_pmovsxdq128_mask", + "avx512.mask.pmovsxd.q.256" => "__builtin_ia32_pmovsxdq256_mask", + "avx512.mask.pmovsxd.q.512" => "__builtin_ia32_pmovsxdq512_mask", + "avx512.mask.pmovsxw.d.128" => "__builtin_ia32_pmovsxwd128_mask", + "avx512.mask.pmovsxw.d.256" => "__builtin_ia32_pmovsxwd256_mask", + "avx512.mask.pmovsxw.d.512" => "__builtin_ia32_pmovsxwd512_mask", + "avx512.mask.pmovsxw.q.128" => "__builtin_ia32_pmovsxwq128_mask", + "avx512.mask.pmovsxw.q.256" => "__builtin_ia32_pmovsxwq256_mask", + "avx512.mask.pmovsxw.q.512" => "__builtin_ia32_pmovsxwq512_mask", + "avx512.mask.pmovzxb.d.128" => "__builtin_ia32_pmovzxbd128_mask", + "avx512.mask.pmovzxb.d.256" => "__builtin_ia32_pmovzxbd256_mask", + "avx512.mask.pmovzxb.d.512" => "__builtin_ia32_pmovzxbd512_mask", + "avx512.mask.pmovzxb.q.128" => "__builtin_ia32_pmovzxbq128_mask", + "avx512.mask.pmovzxb.q.256" => "__builtin_ia32_pmovzxbq256_mask", + "avx512.mask.pmovzxb.q.512" => "__builtin_ia32_pmovzxbq512_mask", + "avx512.mask.pmovzxb.w.128" => "__builtin_ia32_pmovzxbw128_mask", + "avx512.mask.pmovzxb.w.256" => "__builtin_ia32_pmovzxbw256_mask", + "avx512.mask.pmovzxb.w.512" => "__builtin_ia32_pmovzxbw512_mask", + "avx512.mask.pmovzxd.q.128" => "__builtin_ia32_pmovzxdq128_mask", + "avx512.mask.pmovzxd.q.256" => "__builtin_ia32_pmovzxdq256_mask", + "avx512.mask.pmovzxd.q.512" => "__builtin_ia32_pmovzxdq512_mask", + "avx512.mask.pmovzxw.d.128" => "__builtin_ia32_pmovzxwd128_mask", + "avx512.mask.pmovzxw.d.256" => "__builtin_ia32_pmovzxwd256_mask", + "avx512.mask.pmovzxw.d.512" => "__builtin_ia32_pmovzxwd512_mask", + "avx512.mask.pmovzxw.q.128" => "__builtin_ia32_pmovzxwq128_mask", + "avx512.mask.pmovzxw.q.256" => "__builtin_ia32_pmovzxwq256_mask", + "avx512.mask.pmovzxw.q.512" => "__builtin_ia32_pmovzxwq512_mask", + "avx512.mask.pmul.dq.128" => "__builtin_ia32_pmuldq128_mask", + "avx512.mask.pmul.dq.256" => "__builtin_ia32_pmuldq256_mask", + "avx512.mask.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", + "avx512.mask.pmul.hr.sw.128" => "__builtin_ia32_pmulhrsw128_mask", + "avx512.mask.pmul.hr.sw.256" => "__builtin_ia32_pmulhrsw256_mask", + "avx512.mask.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512_mask", + "avx512.mask.pmulh.w.128" => "__builtin_ia32_pmulhw128_mask", + "avx512.mask.pmulh.w.256" => "__builtin_ia32_pmulhw256_mask", + "avx512.mask.pmulh.w.512" => "__builtin_ia32_pmulhw512_mask", + "avx512.mask.pmulhu.w.128" => "__builtin_ia32_pmulhuw128_mask", + "avx512.mask.pmulhu.w.256" => "__builtin_ia32_pmulhuw256_mask", + "avx512.mask.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", + "avx512.mask.pmull.d.128" => "__builtin_ia32_pmulld128_mask", + "avx512.mask.pmull.d.256" => "__builtin_ia32_pmulld256_mask", + "avx512.mask.pmull.d.512" => "__builtin_ia32_pmulld512_mask", + "avx512.mask.pmull.q.128" => "__builtin_ia32_pmullq128_mask", + "avx512.mask.pmull.q.256" => "__builtin_ia32_pmullq256_mask", + "avx512.mask.pmull.q.512" => "__builtin_ia32_pmullq512_mask", + "avx512.mask.pmull.w.128" => "__builtin_ia32_pmullw128_mask", + "avx512.mask.pmull.w.256" => "__builtin_ia32_pmullw256_mask", + "avx512.mask.pmull.w.512" => "__builtin_ia32_pmullw512_mask", + "avx512.mask.pmultishift.qb.128" => "__builtin_ia32_vpmultishiftqb128_mask", + "avx512.mask.pmultishift.qb.256" => "__builtin_ia32_vpmultishiftqb256_mask", + "avx512.mask.pmultishift.qb.512" => "__builtin_ia32_vpmultishiftqb512_mask", + "avx512.mask.pmulu.dq.128" => "__builtin_ia32_pmuludq128_mask", + "avx512.mask.pmulu.dq.256" => "__builtin_ia32_pmuludq256_mask", + "avx512.mask.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", + "avx512.mask.prol.d.128" => "__builtin_ia32_prold128_mask", + "avx512.mask.prol.d.256" => "__builtin_ia32_prold256_mask", + "avx512.mask.prol.d.512" => "__builtin_ia32_prold512_mask", + "avx512.mask.prol.q.128" => "__builtin_ia32_prolq128_mask", + "avx512.mask.prol.q.256" => "__builtin_ia32_prolq256_mask", + "avx512.mask.prol.q.512" => "__builtin_ia32_prolq512_mask", + "avx512.mask.prolv.d.128" => "__builtin_ia32_prolvd128_mask", + "avx512.mask.prolv.d.256" => "__builtin_ia32_prolvd256_mask", + "avx512.mask.prolv.d.512" => "__builtin_ia32_prolvd512_mask", + "avx512.mask.prolv.q.128" => "__builtin_ia32_prolvq128_mask", + "avx512.mask.prolv.q.256" => "__builtin_ia32_prolvq256_mask", + "avx512.mask.prolv.q.512" => "__builtin_ia32_prolvq512_mask", + "avx512.mask.pror.d.128" => "__builtin_ia32_prord128_mask", + "avx512.mask.pror.d.256" => "__builtin_ia32_prord256_mask", + "avx512.mask.pror.d.512" => "__builtin_ia32_prord512_mask", + "avx512.mask.pror.q.128" => "__builtin_ia32_prorq128_mask", + "avx512.mask.pror.q.256" => "__builtin_ia32_prorq256_mask", + "avx512.mask.pror.q.512" => "__builtin_ia32_prorq512_mask", + "avx512.mask.prorv.d.128" => "__builtin_ia32_prorvd128_mask", + "avx512.mask.prorv.d.256" => "__builtin_ia32_prorvd256_mask", + "avx512.mask.prorv.d.512" => "__builtin_ia32_prorvd512_mask", + "avx512.mask.prorv.q.128" => "__builtin_ia32_prorvq128_mask", + "avx512.mask.prorv.q.256" => "__builtin_ia32_prorvq256_mask", + "avx512.mask.prorv.q.512" => "__builtin_ia32_prorvq512_mask", + "avx512.mask.pshuf.b.128" => "__builtin_ia32_pshufb128_mask", + "avx512.mask.pshuf.b.256" => "__builtin_ia32_pshufb256_mask", + "avx512.mask.pshuf.b.512" => "__builtin_ia32_pshufb512_mask", + "avx512.mask.psll.d" => "__builtin_ia32_pslld512_mask", + "avx512.mask.psll.d.128" => "__builtin_ia32_pslld128_mask", + "avx512.mask.psll.d.256" => "__builtin_ia32_pslld256_mask", + "avx512.mask.psll.di.128" => "__builtin_ia32_pslldi128_mask", + "avx512.mask.psll.di.256" => "__builtin_ia32_pslldi256_mask", + "avx512.mask.psll.di.512" => "__builtin_ia32_pslldi512_mask", + "avx512.mask.psll.q" => "__builtin_ia32_psllq512_mask", + "avx512.mask.psll.q.128" => "__builtin_ia32_psllq128_mask", + "avx512.mask.psll.q.256" => "__builtin_ia32_psllq256_mask", + "avx512.mask.psll.qi.128" => "__builtin_ia32_psllqi128_mask", + "avx512.mask.psll.qi.256" => "__builtin_ia32_psllqi256_mask", + "avx512.mask.psll.qi.512" => "__builtin_ia32_psllqi512_mask", + "avx512.mask.psll.w.128" => "__builtin_ia32_psllw128_mask", + "avx512.mask.psll.w.256" => "__builtin_ia32_psllw256_mask", + "avx512.mask.psll.w.512" => "__builtin_ia32_psllw512_mask", + "avx512.mask.psll.wi.128" => "__builtin_ia32_psllwi128_mask", + "avx512.mask.psll.wi.256" => "__builtin_ia32_psllwi256_mask", + "avx512.mask.psll.wi.512" => "__builtin_ia32_psllwi512_mask", + "avx512.mask.psllv.d" => "__builtin_ia32_psllv16si_mask", + "avx512.mask.psllv.q" => "__builtin_ia32_psllv8di_mask", + "avx512.mask.psllv16.hi" => "__builtin_ia32_psllv16hi_mask", + "avx512.mask.psllv2.di" => "__builtin_ia32_psllv2di_mask", + "avx512.mask.psllv32hi" => "__builtin_ia32_psllv32hi_mask", + "avx512.mask.psllv4.di" => "__builtin_ia32_psllv4di_mask", + "avx512.mask.psllv4.si" => "__builtin_ia32_psllv4si_mask", + "avx512.mask.psllv8.hi" => "__builtin_ia32_psllv8hi_mask", + "avx512.mask.psllv8.si" => "__builtin_ia32_psllv8si_mask", + "avx512.mask.psra.d" => "__builtin_ia32_psrad512_mask", + "avx512.mask.psra.d.128" => "__builtin_ia32_psrad128_mask", + "avx512.mask.psra.d.256" => "__builtin_ia32_psrad256_mask", + "avx512.mask.psra.di.128" => "__builtin_ia32_psradi128_mask", + "avx512.mask.psra.di.256" => "__builtin_ia32_psradi256_mask", + "avx512.mask.psra.di.512" => "__builtin_ia32_psradi512_mask", + "avx512.mask.psra.q" => "__builtin_ia32_psraq512_mask", + "avx512.mask.psra.q.128" => "__builtin_ia32_psraq128_mask", + "avx512.mask.psra.q.256" => "__builtin_ia32_psraq256_mask", + "avx512.mask.psra.qi.128" => "__builtin_ia32_psraqi128_mask", + "avx512.mask.psra.qi.256" => "__builtin_ia32_psraqi256_mask", + "avx512.mask.psra.qi.512" => "__builtin_ia32_psraqi512_mask", + "avx512.mask.psra.w.128" => "__builtin_ia32_psraw128_mask", + "avx512.mask.psra.w.256" => "__builtin_ia32_psraw256_mask", + "avx512.mask.psra.w.512" => "__builtin_ia32_psraw512_mask", + "avx512.mask.psra.wi.128" => "__builtin_ia32_psrawi128_mask", + "avx512.mask.psra.wi.256" => "__builtin_ia32_psrawi256_mask", + "avx512.mask.psra.wi.512" => "__builtin_ia32_psrawi512_mask", + "avx512.mask.psrav.d" => "__builtin_ia32_psrav16si_mask", + "avx512.mask.psrav.q" => "__builtin_ia32_psrav8di_mask", + "avx512.mask.psrav.q.128" => "__builtin_ia32_psravq128_mask", + "avx512.mask.psrav.q.256" => "__builtin_ia32_psravq256_mask", + "avx512.mask.psrav16.hi" => "__builtin_ia32_psrav16hi_mask", + "avx512.mask.psrav32.hi" => "__builtin_ia32_psrav32hi_mask", + "avx512.mask.psrav4.si" => "__builtin_ia32_psrav4si_mask", + "avx512.mask.psrav8.hi" => "__builtin_ia32_psrav8hi_mask", + "avx512.mask.psrav8.si" => "__builtin_ia32_psrav8si_mask", + "avx512.mask.psrl.d" => "__builtin_ia32_psrld512_mask", + "avx512.mask.psrl.d.128" => "__builtin_ia32_psrld128_mask", + "avx512.mask.psrl.d.256" => "__builtin_ia32_psrld256_mask", + "avx512.mask.psrl.di.128" => "__builtin_ia32_psrldi128_mask", + "avx512.mask.psrl.di.256" => "__builtin_ia32_psrldi256_mask", + "avx512.mask.psrl.di.512" => "__builtin_ia32_psrldi512_mask", + "avx512.mask.psrl.q" => "__builtin_ia32_psrlq512_mask", + "avx512.mask.psrl.q.128" => "__builtin_ia32_psrlq128_mask", + "avx512.mask.psrl.q.256" => "__builtin_ia32_psrlq256_mask", + "avx512.mask.psrl.qi.128" => "__builtin_ia32_psrlqi128_mask", + "avx512.mask.psrl.qi.256" => "__builtin_ia32_psrlqi256_mask", + "avx512.mask.psrl.qi.512" => "__builtin_ia32_psrlqi512_mask", + "avx512.mask.psrl.w.128" => "__builtin_ia32_psrlw128_mask", + "avx512.mask.psrl.w.256" => "__builtin_ia32_psrlw256_mask", + "avx512.mask.psrl.w.512" => "__builtin_ia32_psrlw512_mask", + "avx512.mask.psrl.wi.128" => "__builtin_ia32_psrlwi128_mask", + "avx512.mask.psrl.wi.256" => "__builtin_ia32_psrlwi256_mask", + "avx512.mask.psrl.wi.512" => "__builtin_ia32_psrlwi512_mask", + "avx512.mask.psrlv.d" => "__builtin_ia32_psrlv16si_mask", + "avx512.mask.psrlv.q" => "__builtin_ia32_psrlv8di_mask", + "avx512.mask.psrlv16.hi" => "__builtin_ia32_psrlv16hi_mask", + "avx512.mask.psrlv2.di" => "__builtin_ia32_psrlv2di_mask", + "avx512.mask.psrlv32hi" => "__builtin_ia32_psrlv32hi_mask", + "avx512.mask.psrlv4.di" => "__builtin_ia32_psrlv4di_mask", + "avx512.mask.psrlv4.si" => "__builtin_ia32_psrlv4si_mask", + "avx512.mask.psrlv8.hi" => "__builtin_ia32_psrlv8hi_mask", + "avx512.mask.psrlv8.si" => "__builtin_ia32_psrlv8si_mask", + "avx512.mask.psub.b.128" => "__builtin_ia32_psubb128_mask", + "avx512.mask.psub.b.256" => "__builtin_ia32_psubb256_mask", + "avx512.mask.psub.b.512" => "__builtin_ia32_psubb512_mask", + "avx512.mask.psub.d.128" => "__builtin_ia32_psubd128_mask", + "avx512.mask.psub.d.256" => "__builtin_ia32_psubd256_mask", + "avx512.mask.psub.d.512" => "__builtin_ia32_psubd512_mask", + "avx512.mask.psub.q.128" => "__builtin_ia32_psubq128_mask", + "avx512.mask.psub.q.256" => "__builtin_ia32_psubq256_mask", + "avx512.mask.psub.q.512" => "__builtin_ia32_psubq512_mask", + "avx512.mask.psub.w.128" => "__builtin_ia32_psubw128_mask", + "avx512.mask.psub.w.256" => "__builtin_ia32_psubw256_mask", + "avx512.mask.psub.w.512" => "__builtin_ia32_psubw512_mask", + "avx512.mask.psubs.b.128" => "__builtin_ia32_psubsb128_mask", + "avx512.mask.psubs.b.256" => "__builtin_ia32_psubsb256_mask", + "avx512.mask.psubs.b.512" => "__builtin_ia32_psubsb512_mask", + "avx512.mask.psubs.w.128" => "__builtin_ia32_psubsw128_mask", + "avx512.mask.psubs.w.256" => "__builtin_ia32_psubsw256_mask", + "avx512.mask.psubs.w.512" => "__builtin_ia32_psubsw512_mask", + "avx512.mask.psubus.b.128" => "__builtin_ia32_psubusb128_mask", + "avx512.mask.psubus.b.256" => "__builtin_ia32_psubusb256_mask", + "avx512.mask.psubus.b.512" => "__builtin_ia32_psubusb512_mask", + "avx512.mask.psubus.w.128" => "__builtin_ia32_psubusw128_mask", + "avx512.mask.psubus.w.256" => "__builtin_ia32_psubusw256_mask", + "avx512.mask.psubus.w.512" => "__builtin_ia32_psubusw512_mask", + "avx512.mask.pternlog.d.128" => "__builtin_ia32_pternlogd128_mask", + "avx512.mask.pternlog.d.256" => "__builtin_ia32_pternlogd256_mask", + "avx512.mask.pternlog.d.512" => "__builtin_ia32_pternlogd512_mask", + "avx512.mask.pternlog.q.128" => "__builtin_ia32_pternlogq128_mask", + "avx512.mask.pternlog.q.256" => "__builtin_ia32_pternlogq256_mask", + "avx512.mask.pternlog.q.512" => "__builtin_ia32_pternlogq512_mask", + "avx512.mask.ptestm.d.512" => "__builtin_ia32_ptestmd512", + "avx512.mask.ptestm.q.512" => "__builtin_ia32_ptestmq512", + "avx512.mask.shuf.f32x4" => "__builtin_ia32_shuf_f32x4_mask", + "avx512.mask.shuf.f32x4.256" => "__builtin_ia32_shuf_f32x4_256_mask", + "avx512.mask.shuf.f64x2" => "__builtin_ia32_shuf_f64x2_mask", + "avx512.mask.shuf.f64x2.256" => "__builtin_ia32_shuf_f64x2_256_mask", + "avx512.mask.shuf.i32x4" => "__builtin_ia32_shuf_i32x4_mask", + "avx512.mask.shuf.i32x4.256" => "__builtin_ia32_shuf_i32x4_256_mask", + "avx512.mask.shuf.i64x2" => "__builtin_ia32_shuf_i64x2_mask", + "avx512.mask.shuf.i64x2.256" => "__builtin_ia32_shuf_i64x2_256_mask", + "avx512.mask.shuf.pd.128" => "__builtin_ia32_shufpd128_mask", + "avx512.mask.shuf.pd.256" => "__builtin_ia32_shufpd256_mask", + "avx512.mask.shuf.pd.512" => "__builtin_ia32_shufpd512_mask", + "avx512.mask.shuf.ps.128" => "__builtin_ia32_shufps128_mask", + "avx512.mask.shuf.ps.256" => "__builtin_ia32_shufps256_mask", + "avx512.mask.shuf.ps.512" => "__builtin_ia32_shufps512_mask", + "avx512.mask.sqrt.pd.128" => "__builtin_ia32_sqrtpd128_mask", + "avx512.mask.sqrt.pd.256" => "__builtin_ia32_sqrtpd256_mask", + "avx512.mask.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", + "avx512.mask.sqrt.ps.128" => "__builtin_ia32_sqrtps128_mask", + "avx512.mask.sqrt.ps.256" => "__builtin_ia32_sqrtps256_mask", + "avx512.mask.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", + "avx512.mask.store.ss" => "__builtin_ia32_storess_mask", + "avx512.mask.storeu.d.512" => "__builtin_ia32_storedqusi512_mask", + "avx512.mask.storeu.pd.512" => "__builtin_ia32_storeupd512_mask", + "avx512.mask.storeu.ps.512" => "__builtin_ia32_storeups512_mask", + "avx512.mask.storeu.q.512" => "__builtin_ia32_storedqudi512_mask", + "avx512.mask.sub.pd.128" => "__builtin_ia32_subpd128_mask", + "avx512.mask.sub.pd.256" => "__builtin_ia32_subpd256_mask", + "avx512.mask.sub.pd.512" => "__builtin_ia32_subpd512_mask", + "avx512.mask.sub.ps.128" => "__builtin_ia32_subps128_mask", + "avx512.mask.sub.ps.256" => "__builtin_ia32_subps256_mask", + "avx512.mask.sub.ps.512" => "__builtin_ia32_subps512_mask", + "avx512.mask.valign.d.128" => "__builtin_ia32_alignd128_mask", + "avx512.mask.valign.d.256" => "__builtin_ia32_alignd256_mask", + "avx512.mask.valign.d.512" => "__builtin_ia32_alignd512_mask", + "avx512.mask.valign.q.128" => "__builtin_ia32_alignq128_mask", + "avx512.mask.valign.q.256" => "__builtin_ia32_alignq256_mask", + "avx512.mask.valign.q.512" => "__builtin_ia32_alignq512_mask", + "avx512.mask.vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps_mask", + "avx512.mask.vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256_mask", + "avx512.mask.vcvtph2ps.512" => "__builtin_ia32_vcvtph2ps512_mask", + "avx512.mask.vextractf32x4.256" => "__builtin_ia32_extractf32x4_256_mask", + "avx512.mask.vextractf32x4.512" => "__builtin_ia32_extractf32x4_mask", + "avx512.mask.vextractf32x8.512" => "__builtin_ia32_extractf32x8_mask", + "avx512.mask.vextractf64x2.256" => "__builtin_ia32_extractf64x2_256_mask", + "avx512.mask.vextractf64x2.512" => "__builtin_ia32_extractf64x2_512_mask", + "avx512.mask.vextractf64x4.512" => "__builtin_ia32_extractf64x4_mask", + "avx512.mask.vextracti32x4.256" => "__builtin_ia32_extracti32x4_256_mask", + "avx512.mask.vextracti32x4.512" => "__builtin_ia32_extracti32x4_mask", + "avx512.mask.vextracti32x8.512" => "__builtin_ia32_extracti32x8_mask", + "avx512.mask.vextracti64x2.256" => "__builtin_ia32_extracti64x2_256_mask", + "avx512.mask.vextracti64x2.512" => "__builtin_ia32_extracti64x2_512_mask", + "avx512.mask.vextracti64x4.512" => "__builtin_ia32_extracti64x4_mask", + "avx512.mask.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask", + "avx512.mask.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask", + "avx512.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", + "avx512.mask.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask", + "avx512.mask.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask", + "avx512.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", + "avx512.mask.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask", + "avx512.mask.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask", + "avx512.mask.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask", + "avx512.mask.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask", + "avx512.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", + "avx512.mask.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask", + "avx512.mask.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask", + "avx512.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", + "avx512.mask.vfnmadd.pd.128" => "__builtin_ia32_vfnmaddpd128_mask", + "avx512.mask.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256_mask", + "avx512.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", + "avx512.mask.vfnmadd.ps.128" => "__builtin_ia32_vfnmaddps128_mask", + "avx512.mask.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256_mask", + "avx512.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", + "avx512.mask.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask", + "avx512.mask.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask", + "avx512.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", + "avx512.mask.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask", + "avx512.mask.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask", + "avx512.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", + "avx512.mask.vpermi2var.d.128" => "__builtin_ia32_vpermi2vard128_mask", + "avx512.mask.vpermi2var.d.256" => "__builtin_ia32_vpermi2vard256_mask", + "avx512.mask.vpermi2var.d.512" => "__builtin_ia32_vpermi2vard512_mask", + "avx512.mask.vpermi2var.hi.128" => "__builtin_ia32_vpermi2varhi128_mask", + "avx512.mask.vpermi2var.hi.256" => "__builtin_ia32_vpermi2varhi256_mask", + "avx512.mask.vpermi2var.hi.512" => "__builtin_ia32_vpermi2varhi512_mask", + "avx512.mask.vpermi2var.pd.128" => "__builtin_ia32_vpermi2varpd128_mask", + "avx512.mask.vpermi2var.pd.256" => "__builtin_ia32_vpermi2varpd256_mask", + "avx512.mask.vpermi2var.pd.512" => "__builtin_ia32_vpermi2varpd512_mask", + "avx512.mask.vpermi2var.ps.128" => "__builtin_ia32_vpermi2varps128_mask", + "avx512.mask.vpermi2var.ps.256" => "__builtin_ia32_vpermi2varps256_mask", + "avx512.mask.vpermi2var.ps.512" => "__builtin_ia32_vpermi2varps512_mask", + "avx512.mask.vpermi2var.q.128" => "__builtin_ia32_vpermi2varq128_mask", + "avx512.mask.vpermi2var.q.256" => "__builtin_ia32_vpermi2varq256_mask", + "avx512.mask.vpermi2var.q.512" => "__builtin_ia32_vpermi2varq512_mask", + "avx512.mask.vpermi2var.qi.128" => "__builtin_ia32_vpermi2varqi128_mask", + "avx512.mask.vpermi2var.qi.256" => "__builtin_ia32_vpermi2varqi256_mask", + "avx512.mask.vpermi2var.qi.512" => "__builtin_ia32_vpermi2varqi512_mask", + "avx512.mask.vpermilvar.pd.128" => "__builtin_ia32_vpermilvarpd_mask", + "avx512.mask.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256_mask", + "avx512.mask.vpermilvar.pd.512" => "__builtin_ia32_vpermilvarpd512_mask", + "avx512.mask.vpermilvar.ps.128" => "__builtin_ia32_vpermilvarps_mask", + "avx512.mask.vpermilvar.ps.256" => "__builtin_ia32_vpermilvarps256_mask", + "avx512.mask.vpermilvar.ps.512" => "__builtin_ia32_vpermilvarps512_mask", + "avx512.mask.vpermt.d.512" => "__builtin_ia32_vpermt2vard512_mask", + "avx512.mask.vpermt.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", + "avx512.mask.vpermt.ps.512" => "__builtin_ia32_vpermt2varps512_mask", + "avx512.mask.vpermt.q.512" => "__builtin_ia32_vpermt2varq512_mask", + "avx512.mask.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_mask", + "avx512.mask.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_mask", + "avx512.mask.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_mask", + "avx512.mask.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_mask", + "avx512.mask.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_mask", + "avx512.mask.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_mask", + "avx512.mask.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_mask", + "avx512.mask.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_mask", + "avx512.mask.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", + "avx512.mask.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_mask", + "avx512.mask.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_mask", + "avx512.mask.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_mask", + "avx512.mask.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_mask", + "avx512.mask.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_mask", + "avx512.mask.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_mask", + "avx512.mask.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_mask", + "avx512.mask.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_mask", + "avx512.mask.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_mask", + "avx512.mask.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_mask", + "avx512.mask.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_mask", + "avx512.mask.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_mask", + "avx512.mask.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_mask", + "avx512.mask.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_mask", + "avx512.mask.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_mask", + "avx512.mask.xor.pd.128" => "__builtin_ia32_xorpd128_mask", + "avx512.mask.xor.pd.256" => "__builtin_ia32_xorpd256_mask", + "avx512.mask.xor.pd.512" => "__builtin_ia32_xorpd512_mask", + "avx512.mask.xor.ps.128" => "__builtin_ia32_xorps128_mask", + "avx512.mask.xor.ps.256" => "__builtin_ia32_xorps256_mask", + "avx512.mask.xor.ps.512" => "__builtin_ia32_xorps512_mask", + "avx512.mask3.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask3", + "avx512.mask3.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask3", + "avx512.mask3.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask3", + "avx512.mask3.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask3", + "avx512.mask3.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask3", + "avx512.mask3.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask3", + "avx512.mask3.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask3", + "avx512.mask3.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask3", + "avx512.mask3.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask3", + "avx512.mask3.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask3", + "avx512.mask3.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask3", + "avx512.mask3.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask3", + "avx512.mask3.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask3", + "avx512.mask3.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask3", + "avx512.mask3.vfmsub.pd.128" => "__builtin_ia32_vfmsubpd128_mask3", + "avx512.mask3.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256_mask3", + "avx512.mask3.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask3", + "avx512.mask3.vfmsub.ps.128" => "__builtin_ia32_vfmsubps128_mask3", + "avx512.mask3.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256_mask3", + "avx512.mask3.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask3", + "avx512.mask3.vfmsubadd.pd.128" => "__builtin_ia32_vfmsubaddpd128_mask3", + "avx512.mask3.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256_mask3", + "avx512.mask3.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask3", + "avx512.mask3.vfmsubadd.ps.128" => "__builtin_ia32_vfmsubaddps128_mask3", + "avx512.mask3.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256_mask3", + "avx512.mask3.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask3", + "avx512.mask3.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask3", + "avx512.mask3.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask3", + "avx512.mask3.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask3", + "avx512.mask3.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask3", + "avx512.mask3.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask3", + "avx512.mask3.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask3", + "avx512.maskz.pternlog.d.128" => "__builtin_ia32_pternlogd128_maskz", + "avx512.maskz.pternlog.d.256" => "__builtin_ia32_pternlogd256_maskz", + "avx512.maskz.pternlog.d.512" => "__builtin_ia32_pternlogd512_maskz", + "avx512.maskz.pternlog.q.128" => "__builtin_ia32_pternlogq128_maskz", + "avx512.maskz.pternlog.q.256" => "__builtin_ia32_pternlogq256_maskz", + "avx512.maskz.pternlog.q.512" => "__builtin_ia32_pternlogq512_maskz", + "avx512.maskz.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_maskz", + "avx512.maskz.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_maskz", + "avx512.maskz.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_maskz", + "avx512.maskz.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_maskz", + "avx512.maskz.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_maskz", + "avx512.maskz.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_maskz", + "avx512.maskz.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_maskz", + "avx512.maskz.vfmadd.ss" => "__builtin_ia32_vfmaddss3_maskz", + "avx512.maskz.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_maskz", + "avx512.maskz.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_maskz", + "avx512.maskz.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_maskz", + "avx512.maskz.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_maskz", + "avx512.maskz.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_maskz", + "avx512.maskz.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_maskz", + "avx512.maskz.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_maskz", + "avx512.maskz.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_maskz", + "avx512.maskz.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_maskz", + "avx512.maskz.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_maskz", + "avx512.maskz.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_maskz", + "avx512.maskz.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_maskz", + "avx512.maskz.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_maskz", + "avx512.maskz.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_maskz", + "avx512.maskz.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_maskz", + "avx512.maskz.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_maskz", + "avx512.maskz.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_maskz", + "avx512.maskz.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_maskz", + "avx512.maskz.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_maskz", + "avx512.maskz.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_maskz", + "avx512.maskz.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_maskz", + "avx512.maskz.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_maskz", + "avx512.maskz.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_maskz", + "avx512.maskz.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_maskz", + "avx512.maskz.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_maskz", + "avx512.maskz.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_maskz", + "avx512.maskz.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_maskz", + "avx512.maskz.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_maskz", + "avx512.maskz.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_maskz", + "avx512.maskz.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_maskz", + "avx512.movntdqa" => "__builtin_ia32_movntdqa512", + "avx512.pbroadcastd.512" => "__builtin_ia32_pbroadcastd512", + "avx512.pbroadcastq.512" => "__builtin_ia32_pbroadcastq512", + "avx512.pmovzxbd" => "__builtin_ia32_pmovzxbd512", + "avx512.pmovzxbq" => "__builtin_ia32_pmovzxbq512", + "avx512.pmovzxdq" => "__builtin_ia32_pmovzxdq512", + "avx512.pmovzxwd" => "__builtin_ia32_pmovzxwd512", + "avx512.pmovzxwq" => "__builtin_ia32_pmovzxwq512", + "avx512.psll.dq" => "__builtin_ia32_pslldqi512", + "avx512.psll.dq.bs" => "__builtin_ia32_pslldqi512_byteshift", + "avx512.psrl.dq" => "__builtin_ia32_psrldqi512", + "avx512.psrl.dq.bs" => "__builtin_ia32_psrldqi512_byteshift", + "avx512.ptestm.b.128" => "__builtin_ia32_ptestmb128", + "avx512.ptestm.b.256" => "__builtin_ia32_ptestmb256", + "avx512.ptestm.b.512" => "__builtin_ia32_ptestmb512", + "avx512.ptestm.d.128" => "__builtin_ia32_ptestmd128", + "avx512.ptestm.d.256" => "__builtin_ia32_ptestmd256", + "avx512.ptestm.d.512" => "__builtin_ia32_ptestmd512", + "avx512.ptestm.q.128" => "__builtin_ia32_ptestmq128", + "avx512.ptestm.q.256" => "__builtin_ia32_ptestmq256", + "avx512.ptestm.q.512" => "__builtin_ia32_ptestmq512", + "avx512.ptestm.w.128" => "__builtin_ia32_ptestmw128", + "avx512.ptestm.w.256" => "__builtin_ia32_ptestmw256", + "avx512.ptestm.w.512" => "__builtin_ia32_ptestmw512", + "avx512.ptestnm.b.128" => "__builtin_ia32_ptestnmb128", + "avx512.ptestnm.b.256" => "__builtin_ia32_ptestnmb256", + "avx512.ptestnm.b.512" => "__builtin_ia32_ptestnmb512", + "avx512.ptestnm.d.128" => "__builtin_ia32_ptestnmd128", + "avx512.ptestnm.d.256" => "__builtin_ia32_ptestnmd256", + "avx512.ptestnm.d.512" => "__builtin_ia32_ptestnmd512", + "avx512.ptestnm.q.128" => "__builtin_ia32_ptestnmq128", + "avx512.ptestnm.q.256" => "__builtin_ia32_ptestnmq256", + "avx512.ptestnm.q.512" => "__builtin_ia32_ptestnmq512", + "avx512.ptestnm.w.128" => "__builtin_ia32_ptestnmw128", + "avx512.ptestnm.w.256" => "__builtin_ia32_ptestnmw256", + "avx512.ptestnm.w.512" => "__builtin_ia32_ptestnmw512", + "avx512.rcp28.pd" => "__builtin_ia32_rcp28pd_mask", + "avx512.rcp28.ps" => "__builtin_ia32_rcp28ps_mask", + "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", + "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", + "avx512.rndscale.sd" => "__builtin_ia32_rndscalesd", + "avx512.rndscale.ss" => "__builtin_ia32_rndscaless", + "avx512.rsqrt28.pd" => "__builtin_ia32_rsqrt28pd_mask", + "avx512.rsqrt28.ps" => "__builtin_ia32_rsqrt28ps_mask", + "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", + "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", + "avx512.scatter.dpd.512" => "__builtin_ia32_scattersiv8df", + "avx512.scatter.dpi.512" => "__builtin_ia32_scattersiv16si", + "avx512.scatter.dpq.512" => "__builtin_ia32_scattersiv8di", + "avx512.scatter.dps.512" => "__builtin_ia32_scattersiv16sf", + "avx512.scatter.qpd.512" => "__builtin_ia32_scatterdiv8df", + "avx512.scatter.qpi.512" => "__builtin_ia32_scatterdiv16si", + "avx512.scatter.qpq.512" => "__builtin_ia32_scatterdiv8di", + "avx512.scatter.qps.512" => "__builtin_ia32_scatterdiv16sf", + "avx512.scatterdiv2.df" => "__builtin_ia32_scatterdiv2df", + "avx512.scatterdiv2.di" => "__builtin_ia32_scatterdiv2di", + "avx512.scatterdiv4.df" => "__builtin_ia32_scatterdiv4df", + "avx512.scatterdiv4.di" => "__builtin_ia32_scatterdiv4di", + "avx512.scatterdiv4.sf" => "__builtin_ia32_scatterdiv4sf", + "avx512.scatterdiv4.si" => "__builtin_ia32_scatterdiv4si", + "avx512.scatterdiv8.sf" => "__builtin_ia32_scatterdiv8sf", + "avx512.scatterdiv8.si" => "__builtin_ia32_scatterdiv8si", + "avx512.scatterpf.dpd.512" => "__builtin_ia32_scatterpfdpd", + "avx512.scatterpf.dps.512" => "__builtin_ia32_scatterpfdps", + "avx512.scatterpf.qpd.512" => "__builtin_ia32_scatterpfqpd", + "avx512.scatterpf.qps.512" => "__builtin_ia32_scatterpfqps", + "avx512.scattersiv2.df" => "__builtin_ia32_scattersiv2df", + "avx512.scattersiv2.di" => "__builtin_ia32_scattersiv2di", + "avx512.scattersiv4.df" => "__builtin_ia32_scattersiv4df", + "avx512.scattersiv4.di" => "__builtin_ia32_scattersiv4di", + "avx512.scattersiv4.sf" => "__builtin_ia32_scattersiv4sf", + "avx512.scattersiv4.si" => "__builtin_ia32_scattersiv4si", + "avx512.scattersiv8.sf" => "__builtin_ia32_scattersiv8sf", + "avx512.scattersiv8.si" => "__builtin_ia32_scattersiv8si", + "avx512.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", + "avx512.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", + "avx512.sqrt.sd" => "__builtin_ia32_sqrtrndsd", + "avx512.sqrt.ss" => "__builtin_ia32_sqrtrndss", + "avx512.vbroadcast.sd.512" => "__builtin_ia32_vbroadcastsd512", + "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", + "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", + "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", + "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", + "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", + "fma.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", + "fma.mask.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask", + "fma.mask.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask", + "fma.mask.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask", + "fma.mask.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask", + "fma.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", + "fma.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", + "fma.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", + "fma.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", + "fma.vfmadd.pd" => "__builtin_ia32_vfmaddpd", + "fma.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256", + "fma.vfmadd.ps" => "__builtin_ia32_vfmaddps", + "fma.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256", + "fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd", + "fma.vfmadd.ss" => "__builtin_ia32_vfmaddss", + "fma.vfmsub.pd" => "__builtin_ia32_vfmsubpd", + "fma.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256", + "fma.vfmsub.ps" => "__builtin_ia32_vfmsubps", + "fma.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256", + "fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd", + "fma.vfmsub.ss" => "__builtin_ia32_vfmsubss", + "fma.vfmsubadd.pd" => "__builtin_ia32_vfmsubaddpd", + "fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256", + "fma.vfmsubadd.ps" => "__builtin_ia32_vfmsubaddps", + "fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256", + "fma.vfnmadd.pd" => "__builtin_ia32_vfnmaddpd", + "fma.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256", + "fma.vfnmadd.ps" => "__builtin_ia32_vfnmaddps", + "fma.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256", + "fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd", + "fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss", + "fma.vfnmsub.pd" => "__builtin_ia32_vfnmsubpd", + "fma.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256", + "fma.vfnmsub.ps" => "__builtin_ia32_vfnmsubps", + "fma.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256", + "fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd", + "fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss", + "mmx.femms" => "__builtin_ia32_femms", + "rdtscp" => "__builtin_ia32_rdtscp", + "sse.add.ss" => "__builtin_ia32_addss", + "sse.cmp.ps" => "__builtin_ia32_cmpps", + "sse.cvtsi2ss" => "__builtin_ia32_cvtsi2ss", + "sse.cvtsi642ss" => "__builtin_ia32_cvtsi642ss", + "sse.div.ss" => "__builtin_ia32_divss", + "sse.mul.ss" => "__builtin_ia32_mulss", + "sse.sqrt.ps" => "__builtin_ia32_sqrtps", + "sse.sqrt.ss" => "__builtin_ia32_sqrtss", + "sse.storeu.ps" => "__builtin_ia32_storeups", + "sse.sub.ss" => "__builtin_ia32_subss", + "sse2.add.sd" => "__builtin_ia32_addsd", + "sse2.cmp.pd" => "__builtin_ia32_cmppd", + "sse2.cvtdq2pd" => "__builtin_ia32_cvtdq2pd", + "sse2.cvtdq2ps" => "__builtin_ia32_cvtdq2ps", + "sse2.cvtps2pd" => "__builtin_ia32_cvtps2pd", + "sse2.cvtsi2sd" => "__builtin_ia32_cvtsi2sd", + "sse2.cvtsi642sd" => "__builtin_ia32_cvtsi642sd", + "sse2.cvtss2sd" => "__builtin_ia32_cvtss2sd", + "sse2.div.sd" => "__builtin_ia32_divsd", + "sse2.mul.sd" => "__builtin_ia32_mulsd", + "sse2.padds.b" => "__builtin_ia32_paddsb128", + "sse2.padds.w" => "__builtin_ia32_paddsw128", + "sse2.paddus.b" => "__builtin_ia32_paddusb128", + "sse2.paddus.w" => "__builtin_ia32_paddusw128", + "sse2.pmaxs.w" => "__builtin_ia32_pmaxsw128", + "sse2.pmaxu.b" => "__builtin_ia32_pmaxub128", + "sse2.pmins.w" => "__builtin_ia32_pminsw128", + "sse2.pminu.b" => "__builtin_ia32_pminub128", + "sse2.pmulu.dq" => "__builtin_ia32_pmuludq128", + "sse2.pshuf.d" => "__builtin_ia32_pshufd", + "sse2.pshufh.w" => "__builtin_ia32_pshufhw", + "sse2.pshufl.w" => "__builtin_ia32_pshuflw", + "sse2.psll.dq" => "__builtin_ia32_pslldqi128", + "sse2.psll.dq.bs" => "__builtin_ia32_pslldqi128_byteshift", + "sse2.psrl.dq" => "__builtin_ia32_psrldqi128", + "sse2.psrl.dq.bs" => "__builtin_ia32_psrldqi128_byteshift", + "sse2.psubs.b" => "__builtin_ia32_psubsb128", + "sse2.psubs.w" => "__builtin_ia32_psubsw128", + "sse2.psubus.b" => "__builtin_ia32_psubusb128", + "sse2.psubus.w" => "__builtin_ia32_psubusw128", + "sse2.sqrt.pd" => "__builtin_ia32_sqrtpd", + "sse2.sqrt.sd" => "__builtin_ia32_sqrtsd", + "sse2.storel.dq" => "__builtin_ia32_storelv4si", + "sse2.storeu.dq" => "__builtin_ia32_storedqu", + "sse2.storeu.pd" => "__builtin_ia32_storeupd", + "sse2.sub.sd" => "__builtin_ia32_subsd", + "sse41.blendpd" => "__builtin_ia32_blendpd", + "sse41.blendps" => "__builtin_ia32_blendps", + "sse41.extractps" => "__builtin_ia32_extractps128", + "sse41.movntdqa" => "__builtin_ia32_movntdqa", + "sse41.pblendw" => "__builtin_ia32_pblendw128", + "sse41.pmaxsb" => "__builtin_ia32_pmaxsb128", + "sse41.pmaxsd" => "__builtin_ia32_pmaxsd128", + "sse41.pmaxud" => "__builtin_ia32_pmaxud128", + "sse41.pmaxuw" => "__builtin_ia32_pmaxuw128", + "sse41.pminsb" => "__builtin_ia32_pminsb128", + "sse41.pminsd" => "__builtin_ia32_pminsd128", + "sse41.pminud" => "__builtin_ia32_pminud128", + "sse41.pminuw" => "__builtin_ia32_pminuw128", + "sse41.pmovsxbd" => "__builtin_ia32_pmovsxbd128", + "sse41.pmovsxbq" => "__builtin_ia32_pmovsxbq128", + "sse41.pmovsxbw" => "__builtin_ia32_pmovsxbw128", + "sse41.pmovsxdq" => "__builtin_ia32_pmovsxdq128", + "sse41.pmovsxwd" => "__builtin_ia32_pmovsxwd128", + "sse41.pmovsxwq" => "__builtin_ia32_pmovsxwq128", + "sse41.pmovzxbd" => "__builtin_ia32_pmovzxbd128", + "sse41.pmovzxbq" => "__builtin_ia32_pmovzxbq128", + "sse41.pmovzxbw" => "__builtin_ia32_pmovzxbw128", + "sse41.pmovzxdq" => "__builtin_ia32_pmovzxdq128", + "sse41.pmovzxwd" => "__builtin_ia32_pmovzxwd128", + "sse41.pmovzxwq" => "__builtin_ia32_pmovzxwq128", + "sse41.pmuldq" => "__builtin_ia32_pmuldq128", + "sse41.round.pd" => "__builtin_ia32_roundpd", + "sse41.round.ps" => "__builtin_ia32_roundps", + "sse41.round.sd" => "__builtin_ia32_roundsd", + "sse41.round.ss" => "__builtin_ia32_roundss", + "sse4a.movnt.sd" => "__builtin_ia32_movntsd", + "sse4a.movnt.ss" => "__builtin_ia32_movntss", + "ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", + "ssse3.pabs.d.128" => "__builtin_ia32_pabsd128", + "ssse3.pabs.w.128" => "__builtin_ia32_pabsw128", + "subborrow.u32" => "__builtin_ia32_subborrow_u32", + "subborrow.u64" => "__builtin_ia32_subborrow_u64", + "xop.vpcmov" => "__builtin_ia32_vpcmov", + "xop.vpcmov.256" => "__builtin_ia32_vpcmov_256", + "xop.vpcomb" => "__builtin_ia32_vpcomb", + "xop.vpcomd" => "__builtin_ia32_vpcomd", + "xop.vpcomq" => "__builtin_ia32_vpcomq", + "xop.vpcomub" => "__builtin_ia32_vpcomub", + "xop.vpcomud" => "__builtin_ia32_vpcomud", + "xop.vpcomuq" => "__builtin_ia32_vpcomuq", + "xop.vpcomuw" => "__builtin_ia32_vpcomuw", + "xop.vpcomw" => "__builtin_ia32_vpcomw", + "xop.vprotb" => "__builtin_ia32_vprotb", + "xop.vprotbi" => "__builtin_ia32_vprotbi", + "xop.vprotd" => "__builtin_ia32_vprotd", + "xop.vprotdi" => "__builtin_ia32_vprotdi", + "xop.vprotq" => "__builtin_ia32_vprotq", + "xop.vprotqi" => "__builtin_ia32_vprotqi", + "xop.vprotw" => "__builtin_ia32_vprotw", + "xop.vprotwi" => "__builtin_ia32_vprotwi", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + _ => return ArchCheckResult::UnknownArch, + }) +} diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 00bea0222622..5d03d2406870 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,7 +27,6 @@ extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; -extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_index; @@ -77,7 +76,6 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -use back::lto::{ThinBuffer, ThinData}; use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] use gccjit::{TargetInfo, Version}; @@ -88,9 +86,12 @@ use rustc_codegen_ssa::back::write::{ }; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; -use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; +use rustc_codegen_ssa::traits::{ + CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods, +}; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::DiagCtxtHandle; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -105,8 +106,6 @@ use tempfile::TempDir; use crate::back::lto::ModuleBuffer; use crate::gcc_util::{target_cpu, to_gcc_features}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct PrintOnPanic String>(pub F); impl String> Drop for PrintOnPanic { @@ -179,8 +178,6 @@ pub struct GccCodegenBackend { lto_supported: Arc, } -static LTO_SUPPORTED: AtomicBool = AtomicBool::new(false); - fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) { if gccjit::is_loaded() { // Do not load a libgccjit second time. @@ -197,10 +194,6 @@ fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) { } impl CodegenBackend for GccCodegenBackend { - fn locale_resource(&self) -> &'static str { - crate::DEFAULT_LOCALE_RESOURCE - } - fn name(&self) -> &'static str { "gcc" } @@ -240,6 +233,8 @@ impl CodegenBackend for GccCodegenBackend { #[cfg(feature = "master")] { + gccjit::set_lang_name(c"GNU Rust"); + let target_cpu = target_cpu(sess); // Get the second TargetInfo with the correct CPU features by setting the arch. @@ -255,7 +250,6 @@ impl CodegenBackend for GccCodegenBackend { #[cfg(feature = "master")] { let lto_supported = gccjit::is_lto_supported(); - LTO_SUPPORTED.store(lto_supported, Ordering::SeqCst); self.lto_supported.store(lto_supported, Ordering::SeqCst); gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); @@ -285,6 +279,10 @@ impl CodegenBackend for GccCodegenBackend { } } + fn thin_lto_supported(&self) -> bool { + false + } + fn provide(&self, providers: &mut Providers) { providers.queries.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess) @@ -381,7 +379,7 @@ impl ExtraBackendMethods for GccCodegenBackend { _features: &[String], ) -> TargetMachineFactoryFn { // TODO(antoyo): set opt level. - Arc::new(|_| Ok(())) + Arc::new(|_, _| ()) } } @@ -425,35 +423,45 @@ unsafe impl Send for SyncContext {} // FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()". unsafe impl Sync for SyncContext {} +pub struct ThinBuffer; + +impl ThinBufferMethods for ThinBuffer { + fn data(&self) -> &[u8] { + &[] + } +} + impl WriteBackendMethods for GccCodegenBackend { type Module = GccContext; type TargetMachine = (); - type TargetMachineError = (); type ModuleBuffer = ModuleBuffer; - type ThinData = ThinData; + type ThinData = (); type ThinBuffer = ThinBuffer; fn run_and_optimize_fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + _tm_factory: TargetMachineFactoryFn, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - back::lto::run_fat(cgcx, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, prof, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( - cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, + _cgcx: &CodegenContext, + _prof: &SelfProfilerRef, + _dcx: DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], - each_linked_rlib_for_lto: &[PathBuf], - modules: Vec<(String, Self::ThinBuffer)>, - cached_modules: Vec<(SerializedModule, WorkProduct)>, + _each_linked_rlib_for_lto: &[PathBuf], + _modules: Vec<(String, Self::ThinBuffer)>, + _cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - back::lto::run_thin(cgcx, dcx, each_linked_rlib_for_lto, modules, cached_modules) + unreachable!() } fn print_pass_timings(&self) { @@ -465,7 +473,8 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize( - _cgcx: &CodegenContext, + _cgcx: &CodegenContext, + _prof: &SelfProfilerRef, _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, @@ -474,24 +483,27 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize_thin( - cgcx: &CodegenContext, + _cgcx: &CodegenContext, + _prof: &SelfProfilerRef, _shared_emitter: &SharedEmitter, - thin: ThinModule, + _tm_factory: TargetMachineFactoryFn, + _thin: ThinModule, ) -> ModuleCodegen { - back::lto::optimize_thin_module(thin, cgcx) + unreachable!() } fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, shared_emitter, module, config) + back::write::codegen(cgcx, prof, shared_emitter, module, config) } - fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { - back::lto::prepare_thin(module) + fn prepare_thin(_module: ModuleCodegen) -> (String, Self::ThinBuffer) { + unreachable!() } fn serialize_module(_module: ModuleCodegen) -> (String, Self::ModuleBuffer) { diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index d356b6af260a..3b1ee53f8336 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, ty}; use crate::common::TypeReflection; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, new_array_type}; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -311,7 +311,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { len = 0; } - self.context.new_array_type(None, ty, len) + new_array_type(self.context, None, ty, len) } } diff --git a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt index 822aaec0edeb..528ee1df9f58 100644 --- a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt +++ b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt @@ -11,4 +11,4 @@ tests/run-make/foreign-exceptions/ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ - +tests/run-make/short-ice diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests-without-128bit-integers.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests-without-128bit-integers.txt new file mode 100644 index 000000000000..1dc3859b335e --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests-without-128bit-integers.txt @@ -0,0 +1 @@ +tests/ui/simd/intrinsic/splat.rs diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt index 99a80fa7e4f4..8589929d2fbc 100644 --- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt +++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt @@ -89,11 +89,13 @@ tests/ui/thir-print/offset_of.rs tests/ui/iterators/rangefrom-overflow-debug.rs tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs -tests/ui/eii/codegen_single_crate.rs -tests/ui/eii/codegen_cross_crate.rs +tests/ui/eii/linking/codegen_single_crate.rs +tests/ui/eii/linking/codegen_cross_crate.rs tests/ui/eii/default/local_crate.rs -tests/ui/eii/multiple_impls.rs +tests/ui/eii/duplicate/multiple_impls.rs tests/ui/eii/default/call_default.rs -tests/ui/eii/same-symbol.rs +tests/ui/eii/linking/same-symbol.rs tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs +tests/ui/c-variadic/copy.rs +tests/ui/asm/x86_64/global_asm_escape.rs diff --git a/compiler/rustc_codegen_gcc/tests/run/call-llvm-intrinsics.rs b/compiler/rustc_codegen_gcc/tests/run/call-llvm-intrinsics.rs new file mode 100644 index 000000000000..86e041c3a2fb --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/call-llvm-intrinsics.rs @@ -0,0 +1,38 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// FIXME: Remove this test once rustc's `./tests/codegen/riscv-abi/call-llvm-intrinsics.rs` +// stops ignoring GCC backend. + +#![feature(link_llvm_intrinsics)] +#![allow(internal_features)] + +struct A; + +impl Drop for A { + fn drop(&mut self) { + println!("A"); + } +} + +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +} + +pub fn do_call() { + let _a = A; + + unsafe { + // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them + // CHECK: store float 4.000000e+00, float* %{{.}}, align 4 + // CHECK: call float @llvm.sqrt.f32(float %{{.}} + sqrt(4.0); + } +} + +fn main() { + do_call(); +} diff --git a/compiler/rustc_codegen_gcc/tests/run/simd-ffi.rs b/compiler/rustc_codegen_gcc/tests/run/simd-ffi.rs new file mode 100644 index 000000000000..67cc2e5b96e3 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/simd-ffi.rs @@ -0,0 +1,102 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// FIXME: Remove this test once stops +// ignoring GCC backend. + +#![allow(internal_features, non_camel_case_types)] +// we can compile to a variety of platforms, because we don't need +// cross-compiled standard libraries. +#![feature(no_core, auto_traits)] +#![no_core] +#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)] + +#[derive(Copy)] +#[repr(simd)] +pub struct f32x4([f32; 4]); + +extern "C" { + #[link_name = "llvm.sqrt.v4f32"] + fn vsqrt(x: f32x4) -> f32x4; +} + +pub fn foo(x: f32x4) -> f32x4 { + unsafe { vsqrt(x) } +} + +#[derive(Copy)] +#[repr(simd)] +pub struct i32x4([i32; 4]); + +extern "C" { + // _mm_sll_epi32 + #[cfg(all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"))] + #[link_name = "llvm.x86.sse2.psll.d"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // vmaxq_s32 + #[cfg(target_arch = "arm")] + #[link_name = "llvm.arm.neon.vmaxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + // vmaxq_s32 + #[cfg(target_arch = "aarch64")] + #[link_name = "llvm.aarch64.neon.maxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // Use a generic LLVM intrinsic to do type checking on other platforms + #[cfg(not(any( + all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"), + target_arch = "arm", + target_arch = "aarch64" + )))] + #[link_name = "llvm.smax.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; +} + +pub fn bar(a: i32x4, b: i32x4) -> i32x4 { + unsafe { integer(a, b) } +} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "copy"] +pub trait Copy {} + +impl Copy for f32 {} +impl Copy for i32 {} +impl Copy for [f32; 4] {} +impl Copy for [i32; 4] {} + +pub mod marker { + pub use Copy; +} + +#[lang = "freeze"] +auto trait Freeze {} + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! Copy { + () => {}; +} +#[macro_export] +#[rustc_builtin_macro] +macro_rules! derive { + () => {}; +} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() {} diff --git a/compiler/rustc_codegen_gcc/tests/run/unreachable-function.rs b/compiler/rustc_codegen_gcc/tests/run/unreachable-function.rs new file mode 100644 index 000000000000..0a975487dd78 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/unreachable-function.rs @@ -0,0 +1,27 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::arch::asm; + +fn exit_syscall(status: i32) -> ! { + #[cfg(target_arch = "x86_64")] + unsafe { + asm!( + "syscall", + in("rax") 60, + in("rdi") status, + options(noreturn) + ); + } + + #[cfg(not(target_arch = "x86_64"))] + std::process::exit(status); +} + +fn main() { + // Used to crash with rustc_codegen_gcc. + exit_syscall(0); + std::process::exit(1); +} diff --git a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py index 767082c23cce..539032340777 100644 --- a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py +++ b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py @@ -12,7 +12,7 @@ def run_command(command, cwd=None): sys.exit(1) -def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None): +def clone_repository(repo_name, path, repo_url, sub_paths): if os.path.exists(path): while True: choice = input("There is already a `{}` folder, do you want to update it? [y/N]".format(path)) @@ -21,18 +21,15 @@ def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None) return elif choice.lower() == "y": print("Updating repository...") - run_command(["git", "pull", "origin", branch], cwd=path) + run_command(["git", "pull", "origin", "main"], cwd=path) return else: print("Didn't understand answer...") print("Cloning {} repository...".format(repo_name)) - if sub_paths is None: - run_command(["git", "clone", repo_url, "--depth", "1", path]) - else: - run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path]) - run_command(["git", "sparse-checkout", "init"], cwd=path) - run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path) - run_command(["git", "checkout"], cwd=path) + run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path]) + run_command(["git", "sparse-checkout", "init"], cwd=path) + run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path) + run_command(["git", "checkout"], cwd=path) def append_intrinsic(array, intrinsic_name, translation): @@ -45,121 +42,36 @@ def convert_to_string(content): return content -def extract_intrinsics_from_llvm(llvm_path, intrinsics): - command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"] +def extract_intrinsics_from_llvm(llvm_path): + intrinsics = {} + command = ["llvm-tblgen", "llvm/IR/Intrinsics.td", "--dump-json"] cwd = os.path.join(llvm_path, "llvm/include") print("=> Running command `{}` from `{}`".format(command, cwd)) p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE) output, err = p.communicate() - lines = convert_to_string(output).splitlines() - pos = 0 - while pos < len(lines): - line = lines[pos] - if not line.startswith("def "): - pos += 1 + content = json.loads(convert_to_string(output)) + for intrinsic in content: + data = content[intrinsic] + if not isinstance(data, dict): continue - intrinsic = line.split(" ")[1].strip() - content = line - while pos < len(lines): - line = lines[pos].split(" // ")[0].strip() - content += line - pos += 1 - if line == "}": - break - entries = re.findall('string ClangBuiltinName = "(\\w+)";', content) - current_arch = re.findall('string TargetPrefix = "(\\w+)";', content) - if len(entries) == 1 and len(current_arch) == 1: - current_arch = current_arch[0] - intrinsic = intrinsic.split("_") - if len(intrinsic) < 2 or intrinsic[0] != "int": - continue - intrinsic[0] = "llvm" - intrinsic = ".".join(intrinsic) - if current_arch not in intrinsics: - intrinsics[current_arch] = [] - append_intrinsic(intrinsics[current_arch], intrinsic, entries[0]) - - -def append_translation(json_data, p, array): - it = json_data["index"][p] - content = it["docs"].split('`') - if len(content) != 5: - return - append_intrinsic(array, content[1], content[3]) - - -def extract_intrinsics_from_llvmint(llvmint, intrinsics): - archs = [ - "AMDGPU", - "aarch64", - "arm", - "cuda", - "hexagon", - "mips", - "nvvm", - "ppc", - "ptx", - "x86", - "xcore", - ] - - json_file = os.path.join(llvmint, "target/doc/llvmint.json") - # We need to regenerate the documentation! - run_command( - ["cargo", "rustdoc", "--", "-Zunstable-options", "--output-format", "json"], - cwd=llvmint, - ) - with open(json_file, "r", encoding="utf8") as f: - json_data = json.loads(f.read()) - for p in json_data["paths"]: - it = json_data["paths"][p] - if it["crate_id"] != 0: - # This is from an external crate. + current_arch = data.get("TargetPrefix") + builtin_name = data.get("ClangBuiltinName") + if current_arch is None or current_arch == "" or builtin_name is None: continue - if it["kind"] != "function": - # We're only looking for functions. + intrinsic = intrinsic.split("_") + if len(intrinsic) < 2 or intrinsic[0] != "int": continue - # if len(it["path"]) == 2: - # # This is a "general" intrinsic, not bound to a specific arch. - # append_translation(json_data, p, general) - # continue - if len(it["path"]) != 3 or it["path"][1] not in archs: - continue - arch = it["path"][1] - if arch not in intrinsics: - intrinsics[arch] = [] - append_translation(json_data, p, intrinsics[arch]) + intrinsic[0] = "llvm" + intrinsic = ".".join(intrinsic) + if current_arch not in intrinsics: + intrinsics[current_arch] = [] + append_intrinsic(intrinsics[current_arch], intrinsic, builtin_name) + + return intrinsics -def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics): - for arch in from_intrinsics: - if arch not in intrinsics: - intrinsics[arch] = [] - for entry in from_intrinsics[arch]: - if entry[0] in all_intrinsics: - if all_intrinsics[entry[0]] == entry[1]: - # This is a "full" duplicate, both the LLVM instruction and the GCC - # translation are the same. - continue - intrinsics[arch].append((entry[0], entry[1], True)) - else: - intrinsics[arch].append((entry[0], entry[1], False)) - all_intrinsics[entry[0]] = entry[1] - - -def update_intrinsics(llvm_path, llvmint, llvmint2): - intrinsics_llvm = {} - intrinsics_llvmint = {} - all_intrinsics = {} - - extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm) - extract_intrinsics_from_llvmint(llvmint, intrinsics_llvmint) - extract_intrinsics_from_llvmint(llvmint2, intrinsics_llvmint) - - intrinsics = {} - # We give priority to translations from LLVM over the ones from llvmint. - fill_intrinsics(intrinsics, intrinsics_llvm, all_intrinsics) - fill_intrinsics(intrinsics, intrinsics_llvmint, all_intrinsics) +def update_intrinsics(llvm_path): + intrinsics = extract_intrinsics_from_llvm(llvm_path) archs = [arch for arch in intrinsics] archs.sort() @@ -173,33 +85,41 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) with open(output_file, "w", encoding="utf8") as out: - out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n") - out.write("// DO NOT EDIT IT!\n") - out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n") - out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n") - out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n') - out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n') - out.write("match arch {\n") + out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` +// DO NOT EDIT IT! +/// Translate a given LLVM intrinsic name to an equivalent GCC one. +fn map_arch_intrinsic(full_name:&str)-> &'static str { + let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) }; + let Some((arch, name)) = name.split_once('.') else { unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) }; + let old_arch_res = old_archs(arch, name); + if let ArchCheckResult::Ok(res) = old_arch_res { + return res; + } +match arch {""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) - intrinsics[arch].sort(key=lambda x: (x[0], x[2])) + intrinsics[arch].sort(key=lambda x: (x[0], x[1])) out.write(' // {}\n'.format(arch)) for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); - if entry[2] is True: # if it is a duplicate - out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(llvm_name, entry[1])) - elif "_round_mask" in entry[1]: + if "_round_mask" in entry[1]: out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) else: out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(' _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n') + out.write(""" _ => { + match old_arch_res { + ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), + ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), + ArchCheckResult::Ok(_) => unreachable!(), + } + }""") out.write("}\n}") subprocess.call(["rustfmt", output_file]) print("Done!") @@ -210,35 +130,21 @@ def main(): os.path.dirname(os.path.abspath(__file__)), "llvm-project", ) - llvmint_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "llvmint", - ) - llvmint2_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "llvmint-2", - ) # First, we clone the LLVM repository if it's not already here. clone_repository( "llvm-project", llvm_path, "https://github.com/llvm/llvm-project", - branch="main", - sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"], + ["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"], ) - clone_repository( - "llvmint", - llvmint_path, - "https://github.com/GuillaumeGomez/llvmint", - ) - clone_repository( - "llvmint2", - llvmint2_path, - "https://github.com/antoyo/llvmint", - ) - update_intrinsics(llvm_path, llvmint_path, llvmint2_path) + update_intrinsics(llvm_path) +# llvm-tblgen can be built with: +# +# mkdir llvm-tblgen-build && cd llvm-tblgen-build +# cmake -G Ninja -DLLVM_ENABLE_PROJECTS="llvm" -DCMAKE_BUILD_TYPE=Release ../llvm +# ninja llvm-tblgen if __name__ == "__main__": sys.exit(main()) diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 9741436aacb7..90c87494c3c5 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -23,7 +23,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl deleted file mode 100644 index 85cb7499cca4..000000000000 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ /dev/null @@ -1,75 +0,0 @@ -codegen_llvm_autodiff_component_missing = autodiff backend not found in the sysroot: {$err} - .note = it will be distributed via rustup in the future - -codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend: {$err} - -codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable -codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml - -codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err} - -codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture - -codegen_llvm_from_llvm_diag = {$message} - -codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} - -codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" -codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} - -codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$err}) - -codegen_llvm_mismatch_data_layout = - data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}` - -codegen_llvm_offload_bundleimages_failed = call to BundleImages failed, `host.out` was not created -codegen_llvm_offload_embed_failed = call to EmbedBufferInModule failed, `host.o` was not created -codegen_llvm_offload_no_abs_path = using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path -codegen_llvm_offload_no_host_out = using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file -codegen_llvm_offload_nonexisting = the given path/file to `host.out` does not exist. Did you forget to run the device compilation first? -codegen_llvm_offload_without_enable = using the offload feature requires -Z offload= -codegen_llvm_offload_without_fat_lto = using the offload feature requires -C lto=fat - -codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module -codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err} - -codegen_llvm_parse_target_machine_config = - failed to parse target machine config to target machine: {$error} - -codegen_llvm_prepare_autodiff = failed to prepare autodiff: src: {$src}, target: {$target}, {$error} -codegen_llvm_prepare_autodiff_with_llvm_err = failed to prepare autodiff: {$llvm_err}, src: {$src}, target: {$target}, {$error} -codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context -codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err} - -codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module -codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err} - -codegen_llvm_run_passes = failed to run LLVM passes -codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err} - -codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0 = `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. - -codegen_llvm_sanitizer_memtag_requires_mte = - `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` - -codegen_llvm_serialize_module = failed to serialize module {$name} -codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err} - -codegen_llvm_symbol_already_defined = - symbol `{$symbol_name}` is already defined - -codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple} -codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} - -codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo - -codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} - -codegen_llvm_write_ir = failed to write LLVM IR to {$path} -codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err} - -codegen_llvm_write_output = could not write output to {$path} -codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err} - -codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err} -codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 7f02518d6c0d..80d77be1cc38 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -399,7 +399,8 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { for piece in template { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { + use rustc_codegen_ssa::back::symbol_export::escape_symbol_name; match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { // Const operands get injected directly into the @@ -414,7 +415,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self.tcx, &symbol, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { let llval = self @@ -428,7 +429,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self.tcx, &symbol, span)); } } } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f5eb9c10db99..b5ab26aea492 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -301,17 +301,6 @@ fn stackprotector_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll A Some(sspattr.create_attr(cx.llcx)) } -fn backchain_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> { - if sess.target.arch != Arch::S390x { - return None; - } - - let requested_features = sess.opts.cg.target_feature.split(','); - let found_positive = requested_features.clone().any(|r| r == "+backchain"); - - if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None } -} - pub(crate) fn target_cpu_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> &'ll Attribute { let target_cpu = llvm_util::target_cpu(sess); llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) @@ -530,9 +519,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align); } - if let Some(backchain) = backchain_attr(cx, sess) { - to_add.push(backchain); - } to_add.extend(patchable_function_entry_attrs( cx, sess, diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 71327ed6d2d1..5d272d10930b 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -9,11 +9,14 @@ use std::{io, iter, slice}; use object::read::archive::ArchiveFile; use object::{Object, ObjectSection}; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; +use rustc_codegen_ssa::back::write::{ + CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn, +}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_hir::attrs::SanitizerSet; use rustc_middle::bug; @@ -33,7 +36,7 @@ use crate::{LlvmCodegenBackend, ModuleLlvm}; const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; fn prepare_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>, @@ -123,7 +126,7 @@ fn prepare_lto( fn get_bitcode_slice_from_object_data<'a>( obj: &'a [u8], - cgcx: &CodegenContext, + cgcx: &CodegenContext, ) -> Result<&'a [u8], LtoBitcodeFromRlib> { // We're about to assume the data here is an object file with sections, but if it's raw LLVM IR // that won't work. Fortunately, if that's what we have we can just return the object directly, @@ -149,8 +152,10 @@ fn get_bitcode_slice_from_object_data<'a>( /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -161,14 +166,24 @@ pub(crate) fn run_fat( prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx); let symbols_below_threshold = symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>(); - fat_lto(cgcx, dcx, shared_emitter, modules, upstream_modules, &symbols_below_threshold) + fat_lto( + cgcx, + prof, + dcx, + shared_emitter, + tm_factory, + modules, + upstream_modules, + &symbols_below_threshold, + ) } /// Performs thin LTO by performing necessary global analysis and returning two /// lists, one of the modules that need optimization and another for modules that /// can simply be copied over from the incr. comp. cache. pub(crate) fn run_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], @@ -185,7 +200,7 @@ pub(crate) fn run_thin( is deferred to the linker" ); } - thin_lto(cgcx, dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold) + thin_lto(cgcx, prof, dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold) } pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBuffer) { @@ -195,14 +210,16 @@ pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBu } fn fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, symbols_below_threshold: &[*const libc::c_char], ) -> ModuleCodegen { - let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module"); + let _timer = prof.generic_activity("LLVM_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -252,7 +269,7 @@ fn fat_lto( assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); let (buffer, name) = serialized_modules.remove(0); info!("no in-memory regular modules to choose from, parsing {:?}", name); - let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx); + let llvm_module = ModuleLlvm::parse(cgcx, tm_factory, &name, buffer.data(), dcx); ModuleCodegen::new_regular(name.into_string().unwrap(), llvm_module) } }; @@ -291,8 +308,7 @@ fn fat_lto( // above, this is all mostly handled in C++. let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg_recorder("LLVM_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{name:?}")) }); @@ -381,14 +397,15 @@ impl Drop for Linker<'_> { /// all of the `LtoModuleCodegen` units returned below and destroyed once /// they all go out of scope. fn thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec<(String, ThinBuffer)>, serialized_modules: Vec<(SerializedModule, CString)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, symbols_below_threshold: &[*const libc::c_char], ) -> (Vec>, Vec) { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis"); + let _timer = prof.generic_activity("LLVM_thin_lto_global_analysis"); unsafe { info!("going for that thin, thin LTO"); @@ -585,12 +602,13 @@ pub(crate) fn enable_autodiff_settings(ad: &[config::AutoDiff]) { } pub(crate) fn run_pass_manager( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, module: &mut ModuleCodegen, thin: bool, ) { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_lto_optimize", &*module.name); + let _timer = prof.generic_activity_with_arg("LLVM_lto_optimize", &*module.name); let config = &cgcx.module_config; // Now we have one massive module inside of llmod. Time to run the @@ -616,7 +634,7 @@ pub(crate) fn run_pass_manager( }; unsafe { - write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage); + write::llvm_optimize(cgcx, prof, dcx, module, None, config, opt_level, opt_stage, stage); } if cfg!(feature = "llvm_enzyme") && enable_ad && !thin { @@ -624,7 +642,9 @@ pub(crate) fn run_pass_manager( let stage = write::AutodiffStage::PostAD; if !config.autodiff.contains(&config::AutoDiff::NoPostopt) { unsafe { - write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage); + write::llvm_optimize( + cgcx, prof, dcx, module, None, config, opt_level, opt_stage, stage, + ); } } @@ -726,8 +746,10 @@ impl Drop for ThinBuffer { } pub(crate) fn optimize_thin_module( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, thin_module: ThinModule, ) -> ModuleCodegen { let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); @@ -740,7 +762,7 @@ pub(crate) fn optimize_thin_module( // into that context. One day, however, we may do this for upstream // crates but for locally codegened modules we may be able to reuse // that LLVM Context and Module. - let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx); + let module_llvm = ModuleLlvm::parse(cgcx, tm_factory, module_name, thin_module.data(), dcx); let mut module = ModuleCodegen::new_regular(thin_module.name(), module_llvm); // Given that the newly created module lacks a thinlto buffer for embedding, we need to re-add it here. if cgcx.module_config.embed_bitcode() { @@ -760,8 +782,7 @@ pub(crate) fn optimize_thin_module( // You can find some more comments about these functions in the LLVM // bindings we've got (currently `PassWrapper.cpp`) { - let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); + let _timer = prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); unsafe { llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target.raw()) }; @@ -769,9 +790,8 @@ pub(crate) fn optimize_thin_module( } { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); + let _timer = + prof.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) } { write::llvm_err(dcx, LlvmError::PrepareThinLtoModule); @@ -780,9 +800,8 @@ pub(crate) fn optimize_thin_module( } { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); + let _timer = + prof.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) } { write::llvm_err(dcx, LlvmError::PrepareThinLtoModule); @@ -791,8 +810,7 @@ pub(crate) fn optimize_thin_module( } { - let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); + let _timer = prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); if unsafe { !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target.raw()) } { @@ -808,7 +826,7 @@ pub(crate) fn optimize_thin_module( // little differently. { info!("running thin lto passes over {}", module.name); - run_pass_manager(cgcx, dcx, &mut module, true); + run_pass_manager(cgcx, prof, dcx, &mut module, true); save_temp_bitcode(cgcx, &module, "thin-lto-after-pm"); } } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fb07794e1bba..3e3ccd39e674 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -38,8 +38,8 @@ use crate::builder::SBuilder; use crate::builder::gpu_offload::scalar_width; use crate::common::AsCCharPtr; use crate::errors::{ - CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression, - WithLlvmError, WriteBytecode, + CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig, + UnknownCompression, WithLlvmError, WriteBytecode, }; use crate::llvm::diagnostic::OptimizationDiagnosticKind::*; use crate::llvm::{self, DiagnosticInfo}; @@ -111,8 +111,7 @@ pub(crate) fn create_informational_target_machine( // 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, only_base_features); - target_machine_factory(sess, config::OptLevel::No, &features)(config) - .unwrap_or_else(|err| llvm_err(sess.dcx(), err)) + target_machine_factory(sess, config::OptLevel::No, &features)(sess.dcx(), config) } pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine { @@ -138,8 +137,7 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar tcx.sess, tcx.backend_optimization_level(()), tcx.global_backend_features(()), - )(config) - .unwrap_or_else(|err| llvm_err(tcx.dcx(), err)) + )(tcx.dcx(), config) } fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) { @@ -278,7 +276,7 @@ pub(crate) fn target_machine_factory( let large_data_threshold = sess.opts.unstable_opts.large_data_threshold.unwrap_or(0); let prof = SelfProfilerRef::clone(&sess.prof); - Arc::new(move |config: TargetMachineFactoryConfig| { + Arc::new(move |dcx: DiagCtxtHandle<'_>, config: TargetMachineFactoryConfig| { // Self-profile timer for invoking a factory to create a target machine. let _prof_timer = prof.generic_activity("target_machine_factory_inner"); @@ -320,11 +318,12 @@ pub(crate) fn target_machine_factory( use_wasm_eh, large_data_threshold, ) + .unwrap_or_else(|err| dcx.emit_fatal(ParseTargetMachineConfig(err))) }) } pub(crate) fn save_temp_bitcode( - cgcx: &CodegenContext, + cgcx: &CodegenContext, module: &ModuleCodegen, name: &str, ) { @@ -359,14 +358,14 @@ pub(crate) enum CodegenDiagnosticsStage { } pub(crate) struct DiagnosticHandlers<'a> { - data: *mut (&'a CodegenContext, &'a SharedEmitter), + data: *mut (&'a CodegenContext, &'a SharedEmitter), llcx: &'a llvm::Context, old_handler: Option<&'a llvm::DiagnosticHandler>, } impl<'a> DiagnosticHandlers<'a> { pub(crate) fn new( - cgcx: &'a CodegenContext, + cgcx: &'a CodegenContext, shared_emitter: &'a SharedEmitter, llcx: &'a llvm::Context, module: &ModuleCodegen, @@ -432,7 +431,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> { } fn report_inline_asm( - cgcx: &CodegenContext, + cgcx: &CodegenContext, msg: String, level: llvm::DiagnosticLevel, cookie: u64, @@ -464,8 +463,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void if user.is_null() { return; } - let (cgcx, shared_emitter) = - unsafe { *(user as *const (&CodegenContext, &SharedEmitter)) }; + let (cgcx, shared_emitter) = unsafe { *(user as *const (&CodegenContext, &SharedEmitter)) }; let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -561,7 +559,8 @@ pub(crate) enum AutodiffStage { } pub(crate) unsafe fn llvm_optimize( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, module: &ModuleCodegen, thin_lto_buffer: Option<&mut *mut llvm::ThinLTOBuffer>, @@ -758,10 +757,9 @@ pub(crate) unsafe fn llvm_optimize( } } - let mut llvm_profiler = cgcx - .prof + let mut llvm_profiler = prof .llvm_recording_enabled() - .then(|| LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap())); + .then(|| LlvmSelfProfiler::new(prof.get_self_profiler().unwrap())); let llvm_selfprofiler = llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut()); @@ -880,7 +878,7 @@ pub(crate) unsafe fn llvm_optimize( &out_obj, None, llvm::FileType::ObjectFile, - &cgcx.prof, + prof, true, ); // We ignore cgcx.save_temps here and unconditionally always keep our `host.out` artifact. @@ -893,12 +891,13 @@ pub(crate) unsafe fn llvm_optimize( // Unsafe due to LLVM calls. pub(crate) fn optimize( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); + let _timer = prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -945,6 +944,7 @@ pub(crate) fn optimize( unsafe { llvm_optimize( cgcx, + prof, dcx, module, thin_lto_buffer.as_mut(), @@ -966,12 +966,12 @@ pub(crate) fn optimize( && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name() { let summary_data = thin_lto_buffer.thin_link_data(); - cgcx.prof.artifact_size( + prof.artifact_size( "llvm_bitcode_summary", thin_link_bitcode_filename.to_string_lossy(), summary_data.len() as u64, ); - let _timer = cgcx.prof.generic_activity_with_arg( + let _timer = prof.generic_activity_with_arg( "LLVM_module_codegen_emit_bitcode_summary", &*module.name, ); @@ -984,12 +984,13 @@ pub(crate) fn optimize( } pub(crate) fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); + let _timer = prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -1028,18 +1029,17 @@ pub(crate) fn codegen( if config.bitcode_needed() { if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let thin = { - let _timer = cgcx.prof.generic_activity_with_arg( + let _timer = prof.generic_activity_with_arg( "LLVM_module_codegen_make_bitcode", &*module.name, ); ThinBuffer::new(llmod, config.emit_thin_lto) }; let data = thin.data(); - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name); if let Some(bitcode_filename) = bc_out.file_name() { - cgcx.prof.artifact_size( + prof.artifact_size( "llvm_bitcode", bitcode_filename.to_string_lossy(), data.len() as u64, @@ -1051,8 +1051,7 @@ pub(crate) fn codegen( } if config.embed_bitcode() && module.kind == ModuleKind::Regular { - let _timer = cgcx - .prof + let _timer = prof .generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name); let thin_bc = module.thin_lto_buffer.as_deref().expect("cannot find embedded bitcode"); @@ -1062,7 +1061,7 @@ pub(crate) fn codegen( if config.emit_ir { let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); + prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); let out = cgcx.output_filenames.temp_path_for_cgu( OutputType::LlvmAssembly, &module.name, @@ -1100,7 +1099,7 @@ pub(crate) fn codegen( unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) }; if result == llvm::LLVMRustResult::Success { - record_artifact_size(&cgcx.prof, "llvm_ir", &out); + record_artifact_size(prof, "llvm_ir", &out); } result @@ -1110,7 +1109,7 @@ pub(crate) fn codegen( if config.emit_asm { let _timer = - cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); + prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path_for_cgu( OutputType::Assembly, &module.name, @@ -1134,16 +1133,15 @@ pub(crate) fn codegen( &path, None, llvm::FileType::AssemblyFile, - &cgcx.prof, + prof, config.verify_llvm_ir, ); } match config.emit_obj { EmitObj::ObjectCode(_) => { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); + let _timer = + prof.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); let dwo_out = cgcx .output_filenames @@ -1170,7 +1168,7 @@ pub(crate) fn codegen( &obj_out, dwo_out, llvm::FileType::ObjectFile, - &cgcx.prof, + prof, config.verify_llvm_ir, ); } @@ -1190,7 +1188,7 @@ pub(crate) fn codegen( EmitObj::None => {} } - record_llvm_cgu_instructions_stats(&cgcx.prof, &module.name, llmod); + record_llvm_cgu_instructions_stats(prof, &module.name, llmod); } // `.dwo` files are only emitted if: @@ -1239,7 +1237,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: asm } -pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { +pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { if cgcx.target_is_like_darwin { c"__LLVM,__bitcode" } else if cgcx.target_is_like_aix { @@ -1251,7 +1249,7 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> /// Embed the bitcode of an LLVM module for LTO in the LLVM module itself. fn embed_bitcode( - cgcx: &CodegenContext, + cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module, bitcode: &[u8], @@ -1335,11 +1333,7 @@ fn embed_bitcode( // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_msvc_imps( - cgcx: &CodegenContext, - llcx: &llvm::Context, - llmod: &llvm::Module, -) { +fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) { if !cgcx.msvc_imps_needed { return; } diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 402861eda870..a60e2d1f0ab0 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -1,12 +1,13 @@ use std::ffi::CString; +use bitflags::Flags; use llvm::Linkage::*; use rustc_abi::Align; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_middle::bug; -use rustc_middle::ty::offload_meta::OffloadMetadata; +use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata}; use crate::builder::Builder; use crate::common::CodegenCx; @@ -28,10 +29,6 @@ pub(crate) struct OffloadGlobals<'ll> { pub mapper_fn_ty: &'ll llvm::Type, pub ident_t_global: &'ll llvm::Value, - - // FIXME(offload): Drop this, once we fully automated our offload compilation pipeline, since - // LLVM will initialize them for us if it sees gpu kernels being registered. - pub init_rtls: &'ll llvm::Value, } impl<'ll> OffloadGlobals<'ll> { @@ -42,9 +39,6 @@ impl<'ll> OffloadGlobals<'ll> { let (begin_mapper, _, end_mapper, mapper_fn_ty) = gen_tgt_data_mappers(cx); let ident_t_global = generate_at_one(cx); - let init_ty = cx.type_func(&[], cx.type_void()); - let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); - // We want LLVM's openmp-opt pass to pick up and optimize this module, since it covers both // openmp and offload optimizations. llvm::add_module_flag_u32(cx.llmod(), llvm::ModuleFlagMergeBehavior::Max, "openmp", 51); @@ -58,7 +52,6 @@ impl<'ll> OffloadGlobals<'ll> { end_mapper, mapper_fn_ty, ident_t_global, - init_rtls, } } } @@ -91,6 +84,11 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) { let atexit = cx.type_func(&[cx.type_ptr()], cx.type_i32()); let atexit_fn = declare_offload_fn(cx, "atexit", atexit); + // FIXME(offload): Drop this, once we fully automated our offload compilation pipeline, since + // LLVM will initialize them for us if it sees gpu kernels being registered. + let init_ty = cx.type_func(&[], cx.type_void()); + let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); + let desc_ty = cx.type_func(&[], cx.type_void()); let reg_name = ".omp_offloading.descriptor_reg"; let unreg_name = ".omp_offloading.descriptor_unreg"; @@ -104,12 +102,14 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) { // define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // entry: // call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) + // call void @__tgt_init_all_rtls() // %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) // ret void // } let bb = Builder::append_block(cx, desc_reg_fn, "entry"); let mut a = Builder::build(cx, bb); a.call(reg_lib_decl, None, None, register_lib, &[omp_descriptor], None, None); + a.call(init_ty, None, None, init_rtls, &[], None, None); a.call(atexit, None, None, atexit_fn, &[desc_unreg_fn], None, None); a.ret_void(); @@ -345,9 +345,10 @@ impl KernelArgsTy { #[derive(Copy, Clone)] pub(crate) struct OffloadKernelGlobals<'ll> { pub offload_sizes: &'ll llvm::Value, - pub memtransfer_types: &'ll llvm::Value, + pub memtransfer_begin: &'ll llvm::Value, + pub memtransfer_kernel: &'ll llvm::Value, + pub memtransfer_end: &'ll llvm::Value, pub region_id: &'ll llvm::Value, - pub offload_entry: &'ll llvm::Value, } fn gen_tgt_data_mappers<'ll>( @@ -424,18 +425,38 @@ pub(crate) fn gen_define_handling<'ll>( let offload_entry_ty = offload_globals.offload_entry_ty; - // FIXME(Sa4dUs): add `OMP_MAP_TARGET_PARAM = 0x20` only if necessary let (sizes, transfer): (Vec<_>, Vec<_>) = - metadata.iter().map(|m| (m.payload_size, m.mode.bits() | 0x20)).unzip(); + metadata.iter().map(|m| (m.payload_size, m.mode)).unzip(); + // Our begin mapper should only see simplified information about which args have to be + // transferred to the device, the end mapper only about which args should be transferred back. + // Any information beyond that makes it harder for LLVM's opt pass to evaluate whether it can + // safely move (=optimize) the LLVM-IR location of this data transfer. Only the mapping types + // mentioned below are handled, so make sure that we don't generate any other ones. + let handled_mappings = MappingFlags::TO + | MappingFlags::FROM + | MappingFlags::TARGET_PARAM + | MappingFlags::LITERAL + | MappingFlags::IMPLICIT; + for arg in &transfer { + debug_assert!(!arg.contains_unknown_bits()); + debug_assert!(handled_mappings.contains(*arg)); + } + + let valid_begin_mappings = MappingFlags::TO | MappingFlags::LITERAL | MappingFlags::IMPLICIT; + let transfer_to: Vec = + transfer.iter().map(|m| m.intersection(valid_begin_mappings).bits()).collect(); + let transfer_from: Vec = + transfer.iter().map(|m| m.intersection(MappingFlags::FROM).bits()).collect(); + // FIXME(offload): add `OMP_MAP_TARGET_PARAM = 0x20` only if necessary + let transfer_kernel = vec![MappingFlags::TARGET_PARAM.bits(); transfer_to.len()]; let offload_sizes = add_priv_unnamed_arr(&cx, &format!(".offload_sizes.{symbol}"), &sizes); - // Here we figure out whether something needs to be copied to the gpu (=1), from the gpu (=2), - // or both to and from the gpu (=3). Other values shouldn't affect us for now. - // A non-mutable reference or pointer will be 1, an array that's not read, but fully overwritten - // will be 2. For now, everything is 3, until we have our frontend set up. - // 1+2+32: 1 (MapTo), 2 (MapFrom), 32 (Add one extra input ptr per function, to be used later). - let memtransfer_types = - add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}"), &transfer); + let memtransfer_begin = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.begin"), &transfer_to); + let memtransfer_kernel = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.kernel"), &transfer_kernel); + let memtransfer_end = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.end"), &transfer_from); // Next: For each function, generate these three entries. A weak constant, // the llvm.rodata entry name, and the llvm_offload_entries value @@ -468,8 +489,18 @@ pub(crate) fn gen_define_handling<'ll>( let c_section_name = CString::new("llvm_offload_entries").unwrap(); llvm::set_section(offload_entry, &c_section_name); - let result = - OffloadKernelGlobals { offload_sizes, memtransfer_types, region_id, offload_entry }; + cx.add_compiler_used_global(offload_entry); + + let result = OffloadKernelGlobals { + offload_sizes, + memtransfer_begin, + memtransfer_kernel, + memtransfer_end, + region_id, + }; + + // FIXME(Sa4dUs): use this global for constant offload sizes + cx.add_compiler_used_global(result.offload_sizes); cx.offload_kernel_cache.borrow_mut().insert(symbol, result); @@ -532,8 +563,13 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( offload_dims: &OffloadKernelDims<'ll>, ) { let cx = builder.cx; - let OffloadKernelGlobals { offload_sizes, offload_entry, memtransfer_types, region_id } = - offload_data; + let OffloadKernelGlobals { + memtransfer_begin, + memtransfer_kernel, + memtransfer_end, + region_id, + .. + } = offload_data; let OffloadKernelDims { num_workgroups, threads_per_block, workgroup_dims, thread_dims } = offload_dims; @@ -548,20 +584,6 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let num_args = types.len() as u64; let bb = builder.llbb(); - // FIXME(Sa4dUs): dummy loads are a temp workaround, we should find a proper way to prevent these - // variables from being optimized away - for val in [offload_sizes, offload_entry] { - unsafe { - let dummy = llvm::LLVMBuildLoad2( - &builder.llbuilder, - llvm::LLVMTypeOf(val), - val, - b"dummy\0".as_ptr() as *const _, - ); - llvm::LLVMSetVolatile(dummy, llvm::TRUE); - } - } - // Step 0) unsafe { llvm::LLVMRustPositionBuilderPastAllocas(&builder.llbuilder, builder.llfn()); @@ -620,12 +642,6 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( geps.push(gep); } - let init_ty = cx.type_func(&[], cx.type_void()); - let init_rtls_decl = offload_globals.init_rtls; - - // call void @__tgt_init_all_rtls() - builder.call(init_ty, None, None, init_rtls_decl, &[], None, None); - for i in 0..num_args { let idx = cx.get_const_i32(i); let gep1 = builder.inbounds_gep(ty, a1, &[i32_0, idx]); @@ -680,14 +696,14 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( generate_mapper_call( builder, geps, - memtransfer_types, + memtransfer_begin, begin_mapper_decl, fn_ty, num_args, s_ident_t, ); let values = - KernelArgsTy::new(&cx, num_args, memtransfer_types, geps, workgroup_dims, thread_dims); + KernelArgsTy::new(&cx, num_args, memtransfer_kernel, geps, workgroup_dims, thread_dims); // Step 3) // Here we fill the KernelArgsTy, see the documentation above @@ -713,7 +729,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( generate_mapper_call( builder, geps, - memtransfer_types, + memtransfer_end, end_mapper_decl, fn_ty, num_args, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md index aaec4e68c174..f5ea5ea77c4b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md +++ b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md @@ -16,7 +16,7 @@ module to generate correct metadata and insert it into the LLVM IR. As the exact format of metadata trees may change between different LLVM versions, we now use LLVM [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) -to create metadata where possible. This will hopefully ease the adaption of +to create metadata where possible. This will hopefully ease the adaptation of this module to future LLVM versions. The public API of the module is a set of functions that will insert the @@ -87,19 +87,19 @@ describe the type anew. This behavior is encapsulated in the ## Source Locations and Line Information In addition to data type descriptions the debugging information must also -allow to map machine code locations back to source code locations in order +allow mapping machine code locations back to source code locations in order to be useful. This functionality is also handled in this module. The -following functions allow to control source mappings: +following functions allow controlling source mappings: + `set_source_location()` + `clear_source_location()` + `start_emitting_source_locations()` -`set_source_location()` allows to set the current source location. All IR +`set_source_location()` allows setting the current source location. All IR instructions created after a call to this function will be linked to the given source location, until another location is specified with `set_source_location()` or the source location is cleared with -`clear_source_location()`. In the later case, subsequent IR instruction +`clear_source_location()`. In the latter case, subsequent IR instructions will not be linked to any source location. As you can see, this is a stateful API (mimicking the one in LLVM), so be careful with source locations set by previous calls. It's probably best to not rely on any diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1c674f0e8a85..c759d46b7d2f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -479,7 +479,18 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>( AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), - _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), + ty::Pat(base, _) => return type_di_node(cx, base), + // FIXME(unsafe_binders): impl debug info + ty::UnsafeBinder(_) => unimplemented!(), + ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Infer(_) + | ty::Placeholder(_) + | ty::CoroutineWitness(..) + | ty::Error(_) => { + bug!("debuginfo: unexpected type in type_di_node(): {:?}", t) + } }; { diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index bd42cf556966..af154a1aea80 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,14 +2,12 @@ use std::ffi::CString; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; use rustc_macros::Diagnostic; use rustc_span::Span; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(codegen_llvm_symbol_already_defined)] +#[diag("symbol `{$symbol_name}` is already defined")] pub(crate) struct SymbolAlreadyDefined<'a> { #[primary_span] pub span: Span, @@ -17,7 +15,7 @@ pub(crate) struct SymbolAlreadyDefined<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_sanitizer_memtag_requires_mte)] +#[diag("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`")] pub(crate) struct SanitizerMemtagRequiresMte; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); @@ -27,90 +25,94 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { let diag: Diag<'_, G> = self.0.into_diag(dcx, level); let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter()); - Diag::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config) - .with_arg("error", message) + Diag::new( + dcx, + level, + msg!("failed to parse target machine config to target machine: {$error}"), + ) + .with_arg("error", message) } } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_component_unavailable)] +#[diag("failed to load our autodiff backend: {$err}")] pub(crate) struct AutoDiffComponentUnavailable { pub err: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_component_missing)] -#[note] +#[diag("autodiff backend not found in the sysroot: {$err}")] +#[note("it will be distributed via rustup in the future")] pub(crate) struct AutoDiffComponentMissing { pub err: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_without_lto)] +#[diag("using the autodiff feature requires setting `lto=\"fat\"` in your Cargo.toml")] pub(crate) struct AutoDiffWithoutLto; #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_without_enable)] +#[diag("using the autodiff feature requires -Z autodiff=Enable")] pub(crate) struct AutoDiffWithoutEnable; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_without_enable)] +#[diag("using the offload feature requires -Z offload=")] pub(crate) struct OffloadWithoutEnable; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_without_fat_lto)] +#[diag("using the offload feature requires -C lto=fat")] pub(crate) struct OffloadWithoutFatLTO; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_no_abs_path)] +#[diag("using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path")] pub(crate) struct OffloadWithoutAbsPath; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_no_host_out)] +#[diag( + "using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file" +)] pub(crate) struct OffloadWrongFileName; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_nonexisting)] +#[diag( + "the given path/file to `host.out` does not exist. Did you forget to run the device compilation first?" +)] pub(crate) struct OffloadNonexistingPath; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_bundleimages_failed)] +#[diag("call to BundleImages failed, `host.out` was not created")] pub(crate) struct OffloadBundleImagesFailed; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_embed_failed)] +#[diag("call to EmbedBufferInModule failed, `host.o` was not created")] pub(crate) struct OffloadEmbedFailed; #[derive(Diagnostic)] -#[diag(codegen_llvm_lto_bitcode_from_rlib)] +#[diag("failed to get bitcode from object file for LTO ({$err})")] pub(crate) struct LtoBitcodeFromRlib { pub err: String, } #[derive(Diagnostic)] -pub enum LlvmError<'a> { - #[diag(codegen_llvm_write_output)] +pub(crate) enum LlvmError<'a> { + #[diag("could not write output to {$path}")] WriteOutput { path: &'a Path }, - #[diag(codegen_llvm_target_machine)] + #[diag("could not create LLVM TargetMachine for triple: {$triple}")] CreateTargetMachine { triple: SmallCStr }, - #[diag(codegen_llvm_run_passes)] + #[diag("failed to run LLVM passes")] RunLlvmPasses, - #[diag(codegen_llvm_serialize_module)] - SerializeModule { name: &'a str }, - #[diag(codegen_llvm_write_ir)] + #[diag("failed to write LLVM IR to {$path}")] WriteIr { path: &'a Path }, - #[diag(codegen_llvm_prepare_thin_lto_context)] + #[diag("failed to prepare thin LTO context")] PrepareThinLtoContext, - #[diag(codegen_llvm_load_bitcode)] + #[diag("failed to load bitcode of module \"{$name}\"")] LoadBitcode { name: CString }, - #[diag(codegen_llvm_write_thinlto_key)] + #[diag("error while writing ThinLTO key data: {$err}")] WriteThinLtoKey { err: std::io::Error }, - #[diag(codegen_llvm_prepare_thin_lto_module)] + #[diag("failed to prepare thin LTO module")] PrepareThinLtoModule, - #[diag(codegen_llvm_parse_bitcode)] + #[diag("failed to parse bitcode for LTO module")] ParseBitcode, - #[diag(codegen_llvm_prepare_autodiff)] - PrepareAutoDiff { src: String, target: String, error: String }, } pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); @@ -119,17 +121,25 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { - WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, - CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err, - RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err, - SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err, - WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err, - PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err, - LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err, - WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err, - PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, - ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, - PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err, + WriteOutput { .. } => msg!("could not write output to {$path}: {$llvm_err}"), + CreateTargetMachine { .. } => { + msg!("could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}") + } + RunLlvmPasses => msg!("failed to run LLVM passes: {$llvm_err}"), + WriteIr { .. } => msg!("failed to write LLVM IR to {$path}: {$llvm_err}"), + PrepareThinLtoContext => { + msg!("failed to prepare thin LTO context: {$llvm_err}") + } + LoadBitcode { .. } => { + msg!("failed to load bitcode of module \"{$name}\": {$llvm_err}") + } + WriteThinLtoKey { .. } => { + msg!("error while writing ThinLTO key data: {$err}: {$llvm_err}") + } + PrepareThinLtoModule => { + msg!("failed to prepare thin LTO module: {$llvm_err}") + } + ParseBitcode => msg!("failed to parse bitcode for LTO module: {$llvm_err}"), }; self.0 .into_diag(dcx, level) @@ -139,7 +149,7 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_from_llvm_optimization_diag)] +#[diag("{$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}")] pub(crate) struct FromLlvmOptimizationDiag<'a> { pub filename: &'a str, pub line: std::ffi::c_uint, @@ -150,32 +160,36 @@ pub(crate) struct FromLlvmOptimizationDiag<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_from_llvm_diag)] +#[diag("{$message}")] pub(crate) struct FromLlvmDiag { pub message: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_write_bytecode)] +#[diag("failed to write bytecode to {$path}: {$err}")] pub(crate) struct WriteBytecode<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_llvm_copy_bitcode)] +#[diag("failed to copy bitcode to object file: {$err}")] pub(crate) struct CopyBitcode { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_llvm_unknown_debuginfo_compression)] +#[diag( + "unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo" +)] pub(crate) struct UnknownCompression { pub algorithm: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_llvm_mismatch_data_layout)] +#[diag( + "data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`" +)] pub(crate) struct MismatchedDataLayout<'a> { pub rustc_target: &'a str, pub rustc_layout: &'a str, @@ -184,11 +198,11 @@ pub(crate) struct MismatchedDataLayout<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_fixed_x18_invalid_arch)] +#[diag("the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture")] pub(crate) struct FixedX18InvalidArch<'a> { pub arch: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0)] +#[diag("`-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later")] pub(crate) struct SanitizerKcfiArityRequiresLLVM2100; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e035f0809d68..6bcc8135f35e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -387,6 +387,27 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let pair = self.insert_value(pair, high, 1); pair } + + // FIXME move into the branch below when LLVM 22 is the lowest version we support. + sym::carryless_mul if crate::llvm_util::get_version() >= (22, 0, 0) => { + let ty = args[0].layout.ty; + if !ty.is_integral() { + tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { + span, + name, + ty, + }); + return Ok(()); + } + let (size, _) = ty.int_size_and_signed(self.tcx); + let width = size.bits(); + let llty = self.type_ix(width); + + let lhs = args[0].immediate(); + let rhs = args[1].immediate(); + self.call_intrinsic("llvm.clmul", &[llty], &[lhs, rhs]) + } + sym::ctlz | sym::ctlz_nonzero | sym::cttz @@ -646,10 +667,32 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { ) -> Self::Value { let tcx = self.tcx(); - // FIXME remove usage of fn_abi - let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - assert!(!fn_abi.ret.is_indirect()); - let fn_ty = fn_abi.llvm_type(self); + let fn_ty = instance.ty(tcx, self.typing_env()); + let fn_sig = match *fn_ty.kind() { + ty::FnDef(def_id, args) => { + tcx.instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args)) + } + _ => unreachable!(), + }; + assert!(!fn_sig.c_variadic); + + let ret_layout = self.layout_of(fn_sig.output()); + let llreturn_ty = if ret_layout.is_zst() { + self.type_void() + } else { + ret_layout.immediate_llvm_type(self) + }; + + let mut llargument_tys = Vec::with_capacity(fn_sig.inputs().len()); + for &arg in fn_sig.inputs() { + let arg_layout = self.layout_of(arg); + if arg_layout.is_zst() { + continue; + } + llargument_tys.push(arg_layout.immediate_llvm_type(self)); + } + + let fn_ty = self.type_func(&llargument_tys, llreturn_ty); let fn_ptr = if let Some(&llfn) = self.intrinsic_instances.borrow().get(&instance) { llfn @@ -665,12 +708,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let llfn = declare_raw_fn( self, sym, - fn_abi.llvm_cconv(self), + llvm::CCallConv, llvm::UnnamedAddr::Global, llvm::Visibility::Default, fn_ty, ); - fn_abi.apply_attrs_llfn(self, llfn, Some(instance)); llfn }; @@ -2763,6 +2805,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( | sym::simd_ctlz | sym::simd_ctpop | sym::simd_cttz + | sym::simd_carryless_mul | sym::simd_funnel_shl | sym::simd_funnel_shr ) { @@ -2787,6 +2830,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_cttz => "llvm.cttz", sym::simd_funnel_shl => "llvm.fshl", sym::simd_funnel_shr => "llvm.fshr", + sym::simd_carryless_mul => "llvm.clmul", _ => unreachable!(), }; let int_size = in_elem.int_size_and_signed(bx.tcx()).0.bits(); @@ -2812,6 +2856,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>( &[vec_ty], &[args[0].immediate(), args[1].immediate(), args[2].immediate()], )), + sym::simd_carryless_mul => { + if crate::llvm_util::get_version() >= (22, 0, 0) { + Ok(bx.call_intrinsic( + llvm_intrinsic, + &[vec_ty], + &[args[0].immediate(), args[1].immediate()], + )) + } else { + span_bug!(span, "`simd_carryless_mul` needs LLVM 22 or higher"); + } + } _ => unreachable!(), }; } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 5879132eb9fb..3310fe4f43f8 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -5,7 +5,7 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(extern_types)] #![feature(file_buffered)] #![feature(if_let_guard)] @@ -25,7 +25,6 @@ use std::path::PathBuf; use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use context::SimpleCx; -use errors::ParseTargetMachineConfig; use llvm_util::target_config; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; @@ -36,6 +35,7 @@ use rustc_codegen_ssa::back::write::{ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -43,7 +43,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use rustc_target::spec::{RelocModel, TlsModel}; use crate::llvm::ToLlvmBool; @@ -74,8 +74,6 @@ mod typetree; mod va_arg; mod value; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub(crate) use macros::TryFromU32; #[derive(Clone)] @@ -154,7 +152,6 @@ impl WriteBackendMethods for LlvmCodegenBackend { type Module = ModuleLlvm; type ModuleBuffer = back::lto::ModuleBuffer; type TargetMachine = OwnedTargetMachine; - type TargetMachineError = crate::errors::LlvmError<'static>; type ThinData = back::lto::ThinData; type ThinBuffer = back::lto::ThinBuffer; fn print_pass_timings(&self) { @@ -166,15 +163,19 @@ impl WriteBackendMethods for LlvmCodegenBackend { print!("{stats}"); } fn run_and_optimize_fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { let mut module = back::lto::run_fat( cgcx, + prof, shared_emitter, + tm_factory, exported_symbols_for_lto, each_linked_rlib_for_lto, modules, @@ -182,12 +183,13 @@ impl WriteBackendMethods for LlvmCodegenBackend { let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); - back::lto::run_pass_manager(cgcx, dcx, &mut module, false); + back::lto::run_pass_manager(cgcx, prof, dcx, &mut module, false); module } fn run_thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], @@ -196,6 +198,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) -> (Vec>, Vec) { back::lto::run_thin( cgcx, + prof, dcx, exported_symbols_for_lto, each_linked_rlib_for_lto, @@ -204,27 +207,31 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) } fn optimize( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { - back::write::optimize(cgcx, shared_emitter, module, config) + back::write::optimize(cgcx, prof, shared_emitter, module, config) } fn optimize_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, thin: ThinModule, ) -> ModuleCodegen { - back::lto::optimize_thin_module(cgcx, shared_emitter, thin) + back::lto::optimize_thin_module(cgcx, prof, shared_emitter, tm_factory, thin) } fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, shared_emitter, module, config) + back::write::codegen(cgcx, prof, shared_emitter, module, config) } fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { back::lto::prepare_thin(module) @@ -241,10 +248,6 @@ impl LlvmCodegenBackend { } impl CodegenBackend for LlvmCodegenBackend { - fn locale_resource(&self) -> &'static str { - crate::DEFAULT_LOCALE_RESOURCE - } - fn name(&self) -> &'static str { "llvm" } @@ -350,6 +353,17 @@ impl CodegenBackend for LlvmCodegenBackend { target_config(sess) } + fn replaced_intrinsics(&self) -> Vec { + let mut will_not_use_fallback = + vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add]; + + if llvm_util::get_version() >= (22, 0, 0) { + will_not_use_fallback.push(sym::carryless_mul); + } + + will_not_use_fallback + } + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { Box::new(rustc_codegen_ssa::base::codegen_crate( LlvmCodegenBackend(()), @@ -442,22 +456,9 @@ impl ModuleLlvm { } } - fn tm_from_cgcx( - cgcx: &CodegenContext, - name: &str, - dcx: DiagCtxtHandle<'_>, - ) -> OwnedTargetMachine { - let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, name); - match (cgcx.tm_factory)(tm_factory_config) { - Ok(m) => m, - Err(e) => { - dcx.emit_fatal(ParseTargetMachineConfig(e)); - } - } - } - fn parse( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + tm_factory: TargetMachineFactoryFn, name: &CStr, buffer: &[u8], dcx: DiagCtxtHandle<'_>, @@ -466,7 +467,7 @@ impl ModuleLlvm { let llcx = llvm::LLVMContextCreate(); llvm::LLVMContextSetDiscardValueNames(llcx, cgcx.fewer_names.to_llvm_bool()); let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx); - let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx); + let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap())); ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) } } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 838db689e729..1a8fbf67f0bc 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -41,7 +41,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { }); llvm::set_linkage(g, base::linkage_to_llvm(linkage)); - llvm::set_visibility(g, base::visibility_to_llvm(visibility)); + self.set_visibility(g, linkage, visibility); + self.assume_dso_local(g, false); let attrs = self.tcx.codegen_instance_attrs(instance.def); @@ -69,16 +70,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { { llvm::SetUniqueComdat(self.llmod, lldecl); } - - // If we're compiling the compiler-builtins crate, e.g., the equivalent of - // compiler-rt, then we want to implicitly compile everything with hidden - // visibility as we're going to link this object all over the place but - // don't want the symbols to get exported. - if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { - llvm::set_visibility(lldecl, llvm::Visibility::Hidden); - } else { - llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility)); - } + self.set_visibility(lldecl, linkage, visibility); debug!("predefine_fn: instance = {:?}", instance); @@ -122,6 +114,18 @@ impl CodegenCx<'_, '_> { assume } + fn set_visibility(&self, lldecl: &llvm::Value, linkage: Linkage, visibility: Visibility) { + // If we're compiling the compiler-builtins crate, i.e., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { + llvm::set_visibility(lldecl, llvm::Visibility::Hidden); + } else { + llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility)); + } + } + fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool { let linkage = llvm::get_linkage(llval); let visibility = llvm::get_visibility(llval); diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index c7da2457ada5..460f4afea963 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -131,7 +131,7 @@ fn emit_ptr_va_arg<'ll, 'tcx>( ); if indirect { let tmp_ret = bx.load(llty, addr, addr_align); - bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi) + bx.load(layout.llvm_type(bx.cx), tmp_ret, align.abi) } else { bx.load(llty, addr, addr_align) } @@ -1007,6 +1007,8 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( /// Determine the va_arg implementation to use. The LLVM va_arg instruction /// is lacking in some instances, so we should only use it as a fallback. +/// +/// pub(super) fn emit_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, @@ -1015,6 +1017,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( let layout = bx.cx.layout_of(target_ty); let target_ty_size = layout.layout.size().bytes(); + // Some ABIs have special behavior for zero-sized types. currently `VaArgSafe` is not + // implemented for any zero-sized types, so this assert should always hold. + assert!(!bx.layout_of(target_ty).is_zst()); + let target = &bx.cx.tcx.sess.target; match target.arch { Arch::X86 => emit_ptr_va_arg( @@ -1026,17 +1032,24 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, ForceRightAdjust::No, ), - Arch::AArch64 | Arch::Arm64EC if target.is_like_windows || target.is_like_darwin => { - emit_ptr_va_arg( - bx, - addr, - target_ty, - PassMode::Direct, - SlotSize::Bytes8, - if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, - ForceRightAdjust::No, - ) - } + Arch::Arm64EC => emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ForceRightAdjust::No, + ), + Arch::AArch64 if target.is_like_windows || target.is_like_darwin => emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ForceRightAdjust::No, + ), Arch::AArch64 => emit_aapcs_va_arg(bx, addr, target_ty), Arch::Arm => { // Types wider than 16 bytes are not currently supported. Clang has special logic for @@ -1064,7 +1077,16 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::Yes, ), - Arch::LoongArch32 => emit_ptr_va_arg( + Arch::RiscV32 if target.abi == Abi::Ilp32e => { + // FIXME: clang manually adjusts the alignment for this ABI. It notes: + // + // > To be compatible with GCC's behaviors, we force arguments with + // > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`, + // > `unsigned long long` and `double` to have 4-byte alignment. This + // > behavior may be changed when RV32E/ILP32E is ratified. + bug!("c-variadic calls with ilp32e use a custom ABI and are not currently implemented"); + } + Arch::RiscV32 | Arch::LoongArch32 => emit_ptr_va_arg( bx, addr, target_ty, @@ -1073,7 +1095,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::No, ), - Arch::LoongArch64 => emit_ptr_va_arg( + Arch::RiscV64 | Arch::LoongArch64 => emit_ptr_va_arg( bx, addr, target_ty, @@ -1100,7 +1122,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::No, ), - Arch::Wasm32 => emit_ptr_va_arg( + Arch::Wasm32 | Arch::Wasm64 => emit_ptr_va_arg( bx, addr, target_ty, @@ -1113,7 +1135,6 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::No, ), - Arch::Wasm64 => bug!("c-variadic functions are not fully implemented for wasm64"), Arch::CSky => emit_ptr_va_arg( bx, addr, @@ -1140,16 +1161,34 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64. Arch::X86_64 => emit_x86_64_sysv64_va_arg(bx, addr, target_ty), Arch::Xtensa => emit_xtensa_va_arg(bx, addr, target_ty), - Arch::Hexagon => { - if target.env == Env::Musl { - emit_hexagon_va_arg_musl(bx, addr, target_ty) - } else { - emit_hexagon_va_arg_bare_metal(bx, addr, target_ty) - } + Arch::Hexagon => match target.env { + Env::Musl => emit_hexagon_va_arg_musl(bx, addr, target_ty), + _ => emit_hexagon_va_arg_bare_metal(bx, addr, target_ty), + }, + Arch::Sparc64 => emit_ptr_va_arg( + bx, + addr, + target_ty, + if target_ty_size > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, + SlotSize::Bytes8, + AllowHigherAlign::Yes, + ForceRightAdjust::No, + ), + + Arch::Bpf => bug!("bpf does not support c-variadic functions"), + Arch::SpirV => bug!("spirv does not support c-variadic functions"), + + Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => { + // FIXME: port MipsTargetLowering::lowerVAARG. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } + Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => { + // Clang uses the LLVM implementation for these architectures. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } + Arch::Other(_) => { + // For custom targets, use the LLVM va_arg instruction as a fallback. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) } - // For all other architecture/OS combinations fall back to using - // the LLVM va_arg instruction. - // https://llvm.org/docs/LangRef.html#va-arg-instruction - _ => bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)), } } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 9c5a3d839ceb..c7d7b7429f34 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -18,7 +18,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } @@ -28,7 +27,6 @@ rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } @@ -38,7 +36,6 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tempfile = "3.2" -thin-vec = "0.2.12" thorin-dwp = "0.9" tracing = "0.1" wasm-encoder = "0.219" diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl deleted file mode 100644 index a49f411a7df6..000000000000 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ /dev/null @@ -1,397 +0,0 @@ -codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender - -codegen_ssa_aarch64_softfloat_neon = enabling the `neon` target feature on the current target is unsound due to ABI issues - -codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} - -codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work - -codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} - -codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty - -codegen_ssa_bpf_staticlib_not_supported = linking static libraries is not supported for BPF - -codegen_ssa_cgu_not_recorded = - CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded - -codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. - -codegen_ssa_compiler_builtins_cannot_call = - `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}` - -codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error} - -codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error} - -codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C target-cpu` - -codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} - -codegen_ssa_dlltool_fail_import_library = - dlltool could not create import library with {$dlltool_path} {$dlltool_args}: - {$stdout} - {$stderr} - -codegen_ssa_dynamic_linking_with_lto = - cannot prefer dynamic linking when performing LTO - .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO - -codegen_ssa_error_calling_dlltool = - error calling dlltool '{$dlltool_path}': {$error} - -codegen_ssa_error_creating_import_library = - error creating import library for {$lib_name}: {$error} - -codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error} - -codegen_ssa_error_writing_def_file = - error writing .DEF file: {$error} - -codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified - -codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error} - -codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err} - -codegen_ssa_failed_to_write = failed to write {$path}: {$error} - -codegen_ssa_feature_not_valid = the feature named `{$feature}` is not valid for this target - .label = `{$feature}` is not valid for this target - .help = consider removing the leading `+` in the feature name - -codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` - -codegen_ssa_forbidden_ctarget_feature = - target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason} - .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -codegen_ssa_forbidden_ctarget_feature_issue = for more information, see issue #116344 - -codegen_ssa_forbidden_target_feature_attr = - target feature `{$feature}` cannot be enabled with `#[target_feature]`: {$reason} - -codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced - -codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced - -codegen_ssa_incorrect_cgu_reuse_type = - CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> - [one] {"at least "} - *[other] {""} - }`{$expected_reuse}` - -codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. - -codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` - -codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type - -codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type - -codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` - -codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` - -codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_ssa_invalid_monomorphization_mask_wrong_element_type = invalid monomorphization of `{$name}` intrinsic: expected mask element type to be an integer, found `{$ty}` - -codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` - -codegen_ssa_invalid_monomorphization_non_scalable_type = invalid monomorphization of `{$name}` intrinsic: expected non-scalable type, found scalable type `{$ty}` -codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` - -codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` - -codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len}) - -codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` - -codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` - -codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` - -codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` - -codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 - -codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error} - -codegen_ssa_link_exe_status_stack_buffer_overrun = 0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN` - .abort_note = this may have been caused by a program abort and not a stack buffer overrun - .event_log_note = consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code - -codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error - -codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker - -codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} - -codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker - -codegen_ssa_linker_not_found = linker `{$linker_path}` not found - .note = {$error} - -codegen_ssa_linker_output = {$inner} - -codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker - -codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} - -codegen_ssa_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs - -codegen_ssa_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` - -codegen_ssa_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto` - -codegen_ssa_malformed_cgu_name = - found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case). - -codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload - -codegen_ssa_missing_features = add the missing features in a `target_feature` attribute - -codegen_ssa_missing_query_depgraph = - found CGU-reuse attribute but `-Zquery-dep-graph` was not specified - -codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found - -codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions - -codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times - .help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point - -codegen_ssa_no_field = no field `{$name}` - -codegen_ssa_no_module_named = - no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} - -codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} - -codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't - -codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} - .note = {$output} - -codegen_ssa_read_file = failed to read file: {$message} - -codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer - -codegen_ssa_requires_rust_abi = `#[track_caller]` requires Rust ABI - -codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error} - -codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`) - -codegen_ssa_rlib_missing_format = could not find formats for rlibs - -codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}` - -codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file - -codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected - -codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot - -codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time - -codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link - -codegen_ssa_static_library_native_artifacts = link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. - -codegen_ssa_static_library_native_artifacts_to_file = native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms. - -codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status} - .note = {$output} - -codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} - -codegen_ssa_target_feature_disable_or_enable = - the target features {$features} must all be either enabled or disabled together - -codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method - .label = cannot be applied to safe trait method - .label_def = not an `unsafe` function - -codegen_ssa_thorin_decompress_data = failed to decompress compressed section - -codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit}) - -codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data - -codegen_ssa_thorin_gimli_read = {$error} -codegen_ssa_thorin_gimli_write = {$error} - -codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format} - -codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object - -codegen_ssa_thorin_io = {$error} -codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id}) - -codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found - -codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` - -codegen_ssa_thorin_mixed_input_encodings = input objects have mixed encodings - -codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections - -codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package - -codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset} - -codegen_ssa_thorin_no_compilation_units = input object has no compilation units - -codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit - -codegen_ssa_thorin_not_output_object_created = no output object was created from inputs - -codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier) - -codegen_ssa_thorin_object_read = {$error} -codegen_ssa_thorin_object_write = {$error} -codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section - -codegen_ssa_thorin_parse_archive_member = failed to parse archive member - -codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section - -codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file - -codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind - -codegen_ssa_thorin_parse_input_object_file = failed to parse input object file - -codegen_ssa_thorin_parse_unit = failed to parse unit - -codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations - -codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute - -codegen_ssa_thorin_parse_unit_header = failed to parse unit header - -codegen_ssa_thorin_read_input_failure = failed to read input file - -codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset} - -codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index - -codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index - -codegen_ssa_thorin_section_without_name = section without name at offset {$offset} - -codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section - -codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit - -codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index - -codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset} - -codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}` - .note = {$error} - .command_note = {$command_formatted} - -codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} - -codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} - -codegen_ssa_unable_to_write_debugger_visualizer = unable to write debugger visualizer file `{$path}`: {$error} - -codegen_ssa_unknown_archive_kind = - don't know how to build archive of type: {$kind} - -codegen_ssa_unknown_ctarget_feature = - unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}` - .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future - .possible_feature = you might have meant: `{$rust_feature}` - .consider_filing_feature_request = consider filing a feature request - -codegen_ssa_unknown_ctarget_feature_prefix = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = features must begin with a `+` to enable or `-` to disable it - -codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified - -codegen_ssa_unstable_ctarget_feature = - unstable feature specified for `-Ctarget-feature`: `{$feature}` - .note = this feature is not stably supported; its behavior can change in the future - -codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target - -codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib) - -codegen_ssa_version_script_write_failure = failed to write version script: {$error} - -codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload - -codegen_ssa_xcrun_about = - the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file - -codegen_ssa_xcrun_command_line_tools_insufficient = - when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode - -codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error} - -codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}" - -# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars. -codegen_ssa_xcrun_no_developer_dir = - pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable - -codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk - .note = {$stderr} - -codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk - .note = {$stdout}{$stderr} diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 43e1e135a666..081fe0aa91aa 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -28,13 +28,13 @@ use std::fmt; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{DiagArgValue, IntoDiagArg}; -use rustc_hir as hir; +use rustc_hir::attrs::{AttributeKind, CguFields, CguKind}; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::{self as hir, find_attr}; use rustc_middle::mir::mono::CodegenUnitNameBuilder; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::{Span, Symbol, sym}; -use thin_vec::ThinVec; +use rustc_span::{Span, Symbol}; use tracing::debug; use crate::errors; @@ -63,9 +63,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr }, }; - for attr in tcx.hir_attrs(rustc_hir::CRATE_HIR_ID) { - ams.check_attr(attr); - } + ams.check_attrs(tcx.hir_attrs(rustc_hir::CRATE_HIR_ID)); set_reuse(&mut ams.cgu_reuse_tracker); @@ -89,109 +87,91 @@ struct AssertModuleSource<'tcx> { } impl<'tcx> AssertModuleSource<'tcx> { - fn check_attr(&mut self, attr: &hir::Attribute) { - let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { - (CguReuse::PreLto, ComparisonKind::AtLeast) - } else if attr.has_name(sym::rustc_partition_codegened) { - (CguReuse::No, ComparisonKind::Exact) - } else if attr.has_name(sym::rustc_expected_cgu_reuse) { - match self.field(attr, sym::kind) { - sym::no => (CguReuse::No, ComparisonKind::Exact), - sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact), - sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), - sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), - other => { - self.tcx - .dcx() - .emit_fatal(errors::UnknownReuseKind { span: attr.span(), kind: other }); - } + fn check_attrs(&mut self, attrs: &[hir::Attribute]) { + for &(span, cgu_fields) in find_attr!(attrs, + AttributeKind::RustcCguTestAttr(e) => e) + .into_iter() + .flatten() + { + let (expected_reuse, comp_kind) = match cgu_fields { + CguFields::PartitionReused { .. } => (CguReuse::PreLto, ComparisonKind::AtLeast), + CguFields::PartitionCodegened { .. } => (CguReuse::No, ComparisonKind::Exact), + CguFields::ExpectedCguReuse { kind, .. } => match kind { + CguKind::No => (CguReuse::No, ComparisonKind::Exact), + CguKind::PreDashLto => (CguReuse::PreLto, ComparisonKind::Exact), + CguKind::PostDashLto => (CguReuse::PostLto, ComparisonKind::Exact), + CguKind::Any => (CguReuse::PreLto, ComparisonKind::AtLeast), + }, + }; + let (CguFields::ExpectedCguReuse { cfg, module, .. } + | CguFields::PartitionCodegened { cfg, module } + | CguFields::PartitionReused { cfg, module }) = cgu_fields; + + if !self.tcx.sess.opts.unstable_opts.query_dep_graph { + self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span }); } - } else { - return; - }; - if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span() }); - } + if !self.check_config(cfg) { + debug!("check_attr: config does not match, ignoring attr"); + return; + } - if !self.check_config(attr) { - debug!("check_attr: config does not match, ignoring attr"); - return; - } + let user_path = module.as_str(); + let crate_name = self.tcx.crate_name(LOCAL_CRATE); + let crate_name = crate_name.as_str(); - let user_path = self.field(attr, sym::module).to_string(); - let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string(); + if !user_path.starts_with(&crate_name) { + self.tcx.dcx().emit_fatal(errors::MalformedCguName { span, user_path, crate_name }); + } - if !user_path.starts_with(&crate_name) { - self.tcx.dcx().emit_fatal(errors::MalformedCguName { - span: attr.span(), - user_path, - crate_name, - }); - } + // Split of the "special suffix" if there is one. + let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') { + (&user_path[..index], Some(&user_path[index + 1..])) + } else { + (&user_path[..], None) + }; - // Split of the "special suffix" if there is one. - let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') { - (&user_path[..index], Some(&user_path[index + 1..])) - } else { - (&user_path[..], None) - }; + let mut iter = user_path.split('-'); - let mut iter = user_path.split('-'); + // Remove the crate name + assert_eq!(iter.next().unwrap(), crate_name); - // Remove the crate name - assert_eq!(iter.next().unwrap(), crate_name); + let cgu_path_components = iter.collect::>(); - let cgu_path_components = iter.collect::>(); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); + let cgu_name = cgu_name_builder.build_cgu_name( + LOCAL_CRATE, + cgu_path_components, + cgu_special_suffix, + ); - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); - let cgu_name = - cgu_name_builder.build_cgu_name(LOCAL_CRATE, cgu_path_components, cgu_special_suffix); + debug!("mapping '{user_path}' to cgu name '{cgu_name}'"); - debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); + if !self.available_cgus.contains(&cgu_name) { + let cgu_names: Vec<&str> = + self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord(); + self.tcx.dcx().emit_err(errors::NoModuleNamed { + span, + user_path, + cgu_name, + cgu_names: cgu_names.join(", "), + }); + } - if !self.available_cgus.contains(&cgu_name) { - let cgu_names: Vec<&str> = - self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord(); - self.tcx.dcx().emit_err(errors::NoModuleNamed { - span: attr.span(), - user_path, + self.cgu_reuse_tracker.set_expectation( cgu_name, - cgu_names: cgu_names.join(", "), - }); + user_path, + span, + expected_reuse, + comp_kind, + ); } - - self.cgu_reuse_tracker.set_expectation( - cgu_name, - user_path, - attr.span(), - expected_reuse, - comp_kind, - ); - } - - fn field(&self, attr: &hir::Attribute, name: Symbol) -> Symbol { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(name) { - if let Some(value) = item.value_str() { - return value; - } else { - self.tcx.dcx().emit_fatal(errors::FieldAssociatedValueExpected { - span: item.span(), - name, - }); - } - } - } - - self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span(), name }); } /// Scan for a `cfg="foo"` attribute and check whether we have a /// cfg flag called `foo`. - fn check_config(&self, attr: &hir::Attribute) -> bool { + fn check_config(&self, value: Symbol) -> bool { let config = &self.tcx.sess.psess.config; - let value = self.field(attr, sym::cfg); debug!("check_config(config={:?}, value={:?})", config, value); if config.iter().any(|&(name, _)| name == value) { debug!("check_config: matched"); diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 23808ade6c85..1b707a24066e 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use std::process::Command; use itertools::Itertools; +use rustc_errors::msg; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; pub(super) use rustc_target::spec::apple::OSVersion; @@ -10,7 +11,6 @@ use rustc_target::spec::{Arch, Env, Os, Target}; use tracing::debug; use crate::errors::{XcrunError, XcrunSdkPathWarning}; -use crate::fluent_generated as fluent; #[cfg(test)] mod tests; @@ -185,19 +185,19 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option { // FIXME(madsmtm): Make this a lint, to allow deny warnings to work. // (Or fix ). let mut diag = sess.dcx().create_warn(err); - diag.note(fluent::codegen_ssa_xcrun_about); + diag.note(msg!("the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file")); // Recognize common error cases, and give more Rust-specific error messages for those. if let Some(developer_dir) = xcode_select_developer_dir() { diag.arg("developer_dir", &developer_dir); - diag.note(fluent::codegen_ssa_xcrun_found_developer_dir); + diag.note(msg!("found active developer directory at \"{$developer_dir}\"")); if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") { if sdk_name != "MacOSX" { - diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient); + diag.help(msg!("when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode")); } } } else { - diag.help(fluent::codegen_ssa_xcrun_no_developer_dir); + diag.help(msg!("pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable")); } diag.emit(); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c8109db86e2f..acc1c0b9f0de 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -11,10 +11,11 @@ use std::{env, fmt, fs, io, mem, str}; use find_msvc_tools; use itertools::Itertools; +use object::{Object, ObjectSection, ObjectSymbol}; use regex::Regex; use rustc_arena::TypedArena; use rustc_attr_parsing::eval_config_entry; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; @@ -662,7 +663,7 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out } #[derive(LintDiagnostic)] -#[diag(codegen_ssa_linker_output)] +#[diag("{$inner}")] /// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just /// end up with inconsistent languages within the same diagnostic. struct LinkerOutput { @@ -2185,6 +2186,71 @@ fn add_rpath_args( } } +fn add_c_staticlib_symbols( + sess: &Session, + lib: &NativeLib, + out: &mut Vec<(String, SymbolExportKind)>, +) -> io::Result<()> { + let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess); + + let archive_map = unsafe { Mmap::map(File::open(&file_path)?)? }; + + let archive = object::read::archive::ArchiveFile::parse(&*archive_map) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + for member in archive.members() { + let member = member.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + let data = member + .data(&*archive_map) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + // clang LTO: raw LLVM bitcode + if data.starts_with(b"BC\xc0\xde") { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "LLVM bitcode object in C static library (LTO not supported)", + )); + } + + let object = object::File::parse(&*data) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + // gcc / clang ELF / Mach-O LTO + if object.sections().any(|s| { + s.name().map(|n| n.starts_with(".gnu.lto_") || n == ".llvm.lto").unwrap_or(false) + }) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "LTO object in C static library is not supported", + )); + } + + for symbol in object.symbols() { + if symbol.scope() != object::SymbolScope::Dynamic { + continue; + } + + let name = match symbol.name() { + Ok(n) => n, + Err(_) => continue, + }; + + let export_kind = match symbol.kind() { + object::SymbolKind::Text => SymbolExportKind::Text, + object::SymbolKind::Data => SymbolExportKind::Data, + _ => continue, + }; + + // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple. + // Need to be resolved. + out.push((name.to_string(), export_kind)); + } + } + + Ok(()) +} + /// Produce the linker command line containing linker path and arguments. /// /// When comments in the function say "order-(in)dependent" they mean order-dependence between @@ -2217,6 +2283,25 @@ fn linker_with_args( ); let link_output_kind = link_output_kind(sess, crate_type); + let mut export_symbols = codegen_results.crate_info.exported_symbols[&crate_type].clone(); + + if crate_type == CrateType::Cdylib { + let mut seen = FxHashSet::default(); + + for lib in &codegen_results.crate_info.used_libraries { + if let NativeLibKind::Static { export_symbols: Some(true), .. } = lib.kind + && seen.insert((lib.name, lib.verbatim)) + { + if let Err(err) = add_c_staticlib_symbols(&sess, lib, &mut export_symbols) { + sess.dcx().fatal(format!( + "failed to process C static library `{}`: {}", + lib.name, err + )); + } + } + } + } + // ------------ Early order-dependent options ------------ // If we're building something like a dynamic library then some platforms @@ -2224,11 +2309,7 @@ fn linker_with_args( // dynamic library. // Must be passed before any libraries to prevent the symbols to export from being thrown away, // at least on some platforms (e.g. windows-gnu). - cmd.export_symbols( - tmpdir, - crate_type, - &codegen_results.crate_info.exported_symbols[&crate_type], - ); + cmd.export_symbols(tmpdir, crate_type, &export_symbols); // Can be used for adding custom CRT objects or overriding order-dependent options above. // FIXME: In practice built-in target specs use this for arbitrary order-independent options, @@ -2678,7 +2759,7 @@ fn add_native_libs_from_crate( let name = lib.name.as_str(); let verbatim = lib.verbatim; match lib.kind { - NativeLibKind::Static { bundle, whole_archive } => { + NativeLibKind::Static { bundle, whole_archive, .. } => { if link_static { let bundle = bundle.unwrap_or(true); let whole_archive = whole_archive == Some(true); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index db49f92e39ac..10c4eedb58e8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -2,7 +2,7 @@ use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; use std::path::{Path, PathBuf}; -use std::{env, io, iter, mem, str}; +use std::{env, iter, mem, str}; use find_msvc_tools; use rustc_hir::attrs::WindowsSubsystemKind; @@ -809,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> { if self.sess.target.is_like_darwin { // Write a plain, newline-separated list of symbols - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; for (sym, _) in symbols { debug!(" _{sym}"); @@ -821,7 +821,7 @@ impl<'a> Linker for GccLinker<'a> { } self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_windows { - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // .def file similar to MSVC one but without LIBRARY section @@ -845,7 +845,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("--export").link_arg(sym); } } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris { - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; writeln!(f, "{{")?; for (sym, _) in symbols { @@ -860,7 +860,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("--dynamic-list").link_arg(path); } else { // Write an LD version script - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; writeln!(f, "{{")?; if !symbols.is_empty() { @@ -1139,7 +1139,7 @@ impl<'a> Linker for MsvcLinker<'a> { } let path = tmpdir.join("lib.def"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // Start off with the standard module name header and then go @@ -1735,7 +1735,7 @@ impl<'a> Linker for AixLinker<'a> { symbols: &[(String, SymbolExportKind)], ) { let path = tmpdir.join("list.exp"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // FIXME: use llvm-nm to generate export list. for (symbol, _) in symbols { @@ -2135,7 +2135,7 @@ impl<'a> Linker for BpfLinker<'a> { symbols: &[(String, SymbolExportKind)], ) { let path = tmpdir.join("symbols"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; for (sym, _) in symbols { writeln!(f, "{sym}")?; diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index e3cf28acfa53..80b3b5a4d7c0 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -127,10 +127,7 @@ pub(super) fn exported_symbols_for_lto( symbols_below_threshold } -pub(super) fn check_lto_allowed( - cgcx: &CodegenContext, - dcx: DiagCtxtHandle<'_>, -) { +pub(super) fn check_lto_allowed(cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>) { if cgcx.lto == Lto::ThinLocal { // Crate local LTO is always allowed return; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index c6e945691921..557b00b911aa 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -14,6 +14,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::config::CrateType; +use rustc_span::Span; use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{Arch, Os, TlsModel}; use tracing::debug; @@ -764,3 +765,43 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap { ret } + +pub fn escape_symbol_name(tcx: TyCtxt<'_>, symbol: &str, span: Span) -> String { + // https://github.com/llvm/llvm-project/blob/a55fbab0cffc9b4af497b9e4f187b61143743e06/llvm/lib/MC/MCSymbol.cpp + use rustc_target::spec::{Arch, BinaryFormat}; + if !symbol.is_empty() + && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) + { + return symbol.to_string(); + } + if tcx.sess.target.binary_format == BinaryFormat::Xcoff { + tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the binary format {}", + tcx.sess.target.binary_format + ), + ); + } + if tcx.sess.target.arch == Arch::Nvptx64 { + tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the architecture {}", + tcx.sess.target.arch + ), + ); + } + let mut escaped_symbol = String::new(); + escaped_symbol.push('\"'); + for c in symbol.chars() { + match c { + '\n' => escaped_symbol.push_str("\\\n"), + '"' => escaped_symbol.push_str("\\\""), + '\\' => escaped_symbol.push_str("\\\\"), + c => escaped_symbol.push(c), + } + } + escaped_symbol.push('\"'); + escaped_symbol +} diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 8321f7fde503..87a043fbdf24 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -23,13 +23,15 @@ use rustc_hir::find_attr; use rustc_incremental::{ copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; +use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::bug; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{ - self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath, + self, CrateType, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes, + SwitchWithOptPath, }; use rustc_span::source_map::SourceMap; use rustc_span::{FileName, InnerSpan, Span, SpanData}; @@ -49,7 +51,7 @@ use crate::{ const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; /// What kind of object file to emit. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable)] pub enum EmitObj { // No object file. None, @@ -63,7 +65,7 @@ pub enum EmitObj { } /// What kind of llvm bitcode section to embed in an object file. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable)] pub enum BitcodeSection { // No bitcode section. None, @@ -73,6 +75,7 @@ pub enum BitcodeSection { } /// Module-specific configuration for `optimize_and_codegen`. +#[derive(Encodable, Decodable)] pub struct ModuleConfig { /// Names of additional optimization passes to run. pub passes: Vec, @@ -287,10 +290,7 @@ pub struct TargetMachineFactoryConfig { } impl TargetMachineFactoryConfig { - pub fn new( - cgcx: &CodegenContext, - module_name: &str, - ) -> TargetMachineFactoryConfig { + pub fn new(cgcx: &CodegenContext, module_name: &str) -> TargetMachineFactoryConfig { let split_dwarf_file = if cgcx.target_can_use_split_dwarf { cgcx.output_filenames.split_dwarf_path( cgcx.split_debuginfo, @@ -313,19 +313,17 @@ impl TargetMachineFactoryConfig { pub type TargetMachineFactoryFn = Arc< dyn Fn( + DiagCtxtHandle<'_>, TargetMachineFactoryConfig, - ) -> Result< - ::TargetMachine, - ::TargetMachineError, - > + Send + ) -> ::TargetMachine + + Send + Sync, >; /// Additional resources used by optimize_and_codegen (not module specific) -#[derive(Clone)] -pub struct CodegenContext { +#[derive(Clone, Encodable, Decodable)] +pub struct CodegenContext { // Resources needed when running LTO - pub prof: SelfProfilerRef, pub lto: Lto, pub use_linker_plugin_lto: bool, pub dylib_lto: bool, @@ -337,7 +335,8 @@ pub struct CodegenContext { pub output_filenames: Arc, pub invocation_temp: Option, pub module_config: Arc, - pub tm_factory: TargetMachineFactoryFn, + pub opt_level: OptLevel, + pub backend_features: Vec, pub msvc_imps_needed: bool, pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, @@ -364,17 +363,19 @@ pub struct CodegenContext { } fn generate_thin_lto_work( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], needs_thin_lto: Vec<(String, B::ThinBuffer)>, import_only_modules: Vec<(SerializedModule, WorkProduct)>, ) -> Vec<(ThinLtoWorkItem, u64)> { - let _prof_timer = cgcx.prof.generic_activity("codegen_thin_generate_lto_work"); + let _prof_timer = prof.generic_activity("codegen_thin_generate_lto_work"); let (lto_modules, copy_jobs) = B::run_thin_lto( cgcx, + prof, dcx, exported_symbols_for_lto, each_linked_rlib_for_lto, @@ -399,9 +400,9 @@ fn generate_thin_lto_work( .collect() } -struct CompiledModules { - modules: Vec, - allocator_module: Option, +pub struct CompiledModules { + pub modules: Vec, + pub allocator_module: Option, } enum MaybeLtoModules { @@ -410,7 +411,7 @@ enum MaybeLtoModules { allocator_module: Option, }, FatLto { - cgcx: CodegenContext, + cgcx: CodegenContext, exported_symbols_for_lto: Arc>, each_linked_rlib_file_for_lto: Vec, needs_fat_lto: Vec>, @@ -418,7 +419,7 @@ enum MaybeLtoModules { Vec<(SerializedModule<::ModuleBuffer>, WorkProduct)>, }, ThinLto { - cgcx: CodegenContext, + cgcx: CodegenContext, exported_symbols_for_lto: Arc>, each_linked_rlib_file_for_lto: Vec, needs_thin_lto: Vec<(String, ::ThinBuffer)>, @@ -534,7 +535,7 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( work_products } -fn produce_final_output_artifacts( +pub fn produce_final_output_artifacts( sess: &Session, compiled_modules: &CompiledModules, crate_output: &OutputFilenames, @@ -842,13 +843,14 @@ pub(crate) fn compute_per_cgu_lto_type( } fn execute_optimize_work_item( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, mut module: ModuleCodegen, ) -> WorkItemResult { - let _timer = cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*module.name); + let _timer = prof.generic_activity_with_arg("codegen_module_optimize", &*module.name); - B::optimize(cgcx, &shared_emitter, &mut module, &cgcx.module_config); + B::optimize(cgcx, prof, &shared_emitter, &mut module, &cgcx.module_config); // After we've done the initial round of optimizations we need to // decide whether to synchronously codegen this module or ship it @@ -869,7 +871,7 @@ fn execute_optimize_work_item( match lto_type { ComputedLtoType::No => { - let module = B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config); + let module = B::codegen(cgcx, &prof, &shared_emitter, module, &cgcx.module_config); WorkItemResult::Finished(module) } ComputedLtoType::Thin => { @@ -897,14 +899,14 @@ fn execute_optimize_work_item( } } -fn execute_copy_from_cache_work_item( - cgcx: &CodegenContext, +fn execute_copy_from_cache_work_item( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, module: CachedModuleCodegen, ) -> CompiledModule { - let _timer = cgcx - .prof - .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*module.name); + let _timer = + prof.generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*module.name); let dcx = DiagCtxt::new(Box::new(shared_emitter)); let dcx = dcx.handle(); @@ -986,14 +988,16 @@ fn execute_copy_from_cache_work_item( } fn do_fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, + tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], mut needs_fat_lto: Vec>, import_only_modules: Vec<(SerializedModule, WorkProduct)>, ) -> CompiledModule { - let _timer = cgcx.prof.verbose_generic_activity("LLVM_fatlto"); + let _timer = prof.verbose_generic_activity("LLVM_fatlto"); let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -1006,17 +1010,21 @@ fn do_fat_lto( let module = B::run_and_optimize_fat_lto( cgcx, + prof, &shared_emitter, + tm_factory, exported_symbols_for_lto, each_linked_rlib_for_lto, needs_fat_lto, ); - B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config) + B::codegen(cgcx, prof, &shared_emitter, module, &cgcx.module_config) } -fn do_thin_lto<'a, B: ExtraBackendMethods>( - cgcx: &'a CodegenContext, +fn do_thin_lto( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, + tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: Arc>, each_linked_rlib_for_lto: Vec, needs_thin_lto: Vec<(String, ::ThinBuffer)>, @@ -1025,7 +1033,7 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( WorkProduct, )>, ) -> Vec { - let _timer = cgcx.prof.verbose_generic_activity("LLVM_thinlto"); + let _timer = prof.verbose_generic_activity("LLVM_thinlto"); let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -1053,8 +1061,9 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( // bunch of work items onto our queue to do LTO. This all // happens on the coordinator thread but it's very quick so // we don't worry about tokens. - for (work, cost) in generate_thin_lto_work( + for (work, cost) in generate_thin_lto_work::( cgcx, + prof, dcx, &exported_symbols_for_lto, &each_linked_rlib_for_lto, @@ -1097,7 +1106,14 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( while used_token_count < tokens.len() + 1 && let Some((item, _)) = work_items.pop() { - spawn_thin_lto_work(&cgcx, shared_emitter.clone(), coordinator_send.clone(), item); + spawn_thin_lto_work( + &cgcx, + prof, + shared_emitter.clone(), + Arc::clone(&tm_factory), + coordinator_send.clone(), + item, + ); used_token_count += 1; } } else { @@ -1158,14 +1174,16 @@ fn do_thin_lto<'a, B: ExtraBackendMethods>( } fn execute_thin_lto_work_item( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, + tm_factory: TargetMachineFactoryFn, module: lto::ThinModule, ) -> CompiledModule { - let _timer = cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", module.name()); + let _timer = prof.generic_activity_with_arg("codegen_module_perform_lto", module.name()); - let module = B::optimize_thin(cgcx, &shared_emitter, module); - B::codegen(cgcx, &shared_emitter, module, &cgcx.module_config) + let module = B::optimize_thin(cgcx, prof, &shared_emitter, tm_factory, module); + B::codegen(cgcx, prof, &shared_emitter, module, &cgcx.module_config) } /// Messages sent to the coordinator. @@ -1265,6 +1283,7 @@ fn start_executing_work( coordinator_send: Sender>, ) -> thread::JoinHandle, ()>> { let sess = tcx.sess; + let prof = sess.prof.clone(); let mut each_linked_rlib_for_lto = Vec::new(); let mut each_linked_rlib_file_for_lto = Vec::new(); @@ -1292,8 +1311,9 @@ fn start_executing_work( }) .expect("failed to spawn helper thread"); - let ol = tcx.backend_optimization_level(()); - let backend_features = tcx.global_backend_features(()); + let opt_level = tcx.backend_optimization_level(()); + let backend_features = tcx.global_backend_features(()).clone(); + let tm_factory = backend.target_machine_factory(tcx.sess, opt_level, &backend_features); let remark_dir = if let Some(ref dir) = sess.opts.unstable_opts.remark_dir { let result = fs::create_dir_all(dir).and_then(|_| dir.canonicalize()); @@ -1305,7 +1325,7 @@ fn start_executing_work( None }; - let cgcx = CodegenContext:: { + let cgcx = CodegenContext { crate_types: tcx.crate_types().to_vec(), lto: sess.lto(), use_linker_plugin_lto: sess.opts.cg.linker_plugin_lto.enabled(), @@ -1314,13 +1334,13 @@ fn start_executing_work( fewer_names: sess.fewer_names(), save_temps: sess.opts.cg.save_temps, time_trace: sess.opts.unstable_opts.llvm_time_trace, - prof: sess.prof.clone(), remark: sess.opts.cg.remark.clone(), remark_dir, incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), output_filenames: Arc::clone(tcx.output_filenames(())), module_config: regular_config, - tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features), + opt_level, + backend_features, msvc_imps_needed: msvc_imps_needed(tcx), is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), @@ -1514,7 +1534,7 @@ fn start_executing_work( let mut llvm_start_time: Option> = None; if let Some(allocator_module) = &mut allocator_module { - B::optimize(&cgcx, &shared_emitter, allocator_module, &allocator_config); + B::optimize(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config); } // Run the message loop while there's still anything that needs message @@ -1554,6 +1574,7 @@ fn start_executing_work( main_thread_state = MainThreadState::Lending; spawn_work( &cgcx, + &prof, shared_emitter.clone(), coordinator_send.clone(), &mut llvm_start_time, @@ -1578,6 +1599,7 @@ fn start_executing_work( main_thread_state = MainThreadState::Lending; spawn_work( &cgcx, + &prof, shared_emitter.clone(), coordinator_send.clone(), &mut llvm_start_time, @@ -1620,6 +1642,7 @@ fn start_executing_work( { spawn_work( &cgcx, + &prof, shared_emitter.clone(), coordinator_send.clone(), &mut llvm_start_time, @@ -1776,9 +1799,11 @@ fn start_executing_work( assert!(needs_fat_lto.is_empty()); if cgcx.lto == Lto::ThinLocal { - compiled_modules.extend(do_thin_lto( + compiled_modules.extend(do_thin_lto::( &cgcx, + &prof, shared_emitter.clone(), + tm_factory, exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, @@ -1803,7 +1828,7 @@ fn start_executing_work( Ok(MaybeLtoModules::NoLto { modules: compiled_modules, allocator_module: allocator_module.map(|allocator_module| { - B::codegen(&cgcx, &shared_emitter, allocator_module, &allocator_config) + B::codegen(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config) }), }) }) @@ -1872,23 +1897,25 @@ fn start_executing_work( pub(crate) struct WorkerFatalError; fn spawn_work<'a, B: ExtraBackendMethods>( - cgcx: &'a CodegenContext, + cgcx: &CodegenContext, + prof: &'a SelfProfilerRef, shared_emitter: SharedEmitter, coordinator_send: Sender>, llvm_start_time: &mut Option>, work: WorkItem, ) { if llvm_start_time.is_none() { - *llvm_start_time = Some(cgcx.prof.verbose_generic_activity("LLVM_passes")); + *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes")); } let cgcx = cgcx.clone(); + let prof = prof.clone(); B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { - WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, shared_emitter, m), + WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, &prof, shared_emitter, m), WorkItem::CopyPostLtoArtifacts(m) => WorkItemResult::Finished( - execute_copy_from_cache_work_item(&cgcx, shared_emitter, m), + execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m), ), })); @@ -1909,20 +1936,25 @@ fn spawn_work<'a, B: ExtraBackendMethods>( .expect("failed to spawn work thread"); } -fn spawn_thin_lto_work<'a, B: ExtraBackendMethods>( - cgcx: &'a CodegenContext, +fn spawn_thin_lto_work( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: SharedEmitter, + tm_factory: TargetMachineFactoryFn, coordinator_send: Sender, work: ThinLtoWorkItem, ) { let cgcx = cgcx.clone(); + let prof = prof.clone(); B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { ThinLtoWorkItem::CopyPostLtoArtifacts(m) => { - execute_copy_from_cache_work_item(&cgcx, shared_emitter, m) + execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m) + } + ThinLtoWorkItem::ThinLto(m) => { + execute_thin_lto_work_item(&cgcx, &prof, shared_emitter, tm_factory, m) } - ThinLtoWorkItem::ThinLto(m) => execute_thin_lto_work_item(&cgcx, shared_emitter, m), })); let msg = match result { @@ -1981,11 +2013,7 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic( - &mut self, - mut diag: rustc_errors::DiagInner, - _registry: &rustc_errors::registry::Registry, - ) { + fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) { // Check that we aren't missing anything interesting when converting to // the cut-down local `DiagInner`. assert!(!diag.span.has_span_labels()); @@ -2163,34 +2191,54 @@ impl OngoingCodegen { each_linked_rlib_file_for_lto, needs_fat_lto, lto_import_only_modules, - } => CompiledModules { - modules: vec![do_fat_lto( - &cgcx, - shared_emitter, - &exported_symbols_for_lto, - &each_linked_rlib_file_for_lto, - needs_fat_lto, - lto_import_only_modules, - )], - allocator_module: None, - }, + } => { + let tm_factory = self.backend.target_machine_factory( + sess, + cgcx.opt_level, + &cgcx.backend_features, + ); + + CompiledModules { + modules: vec![do_fat_lto( + &cgcx, + &sess.prof, + shared_emitter, + tm_factory, + &exported_symbols_for_lto, + &each_linked_rlib_file_for_lto, + needs_fat_lto, + lto_import_only_modules, + )], + allocator_module: None, + } + } MaybeLtoModules::ThinLto { cgcx, exported_symbols_for_lto, each_linked_rlib_file_for_lto, needs_thin_lto, lto_import_only_modules, - } => CompiledModules { - modules: do_thin_lto( - &cgcx, - shared_emitter, - exported_symbols_for_lto, - each_linked_rlib_file_for_lto, - needs_thin_lto, - lto_import_only_modules, - ), - allocator_module: None, - }, + } => { + let tm_factory = self.backend.target_machine_factory( + sess, + cgcx.opt_level, + &cgcx.backend_features, + ); + + CompiledModules { + modules: do_thin_lto::( + &cgcx, + &sess.prof, + shared_emitter, + tm_factory, + exported_symbols_for_lto, + each_linked_rlib_file_for_lto, + needs_thin_lto, + lto_import_only_modules, + ), + allocator_module: None, + } + } }); shared_emitter_main.check(sess, true); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 43767dff92bf..85c8890d661c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1111,7 +1111,7 @@ pub fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> // know that later). If we are not doing LTO, there is only one optimized // version of each module, so we re-use that. let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph.assert_dep_node_not_yet_allocated_in_current_session(&dep_node, || { + tcx.dep_graph.assert_dep_node_not_yet_allocated_in_current_session(tcx.sess, &dep_node, || { format!( "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.", cgu.name() diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4cb390e7d569..edd73f418036 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -8,7 +8,7 @@ use rustc_hir::attrs::{ }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; +use rustc_hir::{self as hir, Attribute, find_attr}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, }; @@ -189,7 +189,7 @@ fn process_builtin_attrs( }, AttributeKind::FfiConst(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, - AttributeKind::StdInternalSymbol(_) => { + AttributeKind::RustcStdInternalSymbol(_) => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } AttributeKind::Linkage(linkage, span) => { @@ -217,10 +217,10 @@ fn process_builtin_attrs( AttributeKind::Sanitize { span, .. } => { interesting_spans.sanitize = Some(*span); } - AttributeKind::ObjcClass { classname, .. } => { + AttributeKind::RustcObjcClass { classname, .. } => { codegen_fn_attrs.objc_class = Some(*classname); } - AttributeKind::ObjcSelector { methname, .. } => { + AttributeKind::RustcObjcSelector { methname, .. } => { codegen_fn_attrs.objc_selector = Some(*methname); } AttributeKind::EiiForeignItem => { @@ -504,7 +504,7 @@ fn handle_lang_items( attrs: &[Attribute], codegen_fn_attrs: &mut CodegenFnAttrs, ) { - let lang_item = lang_items::extract(attrs).and_then(|(name, _)| LangItem::from_name(name)); + let lang_item = find_attr!(attrs, AttributeKind::Lang(lang, _) => lang); // Weak lang items have the same semantics as "std internal" symbols in the // sense that they're preserved through all our LTO passes and only diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 6a97de4c2b13..74f7829ace95 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -8,7 +8,7 @@ use std::process::ExitStatus; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, + Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::layout::LayoutError; @@ -17,10 +17,14 @@ use rustc_span::{Span, Symbol}; use crate::assert_module_sources::CguReuse; use crate::back::command::Command; -use crate::fluent_generated as fluent; #[derive(Diagnostic)] -#[diag(codegen_ssa_incorrect_cgu_reuse_type)] +#[diag( + "CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> + [one] {\"at least \"} + *[other] {\"\"} + }`{$expected_reuse}`" +)] pub(crate) struct IncorrectCguReuseType<'a> { #[primary_span] pub span: Span, @@ -31,38 +35,32 @@ pub(crate) struct IncorrectCguReuseType<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_cgu_not_recorded)] +#[diag("CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded")] pub(crate) struct CguNotRecorded<'a> { pub cgu_user_name: &'a str, pub cgu_name: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_reuse_kind)] -pub(crate) struct UnknownReuseKind { - #[primary_span] - pub span: Span, - pub kind: Symbol, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_missing_query_depgraph)] +#[diag("found CGU-reuse attribute but `-Zquery-dep-graph` was not specified")] pub(crate) struct MissingQueryDepGraph { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_malformed_cgu_name)] -pub(crate) struct MalformedCguName { +#[diag( + "found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case)" +)] +pub(crate) struct MalformedCguName<'a> { #[primary_span] pub span: Span, - pub user_path: String, - pub crate_name: String, + pub user_path: &'a str, + pub crate_name: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_no_module_named)] +#[diag("no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}")] pub(crate) struct NoModuleNamed<'a> { #[primary_span] pub span: Span, @@ -72,72 +70,56 @@ pub(crate) struct NoModuleNamed<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_field_associated_value_expected)] -pub(crate) struct FieldAssociatedValueExpected { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_no_field)] -pub(crate) struct NoField { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_lib_def_write_failure)] +#[diag("failed to write lib.def file: {$error}")] pub(crate) struct LibDefWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_version_script_write_failure)] +#[diag("failed to write version script: {$error}")] pub(crate) struct VersionScriptWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_symbol_file_write_failure)] +#[diag("failed to write symbols file: {$error}")] pub(crate) struct SymbolFileWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ld64_unimplemented_modifier)] +#[diag("`as-needed` modifier not implemented yet for ld64")] pub(crate) struct Ld64UnimplementedModifier; #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_unsupported_modifier)] +#[diag("`as-needed` modifier not supported for current linker")] pub(crate) struct LinkerUnsupportedModifier; #[derive(Diagnostic)] -#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)] +#[diag("exporting symbols not implemented yet for L4Bender")] pub(crate) struct L4BenderExportingSymbolsUnimplemented; #[derive(Diagnostic)] -#[diag(codegen_ssa_no_natvis_directory)] +#[diag("error enumerating natvis directory: {$error}")] pub(crate) struct NoNatvisDirectory { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_no_saved_object_file)] +#[diag("cached cgu {$cgu_name} should have an object file, but doesn't")] pub(crate) struct NoSavedObjectFile<'a> { pub cgu_name: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_requires_rust_abi, code = E0737)] +#[diag("`#[track_caller]` requires Rust ABI", code = E0737)] pub(crate) struct RequiresRustAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_copy_path_buf)] +#[diag("unable to copy {$source_file} to {$output_path}: {$error}")] pub(crate) struct CopyPathBuf { pub source_file: PathBuf, pub output_path: PathBuf, @@ -146,15 +128,15 @@ pub(crate) struct CopyPathBuf { // Reports Paths using `Debug` implementation rather than Path's `Display` implementation. #[derive(Diagnostic)] -#[diag(codegen_ssa_copy_path)] -pub struct CopyPath<'a> { +#[diag("could not copy {$from} to {$to}: {$error}")] +pub(crate) struct CopyPath<'a> { from: DebugArgPath<'a>, to: DebugArgPath<'a>, error: Error, } impl<'a> CopyPath<'a> { - pub fn new(from: &'a Path, to: &'a Path, error: Error) -> CopyPath<'a> { + pub(crate) fn new(from: &'a Path, to: &'a Path, error: Error) -> CopyPath<'a> { CopyPath { from: DebugArgPath(from), to: DebugArgPath(to), error } } } @@ -168,38 +150,42 @@ impl IntoDiagArg for DebugArgPath<'_> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_binary_output_to_tty)] -pub struct BinaryOutputToTty { +#[diag( + "option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty" +)] +pub(crate) struct BinaryOutputToTty { pub shorthand: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ignoring_emit_path)] -pub struct IgnoringEmitPath { +#[diag("ignoring emit path because multiple .{$extension} files were produced")] +pub(crate) struct IgnoringEmitPath { pub extension: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ignoring_output)] -pub struct IgnoringOutput { +#[diag("ignoring -o because multiple .{$extension} files were produced")] +pub(crate) struct IgnoringOutput { pub extension: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_create_temp_dir)] +#[diag("couldn't create a temp dir: {$error}")] pub(crate) struct CreateTempDir { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_add_native_library)] +#[diag("failed to add native library {$library_path}: {$error}")] pub(crate) struct AddNativeLibrary { pub library_path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_multiple_external_func_decl)] +#[diag( + "multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions" +)] pub(crate) struct MultipleExternalFuncDecl<'a> { #[primary_span] pub span: Span, @@ -209,16 +195,18 @@ pub(crate) struct MultipleExternalFuncDecl<'a> { #[derive(Diagnostic)] pub enum LinkRlibError { - #[diag(codegen_ssa_rlib_missing_format)] + #[diag("could not find formats for rlibs")] MissingFormat, - #[diag(codegen_ssa_rlib_only_rmeta_found)] + #[diag("could not find rlib for: `{$crate_name}`, found rmeta (metadata) file")] OnlyRmetaFound { crate_name: Symbol }, - #[diag(codegen_ssa_rlib_not_found)] + #[diag("could not find rlib for: `{$crate_name}`")] NotFound { crate_name: Symbol }, - #[diag(codegen_ssa_rlib_incompatible_dependency_formats)] + #[diag( + "`{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)" + )] IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String }, } @@ -228,122 +216,122 @@ impl Diagnostic<'_, G> for ThorinErrorWrapper { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let build = |msg| Diag::new(dcx, level, msg); match self.0 { - thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure), + thorin::Error::ReadInput(_) => build(msg!("failed to read input file")), thorin::Error::ParseFileKind(_) => { - build(fluent::codegen_ssa_thorin_parse_input_file_kind) + build(msg!("failed to parse input file kind")) } thorin::Error::ParseObjectFile(_) => { - build(fluent::codegen_ssa_thorin_parse_input_object_file) + build(msg!("failed to parse input object file")) } thorin::Error::ParseArchiveFile(_) => { - build(fluent::codegen_ssa_thorin_parse_input_archive_file) + build(msg!("failed to parse input archive file")) } thorin::Error::ParseArchiveMember(_) => { - build(fluent::codegen_ssa_thorin_parse_archive_member) + build(msg!("failed to parse archive member")) } - thorin::Error::InvalidInputKind => build(fluent::codegen_ssa_thorin_invalid_input_kind), - thorin::Error::DecompressData(_) => build(fluent::codegen_ssa_thorin_decompress_data), + thorin::Error::InvalidInputKind => build(msg!("input is not an archive or elf object")), + thorin::Error::DecompressData(_) => build(msg!("failed to decompress compressed section")), thorin::Error::NamelessSection(_, offset) => { - build(fluent::codegen_ssa_thorin_section_without_name) + build(msg!("section without name at offset {$offset}")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol) + build(msg!("relocation with invalid symbol for section `{$section}` at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::MultipleRelocations(section, offset) => { - build(fluent::codegen_ssa_thorin_multiple_relocations) + build(msg!("multiple relocations for section `{$section}` at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::UnsupportedRelocation(section, offset) => { - build(fluent::codegen_ssa_thorin_unsupported_relocation) + build(msg!("unsupported relocation for section {$section} at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } - thorin::Error::MissingDwoName(id) => build(fluent::codegen_ssa_thorin_missing_dwo_name) + thorin::Error::MissingDwoName(id) => build(msg!("missing path attribute to DWARF object ({$id})")) .with_arg("id", format!("0x{id:08x}")), thorin::Error::NoCompilationUnits => { - build(fluent::codegen_ssa_thorin_no_compilation_units) + build(msg!("input object has no compilation units")) } - thorin::Error::NoDie => build(fluent::codegen_ssa_thorin_no_die), + thorin::Error::NoDie => build(msg!("no top-level debugging information entry in compilation/type unit")), thorin::Error::TopLevelDieNotUnit => { - build(fluent::codegen_ssa_thorin_top_level_die_not_unit) + build(msg!("top-level debugging information entry is not a compilation/type unit")) } thorin::Error::MissingRequiredSection(section) => { - build(fluent::codegen_ssa_thorin_missing_required_section) + build(msg!("input object missing required section `{$section}`")) .with_arg("section", section) } thorin::Error::ParseUnitAbbreviations(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_abbreviations) + build(msg!("failed to parse unit abbreviations")) } thorin::Error::ParseUnitAttribute(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_attribute) + build(msg!("failed to parse unit attribute")) } thorin::Error::ParseUnitHeader(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_header) + build(msg!("failed to parse unit header")) } - thorin::Error::ParseUnit(_) => build(fluent::codegen_ssa_thorin_parse_unit), + thorin::Error::ParseUnit(_) => build(msg!("failed to parse unit")), thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - build(fluent::codegen_ssa_thorin_incompatible_index_version) + build(msg!("incompatible `{$section}` index version: found version {$actual}, expected version {$format}")) .with_arg("section", section) .with_arg("actual", actual) .with_arg("format", format) } thorin::Error::OffsetAtIndex(_, index) => { - build(fluent::codegen_ssa_thorin_offset_at_index).with_arg("index", index) + build(msg!("read offset at index {$index} of `.debug_str_offsets.dwo` section")).with_arg("index", index) } thorin::Error::StrAtOffset(_, offset) => { - build(fluent::codegen_ssa_thorin_str_at_offset) + build(msg!("read string at offset {$offset} of `.debug_str.dwo` section")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::ParseIndex(_, section) => { - build(fluent::codegen_ssa_thorin_parse_index).with_arg("section", section) + build(msg!("failed to parse `{$section}` index section")).with_arg("section", section) } thorin::Error::UnitNotInIndex(unit) => { - build(fluent::codegen_ssa_thorin_unit_not_in_index) + build(msg!("unit {$unit} from input package is not in its index")) .with_arg("unit", format!("0x{unit:08x}")) } thorin::Error::RowNotInIndex(_, row) => { - build(fluent::codegen_ssa_thorin_row_not_in_index).with_arg("row", row) + build(msg!("row {$row} found in index's hash table not present in index")).with_arg("row", row) } - thorin::Error::SectionNotInRow => build(fluent::codegen_ssa_thorin_section_not_in_row), - thorin::Error::EmptyUnit(unit) => build(fluent::codegen_ssa_thorin_empty_unit) + thorin::Error::SectionNotInRow => build(msg!("section not found in unit's row in index")), + thorin::Error::EmptyUnit(unit) => build(msg!("unit {$unit} in input DWARF object with no data")) .with_arg("unit", format!("0x{unit:08x}")), thorin::Error::MultipleDebugInfoSection => { - build(fluent::codegen_ssa_thorin_multiple_debug_info_section) + build(msg!("multiple `.debug_info.dwo` sections")) } thorin::Error::MultipleDebugTypesSection => { - build(fluent::codegen_ssa_thorin_multiple_debug_types_section) + build(msg!("multiple `.debug_types.dwo` sections in a package")) } - thorin::Error::NotSplitUnit => build(fluent::codegen_ssa_thorin_not_split_unit), - thorin::Error::DuplicateUnit(unit) => build(fluent::codegen_ssa_thorin_duplicate_unit) + thorin::Error::NotSplitUnit => build(msg!("regular compilation unit in object (missing dwo identifier)")), + thorin::Error::DuplicateUnit(unit) => build(msg!("duplicate split compilation unit ({$unit})")) .with_arg("unit", format!("0x{unit:08x}")), thorin::Error::MissingReferencedUnit(unit) => { - build(fluent::codegen_ssa_thorin_missing_referenced_unit) + build(msg!("unit {$unit} referenced by executable was not found")) .with_arg("unit", format!("0x{unit:08x}")) } thorin::Error::NoOutputObjectCreated => { - build(fluent::codegen_ssa_thorin_not_output_object_created) + build(msg!("no output object was created from inputs")) } thorin::Error::MixedInputEncodings => { - build(fluent::codegen_ssa_thorin_mixed_input_encodings) + build(msg!("input objects have mixed encodings")) } thorin::Error::Io(e) => { - build(fluent::codegen_ssa_thorin_io).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectRead(e) => { - build(fluent::codegen_ssa_thorin_object_read).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectWrite(e) => { - build(fluent::codegen_ssa_thorin_object_write).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliRead(e) => { - build(fluent::codegen_ssa_thorin_gimli_read).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliWrite(e) => { - build(fluent::codegen_ssa_thorin_gimli_write).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } _ => unimplemented!("Untranslated thorin error"), } @@ -361,7 +349,8 @@ pub(crate) struct LinkingFailed<'a> { impl Diagnostic<'_, G> for LinkingFailed<'_> { fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_linking_failed); + let mut diag = + Diag::new(dcx, level, msg!("linking with `{$linker_path}` failed: {$exit_status}")); diag.arg("linker_path", format!("{}", self.linker_path.display())); diag.arg("exit_status", format!("{}", self.exit_status)); @@ -470,11 +459,11 @@ impl Diagnostic<'_, G> for LinkingFailed<'_> { // Trying to match an error from OS linkers // which by now we have no way to translate. if contains_undefined_ref { - diag.note(fluent::codegen_ssa_extern_funcs_not_found) - .note(fluent::codegen_ssa_specify_libraries_to_link); + diag.note(msg!("some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified")) + .note(msg!("use the `-l` flag to specify native libraries to link")); if rustc_session::utils::was_invoked_from_cargo() { - diag.note(fluent::codegen_ssa_use_cargo_directive); + diag.note(msg!("use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)")); } } diag @@ -482,49 +471,50 @@ impl Diagnostic<'_, G> for LinkingFailed<'_> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_link_exe_unexpected_error)] +#[diag("`link.exe` returned an unexpected error")] pub(crate) struct LinkExeUnexpectedError; pub(crate) struct LinkExeStatusStackBufferOverrun; impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun { fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = - Diag::new(dcx, level, fluent::codegen_ssa_link_exe_status_stack_buffer_overrun); - diag.note(fluent::codegen_ssa_abort_note); - diag.note(fluent::codegen_ssa_event_log_note); + let mut diag = Diag::new(dcx, level, msg!("0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`")); + diag.note(msg!( + "this may have been caused by a program abort and not a stack buffer overrun" + )); + diag.note(msg!("consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code")); diag } } #[derive(Diagnostic)] -#[diag(codegen_ssa_repair_vs_build_tools)] +#[diag("the Visual Studio build tools may need to be repaired using the Visual Studio installer")] pub(crate) struct RepairVSBuildTools; #[derive(Diagnostic)] -#[diag(codegen_ssa_missing_cpp_build_tool_component)] +#[diag("or a necessary component may be missing from the \"C++ build tools\" workload")] pub(crate) struct MissingCppBuildToolComponent; #[derive(Diagnostic)] -#[diag(codegen_ssa_select_cpp_build_tool_workload)] +#[diag("in the Visual Studio installer, ensure the \"C++ build tools\" workload is selected")] pub(crate) struct SelectCppBuildToolWorkload; #[derive(Diagnostic)] -#[diag(codegen_ssa_visual_studio_not_installed)] +#[diag("you may need to install Visual Studio build tools with the \"C++ build tools\" workload")] pub(crate) struct VisualStudioNotInstalled; #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_not_found)] -#[note] +#[diag("linker `{$linker_path}` not found")] +#[note("{$error}")] pub(crate) struct LinkerNotFound { pub linker_path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_exe_linker)] -#[note] -#[note(codegen_ssa_command_note)] +#[diag("could not exec the linker `{$linker_path}`")] +#[note("{$error}")] +#[note("{$command_formatted}")] pub(crate) struct UnableToExeLinker { pub linker_path: PathBuf, pub error: Error, @@ -532,42 +522,46 @@ pub(crate) struct UnableToExeLinker { } #[derive(Diagnostic)] -#[diag(codegen_ssa_msvc_missing_linker)] +#[diag("the msvc targets depend on the msvc linker but `link.exe` was not found")] pub(crate) struct MsvcMissingLinker; #[derive(Diagnostic)] -#[diag(codegen_ssa_self_contained_linker_missing)] +#[diag( + "the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot" +)] pub(crate) struct SelfContainedLinkerMissing; #[derive(Diagnostic)] -#[diag(codegen_ssa_check_installed_visual_studio)] +#[diag( + "please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option" +)] pub(crate) struct CheckInstalledVisualStudio; #[derive(Diagnostic)] -#[diag(codegen_ssa_insufficient_vs_code_product)] +#[diag("VS Code is a different product, and is not sufficient")] pub(crate) struct InsufficientVSCodeProduct; #[derive(Diagnostic)] -#[diag(codegen_ssa_cpu_required)] +#[diag("target requires explicitly specifying a cpu with `-C target-cpu`")] pub(crate) struct CpuRequired; #[derive(Diagnostic)] -#[diag(codegen_ssa_processing_dymutil_failed)] -#[note] +#[diag("processing debug info with `dsymutil` failed: {$status}")] +#[note("{$output}")] pub(crate) struct ProcessingDymutilFailed { pub status: ExitStatus, pub output: String, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_run_dsymutil)] +#[diag("unable to run `dsymutil`: {$error}")] pub(crate) struct UnableToRunDsymutil { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_stripping_debug_info_failed)] -#[note] +#[diag("stripping debug info with `{$util}` failed: {$status}")] +#[note("{$output}")] pub(crate) struct StrippingDebugInfoFailed<'a> { pub util: &'a str, pub status: ExitStatus, @@ -575,53 +569,57 @@ pub(crate) struct StrippingDebugInfoFailed<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_run)] +#[diag("unable to run `{$util}`: {$error}")] pub(crate) struct UnableToRun<'a> { pub util: &'a str, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_file_stem)] +#[diag("couldn't extract file stem from specified linker")] pub(crate) struct LinkerFileStem; #[derive(Diagnostic)] -#[diag(codegen_ssa_static_library_native_artifacts)] +#[diag( + "link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms" +)] pub(crate) struct StaticLibraryNativeArtifacts; #[derive(Diagnostic)] -#[diag(codegen_ssa_static_library_native_artifacts_to_file)] +#[diag( + "native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms" +)] pub(crate) struct StaticLibraryNativeArtifactsToFile<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(codegen_ssa_link_script_unavailable)] +#[diag("can only use link script when linking with GNU-like linker")] pub(crate) struct LinkScriptUnavailable; #[derive(Diagnostic)] -#[diag(codegen_ssa_link_script_write_failure)] +#[diag("failed to write link script to {$path}: {$error}")] pub(crate) struct LinkScriptWriteFailure { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_failed_to_write)] +#[diag("failed to write {$path}: {$error}")] pub(crate) struct FailedToWrite { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_write_debugger_visualizer)] +#[diag("unable to write debugger visualizer file `{$path}`: {$error}")] pub(crate) struct UnableToWriteDebuggerVisualizer { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_rlib_archive_build_failure)] +#[diag("failed to build archive from rlib at `{$path}`: {$error}")] pub(crate) struct RlibArchiveBuildFailure { pub path: PathBuf, pub error: Error, @@ -630,68 +628,70 @@ pub(crate) struct RlibArchiveBuildFailure { #[derive(Diagnostic)] // Public for ArchiveBuilderBuilder::extract_bundled_libs pub enum ExtractBundledLibsError<'a> { - #[diag(codegen_ssa_extract_bundled_libs_open_file)] + #[diag("failed to open file '{$rlib}': {$error}")] OpenFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_mmap_file)] + #[diag("failed to mmap file '{$rlib}': {$error}")] MmapFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_parse_archive)] + #[diag("failed to parse archive '{$rlib}': {$error}")] ParseArchive { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_read_entry)] + #[diag("failed to read entry '{$rlib}': {$error}")] ReadEntry { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_archive_member)] + #[diag("failed to get data from archive member '{$rlib}': {$error}")] ArchiveMember { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_convert_name)] + #[diag("failed to convert name '{$rlib}': {$error}")] ConvertName { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_write_file)] + #[diag("failed to write file '{$rlib}': {$error}")] WriteFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_write_file)] + #[diag("failed to write file '{$rlib}': {$error}")] ExtractSection { rlib: &'a Path, error: Box }, } #[derive(Diagnostic)] -#[diag(codegen_ssa_read_file)] +#[diag("failed to read file: {$message}")] pub(crate) struct ReadFileError { pub message: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_link_self_contained)] +#[diag("option `-C link-self-contained` is not supported on this target")] pub(crate) struct UnsupportedLinkSelfContained; #[derive(Diagnostic)] -#[diag(codegen_ssa_archive_build_failure)] +#[diag("failed to build archive at `{$path}`: {$error}")] pub(crate) struct ArchiveBuildFailure { pub path: PathBuf, pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_archive_kind)] +#[diag("don't know how to build archive of type: {$kind}")] pub(crate) struct UnknownArchiveKind<'a> { pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_bpf_staticlib_not_supported)] +#[diag("linking static libraries is not supported for BPF")] pub(crate) struct BpfStaticlibNotSupported; #[derive(Diagnostic)] -#[diag(codegen_ssa_multiple_main_functions)] -#[help] +#[diag("entry symbol `main` declared multiple times")] +#[help( + "did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point" +)] pub(crate) struct MultipleMainFunctions { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_shuffle_indices_evaluation)] +#[diag("could not evaluate shuffle_indices at compile time")] pub(crate) struct ShuffleIndicesEvaluation { #[primary_span] pub span: Span, @@ -699,7 +699,7 @@ pub(crate) struct ShuffleIndicesEvaluation { #[derive(Diagnostic)] pub enum InvalidMonomorphization<'tcx> { - #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`", code = E0511)] BasicIntegerType { #[primary_span] span: Span, @@ -707,7 +707,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}`", code = E0511)] BasicIntegerOrPtrType { #[primary_span] span: Span, @@ -715,7 +715,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`", code = E0511)] BasicFloatType { #[primary_span] span: Span, @@ -723,14 +723,14 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = E0511)] + #[diag("invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`", code = E0511)] FloatToIntUnchecked { #[primary_span] span: Span, ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`", code = E0511)] FloatingPointVector { #[primary_span] span: Span, @@ -739,7 +739,7 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type", code = E0511)] FloatingPointType { #[primary_span] span: Span, @@ -747,14 +747,14 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`", code = E0511)] UnrecognizedIntrinsic { #[primary_span] span: Span, name: Symbol, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`", code = E0511)] SimdArgument { #[primary_span] span: Span, @@ -762,7 +762,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`", code = E0511)] SimdInput { #[primary_span] span: Span, @@ -770,7 +770,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`", code = E0511)] SimdFirst { #[primary_span] span: Span, @@ -778,7 +778,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`", code = E0511)] SimdSecond { #[primary_span] span: Span, @@ -786,7 +786,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`", code = E0511)] SimdThird { #[primary_span] span: Span, @@ -794,7 +794,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`", code = E0511)] SimdReturn { #[primary_span] span: Span, @@ -802,7 +802,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`", code = E0511)] InvalidBitmask { #[primary_span] span: Span, @@ -812,7 +812,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}", code = E0511)] ReturnLengthInputType { #[primary_span] span: Span, @@ -823,7 +823,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}", code = E0511)] SecondArgumentLength { #[primary_span] span: Span, @@ -834,7 +834,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}", code = E0511)] ThirdArgumentLength { #[primary_span] span: Span, @@ -845,7 +845,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`", code = E0511)] ReturnIntegerType { #[primary_span] span: Span, @@ -854,7 +854,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `{$ty}`", code = E0511)] SimdShuffle { #[primary_span] span: Span, @@ -862,7 +862,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}", code = E0511)] ReturnLength { #[primary_span] span: Span, @@ -872,7 +872,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_element, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`", code = E0511)] ReturnElement { #[primary_span] span: Span, @@ -883,7 +883,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len})", code = E0511)] SimdIndexOutOfBounds { #[primary_span] span: Span, @@ -892,7 +892,7 @@ pub enum InvalidMonomorphization<'tcx> { total_len: u128, }, - #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`", code = E0511)] InsertedType { #[primary_span] span: Span, @@ -902,7 +902,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`", code = E0511)] ReturnType { #[primary_span] span: Span, @@ -912,7 +912,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`", code = E0511)] ExpectedReturnType { #[primary_span] span: Span, @@ -921,7 +921,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`", code = E0511)] MismatchedLengths { #[primary_span] span: Span, @@ -930,7 +930,7 @@ pub enum InvalidMonomorphization<'tcx> { v_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_mask_wrong_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected mask element type to be an integer, found `{$ty}`", code = E0511)] MaskWrongElementType { #[primary_span] span: Span, @@ -938,7 +938,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`", code = E0511)] CannotReturn { #[primary_span] span: Span, @@ -948,7 +948,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`", code = E0511)] ExpectedElementType { #[primary_span] span: Span, @@ -960,7 +960,7 @@ pub enum InvalidMonomorphization<'tcx> { mutability: ExpectedPointerMutability, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`", code = E0511)] UnsupportedSymbolOfSize { #[primary_span] span: Span, @@ -972,7 +972,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`", code = E0511)] UnsupportedSymbol { #[primary_span] span: Span, @@ -983,7 +983,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`", code = E0511)] CastWidePointer { #[primary_span] span: Span, @@ -991,7 +991,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`", code = E0511)] ExpectedPointer { #[primary_span] span: Span, @@ -999,7 +999,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`", code = E0511)] ExpectedUsize { #[primary_span] span: Span, @@ -1007,7 +1007,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`", code = E0511)] UnsupportedCast { #[primary_span] span: Span, @@ -1018,7 +1018,7 @@ pub enum InvalidMonomorphization<'tcx> { out_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`", code = E0511)] UnsupportedOperation { #[primary_span] span: Span, @@ -1027,7 +1027,7 @@ pub enum InvalidMonomorphization<'tcx> { in_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type", code = E0511)] ExpectedVectorElementType { #[primary_span] span: Span, @@ -1036,7 +1036,7 @@ pub enum InvalidMonomorphization<'tcx> { vector_type: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_non_scalable_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected non-scalable type, found scalable type `{$ty}`", code = E0511)] NonScalableType { #[primary_span] span: Span, @@ -1060,17 +1060,17 @@ impl IntoDiagArg for ExpectedPointerMutability { } #[derive(Diagnostic)] -#[diag(codegen_ssa_target_feature_safe_trait)] +#[diag("`#[target_feature(..)]` cannot be applied to safe trait method")] pub(crate) struct TargetFeatureSafeTrait { #[primary_span] - #[label] + #[label("cannot be applied to safe trait method")] pub span: Span, - #[label(codegen_ssa_label_def)] + #[label("not an `unsafe` function")] pub def: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_forbidden_target_feature_attr)] +#[diag("target feature `{$feature}` cannot be enabled with `#[target_feature]`: {$reason}")] pub struct ForbiddenTargetFeatureAttr<'a> { #[primary_span] pub span: Span, @@ -1079,7 +1079,7 @@ pub struct ForbiddenTargetFeatureAttr<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_failed_to_get_layout)] +#[diag("failed to get layout for {$ty}: {$err}")] pub struct FailedToGetLayout<'tcx> { #[primary_span] pub span: Span, @@ -1088,7 +1088,11 @@ pub struct FailedToGetLayout<'tcx> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_dlltool_fail_import_library)] +#[diag( + "dlltool could not create import library with {$dlltool_path} {$dlltool_args}: +{$stdout} +{$stderr}" +)] pub(crate) struct DlltoolFailImportLibrary<'a> { pub dlltool_path: Cow<'a, str>, pub dlltool_args: String, @@ -1097,26 +1101,28 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_writing_def_file)] +#[diag("error writing .DEF file: {$error}")] pub(crate) struct ErrorWritingDEFFile { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_calling_dlltool)] +#[diag("error calling dlltool '{$dlltool_path}': {$error}")] pub(crate) struct ErrorCallingDllTool<'a> { pub dlltool_path: Cow<'a, str>, pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_creating_remark_dir)] +#[diag("failed to create remark directory: {$error}")] pub(crate) struct ErrorCreatingRemarkDir { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_compiler_builtins_cannot_call)] +#[diag( + "`compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}`" +)] pub struct CompilerBuiltinsCannotCall { pub caller: String, pub callee: String, @@ -1125,23 +1131,23 @@ pub struct CompilerBuiltinsCannotCall { } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_creating_import_library)] +#[diag("error creating import library for {$lib_name}: {$error}")] pub(crate) struct ErrorCreatingImportLibrary<'a> { pub lib_name: &'a str, pub error: String, } #[derive(Diagnostic)] -#[diag(codegen_ssa_aix_strip_not_used)] +#[diag("using host's `strip` binary to cross-compile to AIX which is not guaranteed to work")] pub(crate) struct AixStripNotUsed; #[derive(Diagnostic, Debug)] pub(crate) enum XcrunError { - #[diag(codegen_ssa_xcrun_failed_invoking)] + #[diag("invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error}")] FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error }, - #[diag(codegen_ssa_xcrun_unsuccessful)] - #[note] + #[diag("failed running `{$command_formatted}` to find {$sdk_name}.sdk")] + #[note("{$stdout}{$stderr}")] Unsuccessful { sdk_name: &'static str, command_formatted: String, @@ -1151,35 +1157,37 @@ pub(crate) enum XcrunError { } #[derive(Diagnostic, Debug)] -#[diag(codegen_ssa_xcrun_sdk_path_warning)] -#[note] +#[diag("output of `xcrun` while finding {$sdk_name}.sdk")] +#[note("{$stderr}")] pub(crate) struct XcrunSdkPathWarning { pub sdk_name: &'static str, pub stderr: String, } #[derive(LintDiagnostic)] -#[diag(codegen_ssa_aarch64_softfloat_neon)] +#[diag("enabling the `neon` target feature on the current target is unsound due to ABI issues")] pub(crate) struct Aarch64SoftfloatNeon; #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_ctarget_feature_prefix)] -#[note] +#[diag("unknown feature specified for `-Ctarget-feature`: `{$feature}`")] +#[note("features must begin with a `+` to enable or `-` to disable it")] pub(crate) struct UnknownCTargetFeaturePrefix<'a> { pub feature: &'a str, } #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { - #[help(codegen_ssa_possible_feature)] + #[help("you might have meant: `{$rust_feature}`")] Some { rust_feature: &'a str }, - #[help(codegen_ssa_consider_filing_feature_request)] + #[help("consider filing a feature request")] None, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_ctarget_feature)] -#[note] +#[diag("unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`")] +#[note( + "it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future" +)] pub(crate) struct UnknownCTargetFeature<'a> { pub feature: &'a str, #[subdiagnostic] @@ -1187,16 +1195,18 @@ pub(crate) struct UnknownCTargetFeature<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_unstable_ctarget_feature)] -#[note] +#[diag("unstable feature specified for `-Ctarget-feature`: `{$feature}`")] +#[note("this feature is not stably supported; its behavior can change in the future")] pub(crate) struct UnstableCTargetFeature<'a> { pub feature: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_forbidden_ctarget_feature)] -#[note] -#[note(codegen_ssa_forbidden_ctarget_feature_issue)] +#[diag("target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}")] +#[note( + "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 #116344 ")] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, @@ -1210,12 +1220,16 @@ pub struct TargetFeatureDisableOrEnable<'a> { } #[derive(Subdiagnostic)] -#[help(codegen_ssa_missing_features)] +#[help("add the missing features in a `target_feature` attribute")] pub struct MissingFeatures; impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable); + let mut diag = Diag::new( + dcx, + level, + msg!("the target features {$features} must all be either enabled or disabled together"), + ); if let Some(span) = self.span { diag.span(span); }; @@ -1228,29 +1242,29 @@ impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_ } #[derive(Diagnostic)] -#[diag(codegen_ssa_feature_not_valid)] +#[diag("the feature named `{$feature}` is not valid for this target")] pub(crate) struct FeatureNotValid<'a> { pub feature: &'a str, #[primary_span] - #[label] + #[label("`{$feature}` is not valid for this target")] pub span: Span, - #[help] + #[help("consider removing the leading `+` in the feature name")] pub plus_hint: bool, } #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_disallowed)] +#[diag("lto can only be run for executables, cdylibs and static library outputs")] pub(crate) struct LtoDisallowed; #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_dylib)] +#[diag("lto cannot be used for `dylib` crate type without `-Zdylib-lto`")] pub(crate) struct LtoDylib; #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_proc_macro)] +#[diag("lto cannot be used for `proc-macro` crate type without `-Zdylib-lto`")] pub(crate) struct LtoProcMacro; #[derive(Diagnostic)] -#[diag(codegen_ssa_dynamic_linking_with_lto)] -#[note] +#[diag("cannot prefer dynamic linking when performing LTO")] +#[note("only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO")] pub(crate) struct DynamicLinkingWithLTO; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3ffc16d49ac1..cbfa12e21eba 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(file_buffered)] #![feature(if_let_guard)] @@ -24,7 +24,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; use rustc_hir::attrs::{CfgEntry, NativeLibKind, WindowsSubsystemKind}; use rustc_hir::def_id::CrateNum; -use rustc_macros::{Decodable, Encodable, HashStable}; +use rustc_macros::{Decodable, Encodable}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::lint::LevelAndSource; @@ -55,8 +55,6 @@ pub mod size_of_val; pub mod target_features; pub mod traits; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct ModuleCodegen { /// The name of the module. When the crate may be saved between /// compilations, incremental compilation requires that name be @@ -175,7 +173,12 @@ bitflags::bitflags! { } } -#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +// This is the same as `rustc_session::cstore::NativeLib`, except: +// - (important) the `foreign_module` field is missing, because it contains a `DefId`, which can't +// be encoded with `FileEncoder`. +// - (less important) the `verbatim` field is a `bool` rather than an `Option`, because here +// we can treat `false` and `absent` the same. +#[derive(Clone, Debug, Encodable, Decodable)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 4bbb7470debe..f12410c65d98 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,5 +1,6 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_hir::attrs::{InstructionSetAttr, Linkage}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::mono::{MonoItemData, Visibility}; use rustc_middle::mir::{InlineAsmOperand, START_BLOCK}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; @@ -128,6 +129,15 @@ fn prefix_and_suffix<'tcx>( let is_arm = tcx.sess.target.arch == Arch::Arm; let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode); + // If we're compiling the compiler-builtins crate, e.g., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. For naked asm we set the visibility here. + let mut visibility = item_data.visibility; + if item_data.linkage != Linkage::Internal && tcx.is_compiler_builtins(LOCAL_CRATE) { + visibility = Visibility::Hidden; + } + let attrs = tcx.codegen_instance_attrs(instance.def); let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string()); @@ -217,7 +227,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); - match item_data.visibility { + match visibility { Visibility::Default => {} Visibility::Protected => writeln!(begin, ".protected {asm_name}").unwrap(), Visibility::Hidden => writeln!(begin, ".hidden {asm_name}").unwrap(), @@ -243,7 +253,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); - match item_data.visibility { + match visibility { Visibility::Default | Visibility::Protected => {} Visibility::Hidden => writeln!(begin, ".private_extern {asm_name}").unwrap(), } @@ -280,7 +290,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".section {section},\"\",@").unwrap(); // wasm functions cannot be aligned, so skip write_linkage(&mut begin).unwrap(); - if let Visibility::Hidden = item_data.visibility { + if let Visibility::Hidden = visibility { writeln!(begin, ".hidden {asm_name}").unwrap(); } writeln!(begin, ".type {asm_name}, @function").unwrap(); @@ -313,7 +323,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".align {}", align_bytes).unwrap(); write_linkage(&mut begin).unwrap(); - if let Visibility::Hidden = item_data.visibility { + if let Visibility::Hidden = visibility { // FIXME apparently `.globl {asm_name}, hidden` is valid // but due to limitations with `.weak` (see above) we can't really use that in general yet } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 625551d17d9d..7ebff77710fb 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -37,10 +37,6 @@ pub trait BackendTypes { } pub trait CodegenBackend { - /// Locale resources for diagnostic messages - a string the content of the Fluent resource. - /// Called before `init` so that all other functions are able to emit translatable diagnostics. - fn locale_resource(&self) -> &'static str; - fn name(&self) -> &'static str; fn init(&self, _sess: &Session) {} @@ -78,6 +74,17 @@ pub trait CodegenBackend { fn print_version(&self) {} + /// Returns a list of all intrinsics that this backend definitely + /// replaces, which means their fallback bodies do not need to be monomorphized. + fn replaced_intrinsics(&self) -> Vec { + vec![] + } + + /// Is ThinLTO supported by this backend? + fn thin_lto_supported(&self) -> bool { + true + } + /// Value printed by `--print=backend-has-zstd`. /// /// Used by compiletest to determine whether tests involving zstd compression diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index e1d23841118c..5f5d0ac5d9fc 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -1,16 +1,18 @@ use std::path::PathBuf; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::DiagCtxtHandle; use rustc_middle::dep_graph::WorkProduct; use crate::back::lto::{SerializedModule, ThinModule}; -use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter}; +use crate::back::write::{ + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, +}; use crate::{CompiledModule, ModuleCodegen}; pub trait WriteBackendMethods: Clone + 'static { type Module: Send + Sync; type TargetMachine; - type TargetMachineError; type ModuleBuffer: ModuleBufferMethods; type ThinData: Send + Sync; type ThinBuffer: ThinBufferMethods; @@ -18,8 +20,10 @@ pub trait WriteBackendMethods: Clone + 'static { /// Performs fat LTO by merging all modules into a single one, running autodiff /// if necessary and running any further optimizations fn run_and_optimize_fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -28,7 +32,8 @@ pub trait WriteBackendMethods: Clone + 'static { /// lists, one of the modules that need optimization and another for modules that /// can simply be copied over from the incr. comp. cache. fn run_thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], @@ -38,18 +43,22 @@ pub trait WriteBackendMethods: Clone + 'static { fn print_pass_timings(&self); fn print_statistics(&self); fn optimize( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ); fn optimize_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, thin: ThinModule, ) -> ModuleCodegen; fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 51dcee8d8822..aa013cf61f48 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -11,7 +11,6 @@ rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl deleted file mode 100644 index 4aa0a0b2a96f..000000000000 --- a/compiler/rustc_const_eval/messages.ftl +++ /dev/null @@ -1,507 +0,0 @@ -const_eval_address_space_full = - there are no more free addresses in the address space - -const_eval_alignment_check_failed = - {$msg -> - [AccessedPtr] accessing memory - *[other] accessing memory based on pointer - } with alignment {$has}, but alignment {$required} is required - -const_eval_already_reported = - an error has already been reported elsewhere (this should not usually be printed) -const_eval_assume_false = - `assume` called with `false` - -const_eval_bad_pointer_op = {$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -} -const_eval_bad_pointer_op_attempting = {const_eval_bad_pointer_op}: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } - } - -const_eval_bounds_check_failed = - indexing out of bounds: the len is {$len} but the index is {$index} -const_eval_call_nonzero_intrinsic = - `{$name}` called on 0 - -const_eval_closure_call = - closures need an RFC before allowed to be called in {const_eval_const_context}s -const_eval_closure_fndef_not_const = - function defined here, but it is not `const` - -const_eval_consider_dereferencing = - consider dereferencing here - -const_eval_const_accesses_mut_global = - constant accesses mutable global memory - -const_eval_const_context = {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -} - -const_eval_const_heap_ptr_in_final = encountered `const_allocate` pointer in final value that was not made global - .note = use `const_make_global` to turn allocated pointers into immutable globals before returning - -const_eval_const_make_global_ptr_already_made_global = attempting to call `const_make_global` twice on the same allocation {$alloc} - -const_eval_const_make_global_ptr_is_non_heap = pointer passed to `const_make_global` does not point to a heap allocation: {$ptr} - -const_eval_const_make_global_with_dangling_ptr = pointer passed to `const_make_global` is dangling: {$ptr} - -const_eval_const_make_global_with_offset = making {$ptr} global which does not point to the beginning of an object - -const_eval_copy_nonoverlapping_overlapping = - `copy_nonoverlapping` called on overlapping ranges - -const_eval_dangling_int_pointer = - {const_eval_bad_pointer_op_attempting}, but got {$pointer} which is a dangling pointer (it has no provenance) -const_eval_dangling_null_pointer = - {const_eval_bad_pointer_op_attempting}, but got null pointer - -const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind} -const_eval_dead_local = - accessing a dead local variable -const_eval_dealloc_immutable = - deallocating immutable allocation {$alloc} - -const_eval_dealloc_incorrect_layout = - incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found} - -const_eval_dealloc_kind_mismatch = - deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation - -const_eval_deref_function_pointer = - accessing {$allocation} which contains a function -const_eval_deref_typeid_pointer = - accessing {$allocation} which contains a `TypeId` -const_eval_deref_vtable_pointer = - accessing {$allocation} which contains a vtable -const_eval_division_by_zero = - dividing by zero -const_eval_division_overflow = - overflow in signed division (dividing MIN by -1) - -const_eval_dyn_call_not_a_method = - `dyn` call trying to call something that is not a method - -const_eval_error = evaluation of `{$instance}` failed {$num_frames -> - [0] here - *[other] inside this call -} - -const_eval_exact_div_has_remainder = - exact_div: {$a} cannot be divided by {$b} without remainder - -const_eval_extern_static = - cannot access extern static `{$did}` -const_eval_extern_type_field = `extern type` field does not have a known offset - -const_eval_fn_ptr_call = - function pointers need an RFC before allowed to be called in {const_eval_const_context}s -const_eval_frame_note = {$times -> - [0] {const_eval_frame_note_inner} - *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...] -} - -const_eval_frame_note_inner = inside {$where_ -> - [closure] closure - [instance] `{$instance}` - *[other] {""} -} - -const_eval_frame_note_last = the failure occurred here - -const_eval_incompatible_arg_types = - calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty} - -const_eval_incompatible_calling_conventions = - calling a function with calling convention "{$callee_conv}" using calling convention "{$caller_conv}" - -const_eval_incompatible_return_types = - calling a function with return type {$callee_ty} passing return place of type {$caller_ty} - -const_eval_interior_mutable_borrow_escaping = - interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed - .label = this borrow of an interior mutable value refers to such a temporary - .note = temporaries in constants and statics can have their lifetime extended until the end of the program - .note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable - .help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut` - -const_eval_intern_kind = {$kind -> - [static] static - [static_mut] mutable static - [const] constant - [promoted] promoted - *[other] {""} -} - -const_eval_interrupted = compilation was interrupted - -const_eval_invalid_align_details = - invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {""} - } - -const_eval_invalid_bool = - interpreting an invalid 8-bit value as a bool: 0x{$value} -const_eval_invalid_char = - interpreting an invalid 32-bit value as a char: 0x{$value} -const_eval_invalid_dealloc = - deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {""} - } - -const_eval_invalid_function_pointer = - using {$pointer} as function pointer but it does not point to a function -const_eval_invalid_meta = - invalid metadata in wide pointer: total size is bigger than largest supported object -const_eval_invalid_meta_slice = - invalid metadata in wide pointer: slice is bigger than largest supported object - -const_eval_invalid_niched_enum_variant_written = - trying to set discriminant of a {$ty} to the niched variant, but the value does not match - -const_eval_invalid_str = - this string is not valid UTF-8: {$err} -const_eval_invalid_tag = - enum value has invalid tag: {$tag} -const_eval_invalid_transmute = - transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}` - -const_eval_invalid_uninit_bytes = - reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory -const_eval_invalid_uninit_bytes_unknown = - using uninitialized data, but this operation requires initialized memory - -const_eval_invalid_vtable_pointer = - using {$pointer} as vtable pointer but it does not point to a vtable - -const_eval_invalid_vtable_trait = - using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected - -const_eval_lazy_lock = - consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` - -const_eval_live_drop = - destructor of `{$dropped_ty}` cannot be evaluated at compile-time - .label = the destructor for this type cannot be evaluated in {const_eval_const_context}s - .dropped_at_label = value is dropped here - -const_eval_long_running = - constant evaluation is taking a long time - .note = this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. - .label = the const evaluator is currently interpreting this expression - .help = the constant being evaluated - -const_eval_memory_exhausted = - tried to allocate more memory than available to compiler - -const_eval_modified_global = - modifying a static's initial value from another static's initializer - -const_eval_mutable_borrow_escaping = - mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed - .label = this mutable borrow refers to such a temporary - .note = temporaries in constants and statics can have their lifetime extended until the end of the program - .note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable - .help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut` - -const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} - -const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead - -const_eval_non_const_await = - cannot convert `{$ty}` into a future in {const_eval_const_context}s - -const_eval_non_const_closure = - cannot call {$non_or_conditionally}-const closure in {const_eval_const_context}s - -const_eval_non_const_deref_coercion = - cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {const_eval_const_context}s - .note = attempting to deref into `{$target_ty}` - .target_note = deref defined here - -const_eval_non_const_fmt_macro_call = - cannot call {$non_or_conditionally}-const formatting macro in {const_eval_const_context}s - -const_eval_non_const_fn_call = - cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s - -const_eval_non_const_for_loop_into_iter = - cannot use `for` loop on `{$ty}` in {const_eval_const_context}s - -const_eval_non_const_impl = - impl defined here, but it is not `const` - -const_eval_non_const_intrinsic = - cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s - -const_eval_non_const_match_eq = cannot match on `{$ty}` in {const_eval_const_context}s - .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es - -const_eval_non_const_operator = - cannot call {$non_or_conditionally}-const operator in {const_eval_const_context}s - -const_eval_non_const_question_branch = - `?` is not allowed on `{$ty}` in {const_eval_const_context}s -const_eval_non_const_question_from_residual = - `?` is not allowed on `{$ty}` in {const_eval_const_context}s - -const_eval_non_const_try_block_from_output = - `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s - -const_eval_not_enough_caller_args = - calling a function with fewer arguments than it requires - -const_eval_offset_from_different_allocations = - `{$name}` called on two different pointers that are not both derived from the same allocation -const_eval_offset_from_out_of_bounds = - `{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation -const_eval_offset_from_overflow = - `{$name}` called when first pointer is too far ahead of second -const_eval_offset_from_underflow = - `{$name}` called when first pointer is too far before second -const_eval_offset_from_unsigned_overflow = - `ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> - [true] address - *[false] offset - } than second: {$a_offset} < {$b_offset} - -const_eval_overflow_arith = - arithmetic overflow in `{$intrinsic}` -const_eval_overflow_shift = - overflowing shift by {$shift_amount} in `{$intrinsic}` - -const_eval_panic = evaluation panicked: {$msg} - -const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str` - -const_eval_partial_pointer_in_final = encountered partial pointer in final value of {const_eval_intern_kind} - .note = while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value - -const_eval_partial_pointer_read = - unable to read parts of a pointer from memory at {$ptr} -const_eval_pointer_arithmetic_overflow = - overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` - -const_eval_pointer_out_of_bounds = - {const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$ptr_offset_is_neg -> - [true] points to before the beginning of the allocation - *[false] {$inbounds_size_is_neg -> - [false] {$alloc_size_minus_ptr_offset -> - [0] is at or beyond the end of the allocation of size {$alloc_size -> - [1] 1 byte - *[x] {$alloc_size} bytes - } - [1] is only 1 byte from the end of the allocation - *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation - } - *[true] {$ptr_offset_abs -> - [0] is at the beginning of the allocation - *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation - } - } - } - -const_eval_pointer_use_after_free = - {const_eval_bad_pointer_op}: {$alloc_id} has been freed, so this pointer is dangling -const_eval_ptr_as_bytes_1 = - this code performed an operation that depends on the underlying bytes representing a pointer -const_eval_ptr_as_bytes_2 = - the absolute address of a pointer is not known at compile-time, so such operations are not supported - -const_eval_range = in the range {$lo}..={$hi} -const_eval_range_lower = greater or equal to {$lo} -const_eval_range_singular = equal to {$lo} -const_eval_range_upper = less or equal to {$hi} -const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo} -const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"} - -const_eval_raw_ptr_comparison = - pointers cannot be reliably compared during const eval - .note = see issue #53020 for more information - -const_eval_raw_ptr_to_int = - pointers cannot be cast to integers during const eval - .note = at compile-time, pointers do not have an integer value - .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior - -const_eval_read_pointer_as_int = - unable to turn pointer into integer -const_eval_realloc_or_alloc_with_offset = - {$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {""} - } {$ptr} which does not point to the beginning of an object - -const_eval_recursive_static = encountered static that tried to access itself during initialization - -const_eval_remainder_by_zero = - calculating the remainder with a divisor of zero -const_eval_remainder_overflow = - overflow in signed remainder (dividing MIN by -1) -const_eval_scalar_size_mismatch = - scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead -const_eval_size_overflow = - overflow computing total size of `{$name}` - -const_eval_stack_frame_limit_reached = - reached the configured maximum number of stack frames - -const_eval_thread_local_access = - thread-local statics cannot be accessed at compile-time - -const_eval_thread_local_static = - cannot access thread local static `{$did}` -const_eval_too_generic = - encountered overly generic constant -const_eval_too_many_caller_args = - calling a function with more arguments than it expected - -const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s - -const_eval_unallowed_heap_allocations = - allocations are not allowed in {const_eval_const_context}s - .label = allocation not allowed in {const_eval_const_context}s - .teach_note = - The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. - -const_eval_unallowed_inline_asm = - inline assembly is not allowed in {const_eval_const_context}s - -const_eval_unallowed_op_in_const_context = - {$msg} - -const_eval_uninhabited_enum_variant_read = - read discriminant of an uninhabited enum variant -const_eval_uninhabited_enum_variant_written = - writing discriminant of an uninhabited enum variant - -const_eval_unmarked_const_item_exposed = `{$def_path}` cannot be (indirectly) exposed to stable - .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` -const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable - .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval) - -const_eval_unreachable = entering unreachable code -const_eval_unreachable_unwind = - unwinding past a stack frame that does not allow unwinding - -const_eval_unsized_local = unsized locals are not supported -const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn -const_eval_unstable_const_trait = `{$def_path}` is not yet stable as a const trait -const_eval_unstable_in_stable_exposed = - const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]` - .is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features - .unstable_sugg = if the {$is_function_call2 -> - [true] caller - *[false] function - } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` - -const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic -const_eval_unstable_intrinsic_suggestion = add `#![feature({$feature})]` to the crate attributes to enable - -const_eval_unterminated_c_string = - reading a null-terminated string starting at {$pointer} with no null found before end of allocation - -const_eval_unwind_past_top = - unwinding past the topmost frame of the stack - -## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`. -## (We'd love to sort this differently to make that more clear but tidy won't let us...) -const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty} - -const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance) -const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation) -const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free) -const_eval_validation_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance) -const_eval_validation_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation) -const_eval_validation_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free) - -const_eval_validation_expected_bool = expected a boolean -const_eval_validation_expected_box = expected a box -const_eval_validation_expected_char = expected a unicode scalar value -const_eval_validation_expected_enum_tag = expected a valid enum tag -const_eval_validation_expected_float = expected a floating point number -const_eval_validation_expected_fn_ptr = expected a function pointer -const_eval_validation_expected_init_scalar = expected initialized scalar value -const_eval_validation_expected_int = expected an integer -const_eval_validation_expected_raw_ptr = expected a raw pointer -const_eval_validation_expected_ref = expected a reference -const_eval_validation_expected_str = expected a string - -const_eval_validation_failure = - it is undefined behavior to use this value - -const_eval_validation_failure_note = - the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -const_eval_validation_front_matter_invalid_value = constructing invalid value -const_eval_validation_front_matter_invalid_value_with_path = constructing invalid value at {$path} - -const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean -const_eval_validation_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object -const_eval_validation_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object -const_eval_validation_invalid_char = {$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) - -const_eval_validation_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag -const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer -const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object -const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object -const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer -const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}` -const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory -const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!` -const_eval_validation_nonnull_ptr_out_of_range = {$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero -const_eval_validation_null_box = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } box -const_eval_validation_null_fn_ptr = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } function pointer -const_eval_validation_null_ref = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } reference -const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range} -const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers -const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected} -const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range} -const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty} -const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes}) -const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes}) -const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant -const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}` -const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected} -const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in read-only memory - -const_eval_write_through_immutable_pointer = - writing through a pointer that was derived from a shared (immutable) reference - -const_eval_write_to_read_only = - writing to {$allocation} which is read-only diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 95dbf42d4d44..57396b657a3f 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -774,16 +774,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Attempting to call a trait method? if let Some(trait_did) = tcx.trait_of_assoc(callee) { - // We can't determine the actual callee here, so we have to do different checks - // than usual. + // We can't determine the actual callee (the underlying impl of the trait) here, so we have + // to do different checks than usual. trace!("attempting to call a trait method"); - let trait_is_const = tcx.is_const_trait(trait_did); + let is_const = tcx.constness(callee) == hir::Constness::Const; // Only consider a trait to be const if the const conditions hold. // Otherwise, it's really misleading to call something "conditionally" // const when it's very obviously not conditionally const. - if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) { + if is_const && has_const_conditions == Some(ConstConditionsHold::Yes) { // Trait calls are always conditionally-const. self.check_op(ops::ConditionallyConstCall { callee, diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index e9824400ab7a..1adba200caaf 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -83,7 +83,7 @@ pub fn rustc_allow_const_fn_unstable( ) -> bool { let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); - find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms, _) if syms.contains(&feature_gate)) + find_attr!(attrs, AttributeKind::RustcAllowConstFnUnstable(syms, _) if syms.contains(&feature_gate)) } /// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable". diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index a9366bf29fbe..5b62ba8c1605 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -2,7 +2,7 @@ use hir::{ConstContext, LangItem}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, MultiSpan}; +use rustc_errors::{Applicability, Diag, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -23,7 +23,7 @@ use rustc_trait_selection::traits::SelectionContext; use tracing::debug; use super::ConstCx; -use crate::{errors, fluent_generated}; +use crate::errors; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Status { @@ -181,7 +181,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ); if let ConstContext::Static(_) = ccx.const_kind() { - err.note(fluent_generated::const_eval_lazy_lock); + err.note(msg!( + "consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`" + )); } err diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index fe3891d0dd7e..462254f064cf 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -345,7 +345,7 @@ where let uneval = match constant.const_ { Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None, - // Unevaluated consts in MIR bodies don't have associated MIR (e.g. `#[type_const]`). + // Unevaluated consts in MIR bodies don't have associated MIR (e.g. `type const`). ty::ConstKind::Unevaluated(_) => None, // FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly // strict, and if instead we should be doing some kind of value-based analysis. diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 69a8f163ca93..69aef3b047df 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -43,21 +43,37 @@ pub enum ConstEvalErrKind { impl MachineStopType for ConstEvalErrKind { fn diagnostic_message(&self) -> DiagMessage { use ConstEvalErrKind::*; + use rustc_errors::msg; - use crate::fluent_generated::*; match self { - ConstAccessesMutGlobal => const_eval_const_accesses_mut_global, - ModifiedGlobal => const_eval_modified_global, - Panic { .. } => const_eval_panic, - RecursiveStatic => const_eval_recursive_static, - AssertFailure(x) => x.diagnostic_message(), - WriteThroughImmutablePointer => const_eval_write_through_immutable_pointer, - ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { - const_eval_const_make_global_ptr_already_made_global + ConstAccessesMutGlobal => "constant accesses mutable global memory".into(), + ModifiedGlobal => { + "modifying a static's initial value from another static's initializer".into() + } + Panic { .. } => msg!("evaluation panicked: {$msg}"), + RecursiveStatic => { + "encountered static that tried to access itself during initialization".into() + } + AssertFailure(x) => x.diagnostic_message(), + WriteThroughImmutablePointer => { + msg!( + "writing through a pointer that was derived from a shared (immutable) reference" + ) + } + ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { + msg!("attempting to call `const_make_global` twice on the same allocation {$alloc}") + } + ConstMakeGlobalPtrIsNonHeap(_) => { + msg!( + "pointer passed to `const_make_global` does not point to a heap allocation: {$ptr}" + ) + } + ConstMakeGlobalWithDanglingPtr(_) => { + msg!("pointer passed to `const_make_global` is dangling: {$ptr}") + } + ConstMakeGlobalWithOffset(_) => { + msg!("making {$ptr} global which does not point to the beginning of an object") } - ConstMakeGlobalPtrIsNonHeap(_) => const_eval_const_make_global_ptr_is_non_heap, - ConstMakeGlobalWithDanglingPtr(_) => const_eval_const_make_global_with_dangling_ptr, - ConstMakeGlobalWithOffset(_) => const_eval_const_make_global_with_offset, } } fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 5383ab3547af..d2b7e9a6b84f 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -2,7 +2,7 @@ use std::sync::atomic::Ordering::Relaxed; use either::{Left, Right}; use rustc_abi::{self as abi, BackendRepr}; -use rustc_errors::E0080; +use rustc_errors::{E0080, msg}; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; @@ -394,7 +394,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); - // #[type_const] don't have bodys + // `type const` don't have bodys debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def); let is_static = tcx.is_static(def); @@ -467,7 +467,15 @@ fn report_eval_error<'tcx>( let num_frames = frames.len(); // FIXME(oli-obk): figure out how to use structured diagnostics again. diag.code(E0080); - diag.span_label(span, crate::fluent_generated::const_eval_error); + diag.span_label( + span, + msg!( + "evaluation of `{$instance}` failed {$num_frames -> + [0] here + *[other] inside this call + }" + ), + ); for frame in frames { diag.subdiagnostic(frame); } @@ -506,8 +514,8 @@ fn report_validation_error<'tcx>( move |diag, span, frames| { // FIXME(oli-obk): figure out how to use structured diagnostics again. diag.code(E0080); - diag.span_label(span, crate::fluent_generated::const_eval_validation_failure); - diag.note(crate::fluent_generated::const_eval_validation_failure_note); + diag.span_label(span, "it is undefined behavior to use this value"); + diag.note("the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior."); for frame in frames { diag.subdiagnostic(frame); } diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index cdf0dcff381f..46cdca53ba8c 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,7 +1,8 @@ +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, - Node, TraitItem, TraitItemKind, VariantData, + Node, TraitItem, TraitItemKind, VariantData, find_attr, }; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -36,7 +37,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness { Constness::NotConst => tcx.constness(tcx.local_parent(def_id)), } } - Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. }) => tcx.trait_def(tcx.local_parent(def_id)).constness, + Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => { + if find_attr!(tcx.hir_attrs(ti.hir_id()), AttributeKind::RustcNonConstTraitMethod) { + Constness::NotConst + } else { + tcx.trait_def(tcx.local_parent(def_id)).constness + } + } _ => { tcx.dcx().span_bug( tcx.def_span(def_id), diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 719187b99012..e017362b8c4b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,6 +5,7 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; +use rustc_errors::msg; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; use rustc_middle::mir::AssertMessage; @@ -19,7 +20,6 @@ use tracing::debug; use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; -use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, @@ -489,7 +489,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - fluent::const_eval_invalid_align_details, + msg!( + "invalid align passed to `{$name}`: {$align} is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" + ), name = "const_allocate", err_kind = err.diag_ident(), align = err.align() @@ -513,7 +519,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - fluent::const_eval_invalid_align_details, + msg!( + "invalid align passed to `{$name}`: {$align} is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" + ), name = "const_deallocate", err_kind = err.diag_ident(), align = err.align() diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index f8881f0968bb..0fd70d784d4f 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -1,4 +1,8 @@ -use rustc_abi::FieldIdx; +mod adt; + +use std::borrow::Cow; + +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_hir::LangItem; use rustc_middle::span_bug; @@ -8,11 +12,58 @@ use rustc_span::{Symbol, sym}; use crate::const_eval::CompileTimeMachine; use crate::interpret::{ - CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable, - interp_ok, + CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Projectable, Scalar, + Writeable, interp_ok, }; impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { + /// Equivalent to `project_downcast`, but identifies the variant by name instead of index. + fn downcast<'a>( + &self, + place: &(impl Writeable<'tcx, CtfeProvenance> + 'a), + name: Symbol, + ) -> InterpResult<'tcx, (VariantIdx, impl Writeable<'tcx, CtfeProvenance> + 'a)> { + let variants = place.layout().ty.ty_adt_def().unwrap().variants(); + let variant_idx = variants + .iter_enumerated() + .find(|(_idx, var)| var.name == name) + .unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}")) + .0; + + interp_ok((variant_idx, self.project_downcast(place, variant_idx)?)) + } + + // A general method to write an array to a static slice place. + fn allocate_fill_and_write_slice_ptr( + &mut self, + slice_place: impl Writeable<'tcx, CtfeProvenance>, + len: u64, + writer: impl Fn(&mut Self, /* index */ u64, MPlaceTy<'tcx>) -> InterpResult<'tcx>, + ) -> InterpResult<'tcx> { + // Array element type + let field_ty = slice_place + .layout() + .ty + .builtin_deref(false) + .unwrap() + .sequence_element_type(self.tcx.tcx); + + // Allocate an array + let array_layout = self.layout_of(Ty::new_array(self.tcx.tcx, field_ty, len))?; + let array_place = self.allocate(array_layout, MemoryKind::Stack)?; + + // Fill the array fields + let mut field_places = self.project_array_fields(&array_place)?; + while let Some((i, place)) = field_places.next(self)? { + writer(self, i, place)?; + } + + // Write the slice pointing to the array + let array_place = array_place.map_provenance(CtfeProvenance::as_immutable); + let ptr = Immediate::new_slice(array_place.ptr(), len, self); + self.write_immediate(ptr, &slice_place) + } + /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place. pub(crate) fn write_type_info( &mut self, @@ -26,22 +77,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { // Fill all fields of the `TypeInfo` struct. for (idx, field) in ty_struct.fields.iter_enumerated() { let field_dest = self.project_field(dest, idx)?; - let downcast = |name: Symbol| { - let variants = field_dest.layout().ty.ty_adt_def().unwrap().variants(); - let variant_id = variants - .iter_enumerated() - .find(|(_idx, var)| var.name == name) - .unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}")) - .0; - - interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?)) - }; let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits(); match field.name { sym::kind => { let variant_index = match ty.kind() { ty::Tuple(fields) => { - let (variant, variant_place) = downcast(sym::Tuple)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Tuple)?; // project to the single tuple variant field of `type_info::Tuple` struct type let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?; assert_eq!( @@ -55,11 +97,12 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { .fields .len() ); - self.write_tuple_fields(tuple_place, fields, ty)?; + self.write_tuple_type_info(tuple_place, fields, ty)?; variant } ty::Array(ty, len) => { - let (variant, variant_place) = downcast(sym::Array)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Array)?; let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_array_type_info(array_place, *ty, *len)?; @@ -67,23 +110,29 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Slice(ty) => { - let (variant, variant_place) = downcast(sym::Slice)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Slice)?; let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_slice_type_info(slice_place, *ty)?; variant } + ty::Adt(adt_def, generics) => { + self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? + } ty::Bool => { - let (variant, _variant_place) = downcast(sym::Bool)?; + let (variant, _variant_place) = + self.downcast(&field_dest, sym::Bool)?; variant } ty::Char => { - let (variant, _variant_place) = downcast(sym::Char)?; + let (variant, _variant_place) = + self.downcast(&field_dest, sym::Char)?; variant } ty::Int(int_ty) => { - let (variant, variant_place) = downcast(sym::Int)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_int_type_info( place, @@ -93,7 +142,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Uint(uint_ty) => { - let (variant, variant_place) = downcast(sym::Int)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_int_type_info( place, @@ -103,17 +152,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Float(float_ty) => { - let (variant, variant_place) = downcast(sym::Float)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Float)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_float_type_info(place, float_ty.bit_width())?; variant } ty::Str => { - let (variant, _variant_place) = downcast(sym::Str)?; + let (variant, _variant_place) = self.downcast(&field_dest, sym::Str)?; variant } ty::Ref(_, ty, mutability) => { - let (variant, variant_place) = downcast(sym::Reference)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Reference)?; let reference_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_reference_type_info(reference_place, *ty, *mutability)?; @@ -121,7 +172,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::RawPtr(ty, mutability) => { - let (variant, variant_place) = downcast(sym::Pointer)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Pointer)?; let pointer_place = self.project_field(&variant_place, FieldIdx::ZERO)?; @@ -130,13 +182,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Dynamic(predicates, region) => { - let (variant, variant_place) = downcast(sym::DynTrait)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::DynTrait)?; let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?; variant } - ty::Adt(_, _) - | ty::Foreign(_) + ty::Foreign(_) | ty::Pat(_, _) | ty::FnDef(..) | ty::FnPtr(..) @@ -151,14 +203,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(..) - | ty::Error(_) => downcast(sym::Other)?.0, + | ty::Error(_) => self.downcast(&field_dest, sym::Other)?.0, }; self.write_discriminant(variant_index, &field_dest)? } sym::size => { let layout = self.layout_of(ty)?; let variant_index = if layout.is_sized() { - let (variant, variant_place) = downcast(sym::Some)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Some)?; let size_field_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_scalar( @@ -168,7 +220,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { )?; variant } else { - downcast(sym::None)?.0 + self.downcast(&field_dest, sym::None)?.0 }; self.write_discriminant(variant_index, &field_dest)?; } @@ -179,46 +231,12 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } - pub(crate) fn write_tuple_fields( - &mut self, - tuple_place: impl Writeable<'tcx, CtfeProvenance>, - fields: &[Ty<'tcx>], - tuple_ty: Ty<'tcx>, - ) -> InterpResult<'tcx> { - // project into the `type_info::Tuple::fields` field - let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?; - // get the `type_info::Field` type from `fields: &[Field]` - let field_type = fields_slice_place - .layout() - .ty - .builtin_deref(false) - .unwrap() - .sequence_element_type(self.tcx.tcx); - // Create an array with as many elements as the number of fields in the inspected tuple - let fields_layout = - self.layout_of(Ty::new_array(self.tcx.tcx, field_type, fields.len() as u64))?; - let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?; - let mut fields_places = self.project_array_fields(&fields_place)?; - - let tuple_layout = self.layout_of(tuple_ty)?; - - while let Some((i, place)) = fields_places.next(self)? { - let field_ty = fields[i as usize]; - self.write_field(field_ty, place, tuple_layout, i)?; - } - - let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable); - - let ptr = Immediate::new_slice(fields_place.ptr(), fields.len() as u64, self); - - self.write_immediate(ptr, &fields_slice_place) - } - fn write_field( &mut self, field_ty: Ty<'tcx>, place: MPlaceTy<'tcx>, layout: TyAndLayout<'tcx>, + name: Option, idx: u64, ) -> InterpResult<'tcx> { for (field_idx, field_ty_field) in @@ -226,7 +244,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { { let field_place = self.project_field(&place, field_idx)?; match field_ty_field.name { - sym::ty => self.write_type_id(field_ty, &field_place)?, + sym::name => { + let name = match name.as_ref() { + Some(name) => Cow::Borrowed(name.as_str()), + None => Cow::Owned(idx.to_string()), // For tuples + }; + let name_place = self.allocate_str_dedup(&name)?; + let ptr = self.mplace_to_ref(&name_place)?; + self.write_immediate(*ptr, &field_place)? + } + sym::ty => { + let field_ty = self.tcx.erase_and_anonymize_regions(field_ty); + self.write_type_id(field_ty, &field_place)? + } sym::offset => { let offset = layout.fields.offset(idx as usize); self.write_scalar( @@ -242,6 +272,24 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + pub(crate) fn write_tuple_type_info( + &mut self, + tuple_place: impl Writeable<'tcx, CtfeProvenance>, + fields: &[Ty<'tcx>], + tuple_ty: Ty<'tcx>, + ) -> InterpResult<'tcx> { + let tuple_layout = self.layout_of(tuple_ty)?; + let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?; + self.allocate_fill_and_write_slice_ptr( + fields_slice_place, + fields.len() as u64, + |this, i, place| { + let field_ty = fields[i as usize]; + this.write_field(field_ty, place, tuple_layout, None, i) + }, + ) + } + pub(crate) fn write_array_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs new file mode 100644 index 000000000000..60f7b95e799a --- /dev/null +++ b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs @@ -0,0 +1,276 @@ +use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{ + AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef, +}; +use rustc_middle::{bug, span_bug}; +use rustc_span::sym; + +use crate::const_eval::CompileTimeMachine; +use crate::interpret::{ + CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok, +}; + +impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { + // FIXME(type_info): No semver considerations for now + pub(crate) fn write_adt_type_info( + &mut self, + place: &impl Writeable<'tcx, CtfeProvenance>, + adt: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx, VariantIdx> { + let (adt_ty, adt_def) = adt; + let variant_idx = match adt_def.adt_kind() { + AdtKind::Struct => { + let (variant, variant_place) = self.downcast(place, sym::Struct)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_struct_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } + AdtKind::Union => { + let (variant, variant_place) = self.downcast(place, sym::Union)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_union_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } + AdtKind::Enum => { + let (variant, variant_place) = self.downcast(place, sym::Enum)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_enum_type_info(place, adt, generics)?; + variant + } + }; + interp_ok(variant_idx) + } + + pub(crate) fn write_struct_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + struct_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (struct_ty, struct_def) = struct_; + let struct_layout = self.layout_of(struct_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => { + self.write_variant_fields(field_place, struct_def, struct_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + pub(crate) fn write_union_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + union_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (union_ty, union_def) = union_; + let union_layout = self.layout_of(union_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => { + self.write_variant_fields(field_place, union_def, union_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + pub(crate) fn write_enum_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + enum_: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (enum_ty, enum_def) = enum_; + let enum_layout = self.layout_of(enum_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::variants => { + self.allocate_fill_and_write_slice_ptr( + field_place, + enum_def.variants().len() as u64, + |this, i, place| { + let variant_idx = VariantIdx::from_usize(i as usize); + let variant_def = &enum_def.variants()[variant_idx]; + let variant_layout = enum_layout.for_variant(this, variant_idx); + this.write_enum_variant(place, (variant_layout, &variant_def), generics) + }, + )?; + } + sym::non_exhaustive => { + let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + fn write_enum_variant( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant: (TyAndLayout<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_layout, variant_def) = variant; + + for (field_idx, field_def) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + match field_def.name { + sym::name => { + let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; + let ptr = self.mplace_to_ref(&name_place)?; + self.write_immediate(*ptr, &field_place)? + } + sym::fields => { + self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + interp_ok(()) + } + + // Write fields for struct, enum variants + fn write_variant_fields( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant_def: &'tcx VariantDef, + variant_layout: TyAndLayout<'tcx>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr( + place, + variant_def.fields.len() as u64, + |this, i, place| { + let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; + let field_ty = field_def.ty(*this.tcx, generics); + this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) + }, + ) + } + + fn write_generics( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr(place, generics.len() as u64, |this, i, place| { + match generics[i as usize].kind() { + GenericArgKind::Lifetime(region) => this.write_generic_lifetime(region, place), + GenericArgKind::Type(ty) => this.write_generic_type(ty, place), + GenericArgKind::Const(c) => this.write_generic_const(c, place), + } + }) + } + + fn write_generic_lifetime( + &mut self, + _region: Region<'tcx>, + place: MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?; + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?; + let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in generic_type_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&generic_type_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") }; + + let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?; + let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in const_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&const_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(c.ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } +} diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 50f5448ec20a..b477c998a278 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -5,7 +5,8 @@ use either::Either; use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic, + Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, + Subdiagnostic, msg, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -17,11 +18,18 @@ use rustc_middle::mir::interpret::{ use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::{Span, Symbol}; -use crate::fluent_generated as fluent; use crate::interpret::InternKind; #[derive(Diagnostic)] -#[diag(const_eval_dangling_ptr_in_final)] +#[diag( + r#"encountered dangling pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] pub(crate) struct DanglingPtrInFinal { #[primary_span] pub span: Span, @@ -29,14 +37,24 @@ pub(crate) struct DanglingPtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_nested_static_in_thread_local)] +#[diag( + "#[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead" +)] pub(crate) struct NestedStaticInThreadLocal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_mutable_ptr_in_final)] +#[diag( + r#"encountered mutable pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] pub(crate) struct MutablePtrInFinal { #[primary_span] pub span: Span, @@ -44,16 +62,28 @@ pub(crate) struct MutablePtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_const_heap_ptr_in_final)] -#[note] +#[diag("encountered `const_allocate` pointer in final value that was not made global")] +#[note( + "use `const_make_global` to turn allocated pointers into immutable globals before returning" +)] pub(crate) struct ConstHeapPtrInFinal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_partial_pointer_in_final)] -#[note] +#[diag( + r#"encountered partial pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] +#[note( + "while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value" +)] pub(crate) struct PartialPtrInFinal { #[primary_span] pub span: Span, @@ -61,17 +91,24 @@ pub(crate) struct PartialPtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_in_stable_exposed)] +#[diag( + "const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]`" +)] pub(crate) struct UnstableInStableExposed { pub gate: String, #[primary_span] pub span: Span, - #[help(const_eval_is_function_call)] + #[help( + "mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features" + )] pub is_function_call: bool, /// Need to duplicate the field so that fluent also provides it as a variable... pub is_function_call2: bool, #[suggestion( - const_eval_unstable_sugg, + "if the {$is_function_call2 -> + [true] caller + *[false] function + } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", applicability = "has-placeholders" )] @@ -79,38 +116,47 @@ pub(crate) struct UnstableInStableExposed { } #[derive(Diagnostic)] -#[diag(const_eval_thread_local_access, code = E0625)] +#[diag("thread-local statics cannot be accessed at compile-time", code = E0625)] pub(crate) struct ThreadLocalAccessErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_raw_ptr_to_int)] -#[note] -#[note(const_eval_note2)] +#[diag("pointers cannot be cast to integers during const eval")] +#[note("at compile-time, pointers do not have an integer value")] +#[note( + "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior" +)] pub(crate) struct RawPtrToIntErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_raw_ptr_comparison)] -#[note] +#[diag("pointers cannot be reliably compared during const eval")] +#[note("see issue #53020 for more information")] pub(crate) struct RawPtrComparisonErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_panic_non_str)] +#[diag("argument to `panic!()` in a const context must have type `&str`")] pub(crate) struct PanicNonStrErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_fn_pointer_call)] +#[diag( + r#"function pointer calls are not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] pub(crate) struct UnallowedFnPointerCall { #[primary_span] pub span: Span, @@ -118,7 +164,7 @@ pub(crate) struct UnallowedFnPointerCall { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_const_fn)] +#[diag("`{$def_path}` is not yet stable as a const fn")] pub(crate) struct UnstableConstFn { #[primary_span] pub span: Span, @@ -126,7 +172,7 @@ pub(crate) struct UnstableConstFn { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_const_trait)] +#[diag("`{$def_path}` is not yet stable as a const trait")] pub(crate) struct UnstableConstTrait { #[primary_span] pub span: Span, @@ -134,14 +180,14 @@ pub(crate) struct UnstableConstTrait { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_intrinsic)] +#[diag("`{$name}` is not yet stable as a const intrinsic")] pub(crate) struct UnstableIntrinsic { #[primary_span] pub span: Span, pub name: Symbol, pub feature: Symbol, #[suggestion( - const_eval_unstable_intrinsic_suggestion, + "add `#![feature({$feature})]` to the crate attributes to enable", code = "#![feature({feature})]\n", applicability = "machine-applicable" )] @@ -149,8 +195,10 @@ pub(crate) struct UnstableIntrinsic { } #[derive(Diagnostic)] -#[diag(const_eval_unmarked_const_item_exposed)] -#[help] +#[diag("`{$def_path}` cannot be (indirectly) exposed to stable")] +#[help( + "either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`" +)] pub(crate) struct UnmarkedConstItemExposed { #[primary_span] pub span: Span, @@ -158,8 +206,10 @@ pub(crate) struct UnmarkedConstItemExposed { } #[derive(Diagnostic)] -#[diag(const_eval_unmarked_intrinsic_exposed)] -#[help] +#[diag("intrinsic `{$def_path}` cannot be (indirectly) exposed to stable")] +#[help( + "mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)" +)] pub(crate) struct UnmarkedIntrinsicExposed { #[primary_span] pub span: Span, @@ -167,19 +217,31 @@ pub(crate) struct UnmarkedIntrinsicExposed { } #[derive(Diagnostic)] -#[diag(const_eval_mutable_borrow_escaping, code = E0764)] -#[note] -#[note(const_eval_note2)] -#[help] +#[diag("mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0764)] +#[note( + "temporaries in constants and statics can have their lifetime extended until the end of the program" +)] +#[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] +#[help( + "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" +)] pub(crate) struct MutableBorrowEscaping { #[primary_span] - #[label] + #[label("this mutable borrow refers to such a temporary")] pub span: Span, pub kind: ConstContext, } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fmt_macro_call, code = E0015)] +#[diag( + r#"cannot call {$non_or_conditionally}-const formatting macro in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, + code = E0015, +)] pub(crate) struct NonConstFmtMacroCall { #[primary_span] pub span: Span, @@ -188,7 +250,12 @@ pub(crate) struct NonConstFmtMacroCall { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fn_call, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub(crate) struct NonConstFnCall { #[primary_span] pub span: Span, @@ -199,7 +266,14 @@ pub(crate) struct NonConstFnCall { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_intrinsic)] +#[diag( + r#"cannot call non-const intrinsic `{$name}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] pub(crate) struct NonConstIntrinsic { #[primary_span] pub span: Span, @@ -208,7 +282,7 @@ pub(crate) struct NonConstIntrinsic { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_op_in_const_context)] +#[diag("{$msg}")] pub(crate) struct UnallowedOpInConstContext { #[primary_span] pub span: Span, @@ -216,18 +290,37 @@ pub(crate) struct UnallowedOpInConstContext { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_heap_allocations, code = E0010)] +#[diag(r#"allocations are not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0010)] pub(crate) struct UnallowedHeapAllocations { #[primary_span] - #[label] + #[label( + r#"allocation not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# + )] pub span: Span, pub kind: ConstContext, - #[note(const_eval_teach_note)] + #[note( + "the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created" + )] pub teach: bool, } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_inline_asm, code = E0015)] +#[diag(r#"inline assembly is not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub(crate) struct UnallowedInlineAsm { #[primary_span] pub span: Span, @@ -235,39 +328,46 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_borrow_escaping, code = E0492)] -#[note] -#[note(const_eval_note2)] -#[help] +#[diag("interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0492)] +#[note( + "temporaries in constants and statics can have their lifetime extended until the end of the program" +)] +#[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] +#[help( + "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" +)] pub(crate) struct InteriorMutableBorrowEscaping { #[primary_span] - #[label] + #[label("this borrow of an interior mutable value refers to such a temporary")] pub span: Span, pub kind: ConstContext, } #[derive(LintDiagnostic)] -#[diag(const_eval_long_running)] -#[note] +#[diag("constant evaluation is taking a long time")] +#[note( + "this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint" +)] pub struct LongRunning { - #[help] + #[help("the constant being evaluated")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_long_running)] +#[diag("constant evaluation is taking a long time")] pub struct LongRunningWarn { #[primary_span] - #[label] + #[label("the const evaluator is currently interpreting this expression")] pub span: Span, - #[help] + #[help("the constant being evaluated")] pub item_span: Span, // Used for evading `-Z deduplicate-diagnostics`. pub force_duplicate: usize, } #[derive(Subdiagnostic)] -#[note(const_eval_non_const_impl)] +#[note("impl defined here, but it is not `const`")] pub(crate) struct NonConstImplNote { #[primary_span] pub span: Span, @@ -289,9 +389,22 @@ impl Subdiagnostic for FrameNote { diag.arg("instance", self.instance); let mut span: MultiSpan = self.span.into(); if self.has_label && !self.span.is_dummy() { - span.push_span_label(self.span, fluent::const_eval_frame_note_last); + span.push_span_label(self.span, msg!("the failure occurred here")); } - let msg = diag.eagerly_translate(fluent::const_eval_frame_note); + let msg = diag.eagerly_translate(msg!( + r#"{$times -> + [0] inside {$where_ -> + [closure] closure + [instance] `{$instance}` + *[other] {""} + } + *[other] [... {$times} additional calls inside {$where_ -> + [closure] closure + [instance] `{$instance}` + *[other] {""} + } ...] + }"# + )); diag.remove_arg("times"); diag.remove_arg("where_"); diag.remove_arg("instance"); @@ -300,7 +413,7 @@ impl Subdiagnostic for FrameNote { } #[derive(Subdiagnostic)] -#[note(const_eval_raw_bytes)] +#[note(r#"the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"}"#)] pub struct RawBytesNote { pub size: u64, pub align: u64, @@ -310,8 +423,15 @@ pub struct RawBytesNote { // FIXME(fee1-dead) do not use stringly typed `ConstContext` #[derive(Diagnostic)] -#[diag(const_eval_non_const_match_eq, code = E0015)] -#[note] +#[diag( + r#"cannot match on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] +#[note("`{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es")] pub struct NonConstMatchEq<'tcx> { #[primary_span] pub span: Span, @@ -321,7 +441,12 @@ pub struct NonConstMatchEq<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_for_loop_into_iter, code = E0015)] +#[diag(r#"cannot use `for` loop on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstForLoopIntoIter<'tcx> { #[primary_span] pub span: Span, @@ -331,7 +456,12 @@ pub struct NonConstForLoopIntoIter<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_question_branch, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstQuestionBranch<'tcx> { #[primary_span] pub span: Span, @@ -341,7 +471,12 @@ pub struct NonConstQuestionBranch<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_question_from_residual, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstQuestionFromResidual<'tcx> { #[primary_span] pub span: Span, @@ -351,7 +486,12 @@ pub struct NonConstQuestionFromResidual<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_try_block_from_output, code = E0015)] +#[diag(r#"`try` block cannot convert `{$ty}` to the result in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstTryBlockFromOutput<'tcx> { #[primary_span] pub span: Span, @@ -361,7 +501,12 @@ pub struct NonConstTryBlockFromOutput<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_await, code = E0015)] +#[diag(r#"cannot convert `{$ty}` into a future in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstAwait<'tcx> { #[primary_span] pub span: Span, @@ -371,7 +516,12 @@ pub struct NonConstAwait<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_closure, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const closure in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstClosure { #[primary_span] pub span: Span, @@ -383,19 +533,33 @@ pub struct NonConstClosure { #[derive(Subdiagnostic)] pub enum NonConstClosureNote { - #[note(const_eval_closure_fndef_not_const)] + #[note("function defined here, but it is not `const`")] FnDef { #[primary_span] span: Span, }, - #[note(const_eval_fn_ptr_call)] + #[note( + r#"function pointers need an RFC before allowed to be called in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# + )] FnPtr, - #[note(const_eval_closure_call)] + #[note( + r#"closures need an RFC before allowed to be called in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# + )] Closure, } #[derive(Subdiagnostic)] -#[multipart_suggestion(const_eval_consider_dereferencing, applicability = "machine-applicable")] +#[multipart_suggestion("consider dereferencing here", applicability = "machine-applicable")] pub struct ConsiderDereferencing { pub deref: String, #[suggestion_part(code = "{deref}")] @@ -405,7 +569,12 @@ pub struct ConsiderDereferencing { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_operator, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const operator in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstOperator { #[primary_span] pub span: Span, @@ -416,28 +585,40 @@ pub struct NonConstOperator { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_deref_coercion, code = E0015)] -#[note] +#[diag(r#"cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] +#[note("attempting to deref into `{$target_ty}`")] pub struct NonConstDerefCoercion<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub kind: ConstContext, pub target_ty: Ty<'tcx>, - #[note(const_eval_target_note)] + #[note("deref defined here")] pub deref_target: Option, pub non_or_conditionally: &'static str, } #[derive(Diagnostic)] -#[diag(const_eval_live_drop, code = E0493)] +#[diag("destructor of `{$dropped_ty}` cannot be evaluated at compile-time", code = E0493)] pub struct LiveDrop<'tcx> { #[primary_span] - #[label] + #[label( + r#"the destructor for this type cannot be evaluated in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# + )] pub span: Span, pub kind: ConstContext, pub dropped_ty: Ty<'tcx>, - #[label(const_eval_dropped_at_label)] + #[label("value is dropped here")] pub dropped_at: Span, } @@ -466,51 +647,135 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { fn diagnostic_message(&self) -> DiagMessage { use UndefinedBehaviorInfo::*; - use crate::fluent_generated::*; match self { Ub(msg) => msg.clone().into(), Custom(x) => (x.msg)(), ValidationError(e) => e.diagnostic_message(), - Unreachable => const_eval_unreachable, - BoundsCheckFailed { .. } => const_eval_bounds_check_failed, - DivisionByZero => const_eval_division_by_zero, - RemainderByZero => const_eval_remainder_by_zero, - DivisionOverflow => const_eval_division_overflow, - RemainderOverflow => const_eval_remainder_overflow, - PointerArithOverflow => const_eval_pointer_arithmetic_overflow, - ArithOverflow { .. } => const_eval_overflow_arith, - ShiftOverflow { .. } => const_eval_overflow_shift, - InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, - InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, - UnterminatedCString(_) => const_eval_unterminated_c_string, - PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free, - PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds, - DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer, - DanglingIntPointer { .. } => const_eval_dangling_int_pointer, - AlignmentCheckFailed { .. } => const_eval_alignment_check_failed, - WriteToReadOnly(_) => const_eval_write_to_read_only, - DerefFunctionPointer(_) => const_eval_deref_function_pointer, - DerefVTablePointer(_) => const_eval_deref_vtable_pointer, - DerefTypeIdPointer(_) => const_eval_deref_typeid_pointer, - InvalidBool(_) => const_eval_invalid_bool, - InvalidChar(_) => const_eval_invalid_char, - InvalidTag(_) => const_eval_invalid_tag, - InvalidFunctionPointer(_) => const_eval_invalid_function_pointer, - InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer, - InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait, - InvalidStr(_) => const_eval_invalid_str, - InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown, - InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes, - DeadLocal => const_eval_dead_local, - ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch, - UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written, - UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read, + Unreachable => "entering unreachable code".into(), + BoundsCheckFailed { .. } => msg!("indexing out of bounds: the len is {$len} but the index is {$index}"), + DivisionByZero => "dividing by zero".into(), + RemainderByZero => "calculating the remainder with a divisor of zero".into(), + DivisionOverflow => "overflow in signed division (dividing MIN by -1)".into(), + RemainderOverflow => "overflow in signed remainder (dividing MIN by -1)".into(), + PointerArithOverflow => "overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`".into(), + ArithOverflow { .. } => msg!("arithmetic overflow in `{$intrinsic}`"), + ShiftOverflow { .. } => msg!("overflowing shift by {$shift_amount} in `{$intrinsic}`"), + InvalidMeta(InvalidMetaKind::SliceTooBig) => "invalid metadata in wide pointer: slice is bigger than largest supported object".into(), + InvalidMeta(InvalidMetaKind::TooBig) => "invalid metadata in wide pointer: total size is bigger than largest supported object".into(), + UnterminatedCString(_) => "reading a null-terminated string starting at {$pointer} with no null found before end of allocation".into(), + PointerUseAfterFree(_, _) => msg!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$alloc_id} has been freed, so this pointer is dangling" + ), + PointerOutOfBounds { .. } => msg!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got {$pointer} which {$ptr_offset_is_neg -> + [true] points to before the beginning of the allocation + *[false] {$inbounds_size_is_neg -> + [false] {$alloc_size_minus_ptr_offset -> + [0] is at or beyond the end of the allocation of size {$alloc_size -> + [1] 1 byte + *[x] {$alloc_size} bytes + } + [1] is only 1 byte from the end of the allocation + *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation + } + *[true] {$ptr_offset_abs -> + [0] is at the beginning of the allocation + *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation + } + } + }" + ), + DanglingIntPointer { addr: 0, .. } => msg!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got null pointer"), + DanglingIntPointer { .. } => msg!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got {$pointer} which is a dangling pointer (it has no provenance)"), + AlignmentCheckFailed { .. } => msg!( + "{$msg -> + [AccessedPtr] accessing memory + *[other] accessing memory based on pointer + } with alignment {$has}, but alignment {$required} is required" + ), + WriteToReadOnly(_) => msg!("writing to {$allocation} which is read-only"), + DerefFunctionPointer(_) => msg!("accessing {$allocation} which contains a function"), + DerefVTablePointer(_) => msg!("accessing {$allocation} which contains a vtable"), + DerefTypeIdPointer(_) => msg!("accessing {$allocation} which contains a `TypeId`"), + InvalidBool(_) => msg!("interpreting an invalid 8-bit value as a bool: 0x{$value}"), + InvalidChar(_) => msg!("interpreting an invalid 32-bit value as a char: 0x{$value}"), + InvalidTag(_) => msg!("enum value has invalid tag: {$tag}"), + InvalidFunctionPointer(_) => msg!("using {$pointer} as function pointer but it does not point to a function"), + InvalidVTablePointer(_) => msg!("using {$pointer} as vtable pointer but it does not point to a vtable"), + InvalidVTableTrait { .. } => msg!("using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected"), + InvalidStr(_) => msg!("this string is not valid UTF-8: {$err}"), + InvalidUninitBytes(None) => "using uninitialized data, but this operation requires initialized memory".into(), + InvalidUninitBytes(Some(_)) => msg!("reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory"), + DeadLocal => "accessing a dead local variable".into(), + ScalarSizeMismatch(_) => msg!("scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead"), + UninhabitedEnumVariantWritten(_) => "writing discriminant of an uninhabited enum variant".into(), + UninhabitedEnumVariantRead(_) => "read discriminant of an uninhabited enum variant".into(), InvalidNichedEnumVariantWritten { .. } => { - const_eval_invalid_niched_enum_variant_written + msg!("trying to set discriminant of a {$ty} to the niched variant, but the value does not match") } - AbiMismatchArgument { .. } => const_eval_incompatible_arg_types, - AbiMismatchReturn { .. } => const_eval_incompatible_return_types, + AbiMismatchArgument { .. } => msg!("calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty}"), + AbiMismatchReturn { .. } => msg!("calling a function with return type {$callee_ty} passing return place of type {$caller_ty}"), } } @@ -653,94 +918,174 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { fn diagnostic_message(&self) -> DiagMessage { use rustc_middle::mir::interpret::ValidationErrorKind::*; - use crate::fluent_generated::*; match self.kind { PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => { - const_eval_validation_box_to_uninhabited + msg!("{$front_matter}: encountered a box pointing to uninhabited type {$ty}") } PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_ref_to_uninhabited + msg!("{$front_matter}: encountered a reference pointing to uninhabited type {$ty}") } - PointerAsInt { .. } => const_eval_validation_pointer_as_int, - PartialPointer => const_eval_validation_partial_pointer, - MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable, - NullFnPtr { .. } => const_eval_validation_null_fn_ptr, - NeverVal => const_eval_validation_never_val, - NonnullPtrMaybeNull { .. } => const_eval_validation_nonnull_ptr_out_of_range, - PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range, - OutOfRange { .. } => const_eval_validation_out_of_range, - UnsafeCellInImmutable => const_eval_validation_unsafe_cell, - UninhabitedVal { .. } => const_eval_validation_uninhabited_val, - InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag, - UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant, - Uninit { .. } => const_eval_validation_uninit, - InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr, - InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait, + PointerAsInt { .. } => { + msg!("{$front_matter}: encountered a pointer, but {$expected}") + } + PartialPointer => { + msg!("{$front_matter}: encountered a partial pointer or a mix of pointers") + } + MutableRefToImmutable => { + msg!( + "{$front_matter}: encountered mutable reference or box pointing to read-only memory" + ) + } + NullFnPtr { .. } => { + msg!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null + } function pointer" + ) + } + NeverVal => { + msg!("{$front_matter}: encountered a value of the never type `!`") + } + NonnullPtrMaybeNull { .. } => { + msg!( + "{$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero" + ) + } + PtrOutOfRange { .. } => { + msg!( + "{$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}" + ) + } + OutOfRange { .. } => { + msg!("{$front_matter}: encountered {$value}, but expected something {$in_range}") + } + UnsafeCellInImmutable => { + msg!("{$front_matter}: encountered `UnsafeCell` in read-only memory") + } + UninhabitedVal { .. } => { + msg!("{$front_matter}: encountered a value of uninhabited type `{$ty}`") + } + InvalidEnumTag { .. } => { + msg!("{$front_matter}: encountered {$value}, but expected a valid enum tag") + } + UninhabitedEnumVariant => { + msg!("{$front_matter}: encountered an uninhabited enum variant") + } + Uninit { .. } => { + msg!("{$front_matter}: encountered uninitialized memory, but {$expected}") + } + InvalidVTablePtr { .. } => { + msg!("{$front_matter}: encountered {$value}, but expected a vtable pointer") + } + InvalidMetaWrongTrait { .. } => { + msg!( + "{$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`" + ) + } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => { - const_eval_validation_invalid_box_slice_meta + msg!( + "{$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object" + ) } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_invalid_ref_slice_meta + msg!( + "{$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object" + ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => { - const_eval_validation_invalid_box_meta + msg!( + "{$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object" + ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_invalid_ref_meta + msg!( + "{$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object" + ) } UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_unaligned_ref + msg!( + "{$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})" + ) + } + UnalignedPtr { ptr_kind: PointerKind::Box, .. } => { + msg!( + "{$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})" + ) } - UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box, - NullPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_null_box, - NullPtr { ptr_kind: PointerKind::Ref(_), .. } => const_eval_validation_null_ref, + NullPtr { ptr_kind: PointerKind::Box, .. } => { + msg!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null + } box" + ) + } + NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { + msg!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null + } reference" + ) + } DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { - const_eval_validation_dangling_box_no_provenance + msg!("{$front_matter}: encountered a dangling box ({$pointer} has no provenance)") } DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_dangling_ref_no_provenance + msg!( + "{$front_matter}: encountered a dangling reference ({$pointer} has no provenance)" + ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => { - const_eval_validation_dangling_box_out_of_bounds + msg!( + "{$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)" + ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_dangling_ref_out_of_bounds + msg!( + "{$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)" + ) } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => { - const_eval_validation_dangling_box_use_after_free + msg!("{$front_matter}: encountered a dangling box (use-after-free)") } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_dangling_ref_use_after_free + msg!("{$front_matter}: encountered a dangling reference (use-after-free)") + } + InvalidBool { .. } => { + msg!("{$front_matter}: encountered {$value}, but expected a boolean") + } + InvalidChar { .. } => { + msg!( + "{$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" + ) + } + InvalidFnPtr { .. } => { + msg!("{$front_matter}: encountered {$value}, but expected a function pointer") } - InvalidBool { .. } => const_eval_validation_invalid_bool, - InvalidChar { .. } => const_eval_validation_invalid_char, - InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr, } } fn add_args(self, err: &mut Diag<'_, G>) { + use rustc_errors::msg; use rustc_middle::mir::interpret::ValidationErrorKind::*; - use crate::fluent_generated as fluent; - if let PointerAsInt { .. } | PartialPointer = self.kind { - err.help(fluent::const_eval_ptr_as_bytes_1); - err.help(fluent::const_eval_ptr_as_bytes_2); + err.help(msg!("this code performed an operation that depends on the underlying bytes representing a pointer")); + err.help(msg!("the absolute address of a pointer is not known at compile-time, so such operations are not supported")); } let message = if let Some(path) = self.path { err.dcx.eagerly_translate_to_string( - fluent::const_eval_validation_front_matter_invalid_value_with_path, + msg!("constructing invalid value at {$path}"), [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), ) } else { - err.dcx.eagerly_translate_to_string( - fluent::const_eval_validation_front_matter_invalid_value, - [].into_iter(), - ) + err.dcx.eagerly_translate_to_string(msg!("constructing invalid value"), [].into_iter()) }; err.arg("front_matter", message); @@ -753,17 +1098,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { let WrappingRange { start: lo, end: hi } = r; assert!(hi <= max_hi); let msg = if lo > hi { - fluent::const_eval_range_wrapping + msg!("less or equal to {$hi}, or greater or equal to {$lo}") } else if lo == hi { - fluent::const_eval_range_singular + msg!("equal to {$lo}") } else if lo == 0 { assert!(hi < max_hi, "should not be printing if the range covers everything"); - fluent::const_eval_range_upper + msg!("less or equal to {$hi}") } else if hi == max_hi { assert!(lo > 0, "should not be printing if the range covers everything"); - fluent::const_eval_range_lower + msg!("greater or equal to {$lo}") } else { - fluent::const_eval_range + msg!("in the range {$lo}..={$hi}") }; let args = [ @@ -781,17 +1126,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { - ExpectedKind::Reference => fluent::const_eval_validation_expected_ref, - ExpectedKind::Box => fluent::const_eval_validation_expected_box, - ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr, - ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar, - ExpectedKind::Bool => fluent::const_eval_validation_expected_bool, - ExpectedKind::Char => fluent::const_eval_validation_expected_char, - ExpectedKind::Float => fluent::const_eval_validation_expected_float, - ExpectedKind::Int => fluent::const_eval_validation_expected_int, - ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr, - ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag, - ExpectedKind::Str => fluent::const_eval_validation_expected_str, + ExpectedKind::Reference => msg!("expected a reference"), + ExpectedKind::Box => msg!("expected a box"), + ExpectedKind::RawPtr => msg!("expected a raw pointer"), + ExpectedKind::InitScalar => msg!("expected initialized scalar value"), + ExpectedKind::Bool => msg!("expected a boolean"), + ExpectedKind::Char => msg!("expected a unicode scalar value"), + ExpectedKind::Float => msg!("expected a floating point number"), + ExpectedKind::Int => msg!("expected an integer"), + ExpectedKind::FnPtr => msg!("expected a function pointer"), + ExpectedKind::EnumTag => msg!("expected a valid enum tag"), + ExpectedKind::Str => msg!("expected a string"), }; let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter()); err.arg("expected", msg); @@ -838,25 +1183,32 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { impl ReportErrorExt for UnsupportedOpInfo { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { UnsupportedOpInfo::Unsupported(s) => s.clone().into(), - UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field, - UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local, - UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_read, - UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int, - UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static, - UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, + UnsupportedOpInfo::ExternTypeField => { + "`extern type` field does not have a known offset".into() + } + UnsupportedOpInfo::UnsizedLocal => "unsized locals are not supported".into(), + UnsupportedOpInfo::ReadPartialPointer(_) => { + msg!("unable to read parts of a pointer from memory at {$ptr}") + } + UnsupportedOpInfo::ReadPointerAsInt(_) => "unable to turn pointer into integer".into(), + UnsupportedOpInfo::ThreadLocalStatic(_) => { + msg!("cannot access thread local static `{$did}`") + } + UnsupportedOpInfo::ExternStatic(_) => { + msg!("cannot access extern static `{$did}`") + } } + .into() } fn add_args(self, diag: &mut Diag<'_, G>) { use UnsupportedOpInfo::*; - use crate::fluent_generated::*; if let ReadPointerAsInt(_) | ReadPartialPointer(_) = self { - diag.help(const_eval_ptr_as_bytes_1); - diag.help(const_eval_ptr_as_bytes_2); + diag.help("this code performed an operation that depends on the underlying bytes representing a pointer"); + diag.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported"); } match self { // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to @@ -901,10 +1253,12 @@ impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> { impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { - InvalidProgramInfo::TooGeneric => const_eval_too_generic, - InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported, + InvalidProgramInfo::TooGeneric => "encountered overly generic constant".into(), + InvalidProgramInfo::AlreadyReported(_) => { + "an error has already been reported elsewhere (this should not usually be printed)" + .into() + } InvalidProgramInfo::Layout(e) => e.diagnostic_message(), } } @@ -926,13 +1280,19 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { impl ReportErrorExt for ResourceExhaustionInfo { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { - ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached, - ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted, - ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, - ResourceExhaustionInfo::Interrupted => const_eval_interrupted, + ResourceExhaustionInfo::StackFrameLimitReached => { + "reached the configured maximum number of stack frames" + } + ResourceExhaustionInfo::MemoryExhausted => { + "tried to allocate more memory than available to compiler" + } + ResourceExhaustionInfo::AddressSpaceFull => { + "there are no more free addresses in the address space" + } + ResourceExhaustionInfo::Interrupted => "compilation was interrupted", } + .into() } fn add_args(self, _: &mut Diag<'_, G>) {} } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 9c8ca44c5e8f..b17740f57f78 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -1,10 +1,12 @@ //! Manages calling a concrete function (with known MIR body) with argument passing, //! and returning the return value to the caller. + use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_data_structures::assert_matches; +use rustc_errors::msg; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; @@ -19,8 +21,8 @@ use super::{ Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, StackPopInfo, interp_ok, throw_ub, throw_ub_custom, throw_unsup_format, }; +use crate::enter_trace_span; use crate::interpret::EnteredTraceSpan; -use crate::{enter_trace_span, fluent_generated as fluent}; /// An argument passed to a function. #[derive(Clone, Debug)] @@ -89,6 +91,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (_, field) = layout.non_1zst_field(self).unwrap(); self.unfold_transparent(field, may_unfold) } + ty::Pat(base, _) => self.layout_of(*base).expect( + "if the layout of a pattern type could be computed, so can the layout of its base", + ), // Not a transparent type, no further unfolding. _ => layout, } @@ -292,7 +297,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // Find next caller arg. let Some((caller_arg, caller_abi)) = caller_args.next() else { - throw_ub_custom!(fluent::const_eval_not_enough_caller_args); + throw_ub_custom!(msg!("calling a function with fewer arguments than it requires")); }; assert_eq!(caller_arg.layout().layout, caller_abi.layout.layout); // Sadly we cannot assert that `caller_arg.layout().ty` and `caller_abi.layout.ty` are @@ -359,7 +364,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if caller_fn_abi.conv != callee_fn_abi.conv { throw_ub_custom!( - fluent::const_eval_incompatible_calling_conventions, + rustc_errors::msg!( + "calling a function with calling convention \"{$callee_conv}\" using calling convention \"{$caller_conv}\"" + ), callee_conv = format!("{}", callee_fn_abi.conv), caller_conv = format!("{}", caller_fn_abi.conv), ) @@ -490,7 +497,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { "mismatch between callee ABI and callee body arguments" ); if caller_args.next().is_some() { - throw_ub_custom!(fluent::const_eval_too_many_caller_args); + throw_ub_custom!(msg!("calling a function with more arguments than it expected")); } // Don't forget to check the return type! if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? { @@ -690,7 +697,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let vtable_entries = self.vtable_entries(receiver_trait.principal(), dyn_ty); let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else { // FIXME(fee1-dead) these could be variants of the UB info enum instead of this - throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method); + throw_ub_custom!(msg!( + "`dyn` call trying to call something that is not a method" + )); }; trace!("Virtual call dispatches to {fn_inst:#?}"); // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that @@ -887,7 +896,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } ); if unwinding && self.frame_idx() == 0 { - throw_ub_custom!(fluent::const_eval_unwind_past_top); + throw_ub_custom!(msg!("unwinding past the topmost frame of the stack")); } // Get out the return value. Must happen *before* the frame is popped as we have to get the diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 43de2e7f078a..6ea83167157c 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -2,6 +2,7 @@ use rustc_abi::{FieldIdx, Integer}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, FloatConvert}; use rustc_data_structures::assert_matches; +use rustc_errors::msg; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; @@ -15,8 +16,8 @@ use super::{ FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub, throw_ub_custom, }; +use crate::enter_trace_span; use crate::interpret::Writeable; -use crate::{enter_trace_span, fluent_generated as fluent}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn cast( @@ -138,7 +139,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely... if src.layout.size != dest.layout.size { throw_ub_custom!( - fluent::const_eval_invalid_transmute, + msg!( + "transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}`" + ), src_bytes = src.layout.size.bytes(), dest_bytes = dest.layout.size.bytes(), src = src.layout.ty, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index b72a50a0bfce..c2f772d56075 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,7 +1,7 @@ use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_data_structures::debug_assert_matches; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxtHandle, msg}; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; @@ -23,7 +23,7 @@ use super::{ MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom, }; -use crate::{ReportErrorExt, enter_trace_span, fluent_generated as fluent, util}; +use crate::{ReportErrorExt, enter_trace_span, util}; pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// Stores the `Machine` instance. @@ -555,7 +555,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), mir::UnwindAction::Continue => Right(self.frame_mut().body.span), mir::UnwindAction::Unreachable => { - throw_ub_custom!(fluent::const_eval_unreachable_unwind); + throw_ub_custom!(msg!( + "unwinding past a stack frame that does not allow unwinding" + )); } mir::UnwindAction::Terminate(reason) => { self.frame_mut().loc = Right(self.frame_mut().body.span); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e526f6120689..c9a3b578e793 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,12 +7,13 @@ mod simd; use rustc_abi::{FIRST_VARIANT, FieldIdx, HasDataLayout, Size, VariantIdx}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_data_structures::assert_matches; +use rustc_errors::msg; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint}; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug, ty}; use rustc_span::{Symbol, sym}; use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; @@ -25,7 +26,6 @@ use super::{ PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format, }; -use crate::fluent_generated as fluent; use crate::interpret::Writeable; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -73,6 +73,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty: Ty<'tcx>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> { + debug_assert!( + !ty.has_erasable_regions(), + "type {ty:?} has regions that need erasing before writing a TypeId", + ); + let tcx = self.tcx; let type_id_hash = tcx.type_id_hash(ty).as_u128(); let op = self.const_val_to_op( @@ -438,7 +443,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { _ => { // Not into the same allocation -- this is UB. throw_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + msg!( + "`{$name}` called on two different pointers that are not both derived from the same allocation" + ), name = intrinsic_name, ); } @@ -459,7 +466,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( - fluent::const_eval_offset_from_unsigned_overflow, + msg!( + "`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> + [true] address + *[false] offset + } than second: {$a_offset} < {$b_offset}" + ), a_offset = a_offset, b_offset = b_offset, is_addr = is_addr, @@ -471,7 +483,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let dist = val.to_target_isize(self)?; if dist >= 0 || i128::from(dist) == self.pointer_size().signed_int_min() { throw_ub_custom!( - fluent::const_eval_offset_from_underflow, + msg!( + "`{$name}` called when first pointer is too far before second" + ), name = intrinsic_name, ); } @@ -483,7 +497,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // because they were more than isize::MAX apart. if dist < 0 { throw_ub_custom!( - fluent::const_eval_offset_from_overflow, + msg!( + "`{$name}` called when first pointer is too far ahead of second" + ), name = intrinsic_name, ); } @@ -502,12 +518,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { && a_alloc_id == b_alloc_id { err_ub_custom!( - fluent::const_eval_offset_from_out_of_bounds, + msg!("`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation"), name = intrinsic_name, ) } else { err_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) } @@ -522,7 +538,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .map_err_kind(|_| { // Make the error more specific. err_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) })?; @@ -752,7 +768,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let op = self.eval_operand(op, None)?; let cond = self.read_scalar(&op)?.to_bool()?; if !cond { - throw_ub_custom!(fluent::const_eval_assume_false); + throw_ub_custom!(msg!("`assume` called with `false`")); } interp_ok(()) } @@ -782,7 +798,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let bits_out = match name { sym::ctpop => u128::from(bits.count_ones()), sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => { - throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,); + throw_ub_custom!(msg!("`{$name}` called on 0"), name = name,); } sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra, sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra, @@ -815,7 +831,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // sign does not matter for 0 test, so `to_bits` is fine if rem.to_scalar().to_bits(a.layout.size)? != 0 { throw_ub_custom!( - fluent::const_eval_exact_div_has_remainder, + msg!("exact_div: {$a} cannot be divided by {$b} without remainder"), a = format!("{a}"), b = format!("{b}") ) @@ -900,7 +916,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let size = self.compute_size_in_bytes(size, count).ok_or_else(|| { err_ub_custom!( - fluent::const_eval_size_overflow, + msg!("overflow computing total size of `{$name}`"), name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" } ) })?; @@ -963,9 +979,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. - let len = self - .compute_size_in_bytes(layout.size, count) - .ok_or_else(|| err_ub_custom!(fluent::const_eval_size_overflow, name = name))?; + let len = self.compute_size_in_bytes(layout.size, count).ok_or_else(|| { + err_ub_custom!(msg!("overflow computing total size of `{$name}`"), name = name) + })?; let bytes = std::iter::repeat_n(byte, len.bytes_usize()); self.write_bytes_ptr(dst, bytes) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a6c8b28cce9f..0049feee523c 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,6 +15,7 @@ use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_errors::msg; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, throw_ub_format}; @@ -27,7 +28,6 @@ use super::{ err_ub_custom, interp_ok, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, }; use crate::const_eval::ConstEvalErrKind; -use crate::fluent_generated as fluent; #[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { @@ -291,7 +291,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { throw_ub_custom!( - fluent::const_eval_realloc_or_alloc_with_offset, + msg!( + "{$kind -> + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" + ), ptr = format!("{ptr:?}"), kind = "realloc" ); @@ -371,7 +377,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if offset.bytes() != 0 { throw_ub_custom!( - fluent::const_eval_realloc_or_alloc_with_offset, + msg!( + "{$kind -> + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" + ), ptr = format!("{ptr:?}"), kind = "dealloc", ); @@ -382,28 +394,56 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return Err(match self.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Function { .. }) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + msg!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" + ), alloc_id = alloc_id, kind = "fn", ) } Some(GlobalAlloc::VTable(..)) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + msg!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" + ), alloc_id = alloc_id, kind = "vtable", ) } Some(GlobalAlloc::TypeId { .. }) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + msg!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" + ), alloc_id = alloc_id, kind = "typeid", ) } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + msg!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" + ), alloc_id = alloc_id, kind = "static_mem" ) @@ -414,11 +454,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; if alloc.mutability.is_not() { - throw_ub_custom!(fluent::const_eval_dealloc_immutable, alloc = alloc_id,); + throw_ub_custom!(msg!("deallocating immutable allocation {$alloc}"), alloc = alloc_id,); } if alloc_kind != kind { throw_ub_custom!( - fluent::const_eval_dealloc_kind_mismatch, + msg!( + "deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation" + ), alloc = alloc_id, alloc_kind = format!("{alloc_kind}"), kind = format!("{kind}"), @@ -427,7 +469,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { throw_ub_custom!( - fluent::const_eval_dealloc_incorrect_layout, + msg!( + "incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found}" + ), alloc = alloc_id, size = alloc.size().bytes(), align = alloc.align.bytes(), @@ -1546,7 +1590,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if (src_offset <= dest_offset && src_offset + size > dest_offset) || (dest_offset <= src_offset && dest_offset + size > src_offset) { - throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping); + throw_ub_custom!(msg!( + "`copy_nonoverlapping` called on overlapping ranges" + )); } } } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d472c14253b5..fb07d5f0d0d6 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -5,8 +5,8 @@ use either::{Either, Left, Right}; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_data_structures::assert_matches; -use rustc_middle::ty::Ty; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use tracing::field::Empty; use tracing::{instrument, trace}; @@ -884,10 +884,38 @@ where dest.layout().ty, ); } + // If the source has padding, we want to always do a mem-to-mem copy to ensure consistent + // padding in the target independent of layout choices. + let src_has_padding = match src.layout().backend_repr { + BackendRepr::Scalar(_) => false, + BackendRepr::ScalarPair(left, right) + if matches!(src.layout().ty.kind(), ty::Ref(..) | ty::RawPtr(..)) => + { + // Wide pointers never have padding, so we can avoid calling `size()`. + debug_assert_eq!(left.size(self) + right.size(self), src.layout().size); + false + } + BackendRepr::ScalarPair(left, right) => { + let left_size = left.size(self); + let right_size = right.size(self); + // We have padding if the sizes don't add up to the total. + left_size + right_size != src.layout().size + } + // Everything else can only exist in memory anyway, so it doesn't matter. + BackendRepr::SimdVector { .. } + | BackendRepr::ScalableVector { .. } + | BackendRepr::Memory { .. } => true, + }; - // Let us see if the layout is simple so we take a shortcut, - // avoid force_allocation. - let src = match self.read_immediate_raw(src)? { + let src_val = if src_has_padding { + // Do our best to get an mplace. If there's no mplace, then this is stored as an + // "optimized" local, so its padding is definitely uninitialized and we are fine. + src.to_op(self)?.as_mplace_or_imm() + } else { + // Do our best to get an immediate, to avoid having to force_allocate the destination. + self.read_immediate_raw(src)? + }; + let src = match src_val { Right(src_val) => { assert!(!src.layout().is_unsized()); assert!(!dest.layout().is_unsized()); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 027e634ef7f7..db72c02e308c 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -97,7 +97,7 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug { } /// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for - /// reading from this thing. + /// reading from this thing. This will never actually do a read from memory! fn to_op>( &self, ecx: &InterpCx<'tcx, M>, diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 1266e15c682f..ead1ee9bf85e 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,6 +1,6 @@ // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(array_try_map)] -#![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] @@ -26,8 +26,6 @@ use rustc_middle::util::Providers; pub use self::errors::ReportErrorExt; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { const_eval::provide(&mut providers.queries); providers.queries.tag_for_variant = const_eval::tag_for_variant_provider; diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index f358ffffb47d..0332ff681082 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -9,7 +9,7 @@ arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" either = "1.0" elsa = "1.11.0" -ena = "0.14.3" +ena = "0.14.4" indexmap = "2.12.1" jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "12.0.1" diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 85877d73519a..594d6d294d75 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,16 +10,17 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] +#![cfg_attr(bootstrap, feature(assert_matches))] +#![cfg_attr(bootstrap, feature(cold_path))] +#![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![feature(allocator_api)] #![feature(ascii_char)] #![feature(ascii_char_variants)] -#![feature(assert_matches)] #![feature(auto_traits)] #![feature(cfg_select)] #![feature(const_default)] #![feature(const_trait_impl)] -#![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(extend_one)] #![feature(file_buffered)] @@ -30,7 +31,6 @@ #![feature(ptr_alignment_type)] #![feature(rustc_attrs)] #![feature(sized_hierarchy)] -#![feature(test)] #![feature(thread_id_value)] #![feature(trusted_len)] #![feature(type_alias_impl_trait)] @@ -49,6 +49,10 @@ pub use std::{assert_matches, debug_assert_matches}; pub use atomic_ref::AtomicRef; pub use ena::{snapshot_vec, undo_log, unify}; +// Re-export `hashbrown::hash_table`, because it's part of our API +// (via `ShardedHashMap`), and because it lets other compiler crates use the +// lower-level `HashTable` API without a tricky `hashbrown` dependency. +pub use hashbrown::hash_table; pub use rustc_index::static_assert_size; // Re-export some data-structure crates which are part of our public API. pub use {either, indexmap, smallvec, thin_vec}; diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 4a9551a60cf9..cab57edb8946 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -85,12 +85,11 @@ use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::error::Error; use std::fmt::Display; -use std::intrinsics::unlikely; use std::path::Path; use std::sync::Arc; use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; -use std::{fs, process}; +use std::{fs, hint, process}; pub use measureme::EventId; use measureme::{EventIdBuilder, Profiler, SerializableString, StringId}; @@ -427,7 +426,8 @@ impl SelfProfilerRef { .unwrap() .increment_query_cache_hit_counters(QueryInvocationId(query_invocation_id.0)); } - if unlikely(profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS)) { + if profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS) { + hint::cold_path(); profiler_ref.instant_query_event( |profiler| profiler.query_cache_hit_event_kind, query_invocation_id, @@ -437,7 +437,8 @@ impl SelfProfilerRef { // We check both kinds of query cache hit events at once, to reduce overhead in the // common case (with self-profile disabled). - if unlikely(self.event_filter_mask.intersects(EventFilter::QUERY_CACHE_HIT_COMBINED)) { + if self.event_filter_mask.intersects(EventFilter::QUERY_CACHE_HIT_COMBINED) { + hint::cold_path(); cold_call(self, query_invocation_id); } } @@ -995,12 +996,14 @@ cfg_select! { } unix => { pub fn get_resident_set_size() -> Option { + use libc::{sysconf, _SC_PAGESIZE}; let field = 1; let contents = fs::read("/proc/self/statm").ok()?; let contents = String::from_utf8(contents).ok()?; let s = contents.split_whitespace().nth(field)?; let npages = s.parse::().ok()?; - Some(npages * 4096) + // SAFETY: `sysconf(_SC_PAGESIZE)` has no side effects and is safe to call. + Some(npages * unsafe { sysconf(_SC_PAGESIZE) } as usize) } } _ => { diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 5de9413cf15d..e10ccccad5bb 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use std::{iter, mem}; use either::Either; -use hashbrown::hash_table::{Entry, HashTable}; +use hashbrown::hash_table::{self, Entry, HashTable}; use crate::fx::FxHasher; use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe}; @@ -140,7 +140,7 @@ pub fn shards() -> usize { 1 } -pub type ShardedHashMap = Sharded>; +pub type ShardedHashMap = Sharded>; impl ShardedHashMap { pub fn with_capacity(cap: usize) -> Self { diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 3a64c924cc22..9fb4d4352c2f 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -607,7 +607,7 @@ where /// result (for example, using a `Fingerprint` produced while /// hashing `Span`s when a `Fingerprint` without `Span`s is /// being requested) -#[derive(Clone, Hash, Eq, PartialEq, Debug)] +#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)] pub struct HashingControls { pub hash_spans: bool, } diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 3881f3c2aa84..31768fe189ae 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -41,7 +41,8 @@ pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard}; pub use self::lock::{Lock, LockGuard, Mode}; pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode}; pub use self::parallel::{ - broadcast, join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in, + broadcast, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn, + try_par_for_each_in, }; pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec}; pub use self::worker_local::{Registry, WorkerLocal}; diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs index 6338afb92c34..fb2dcb25556a 100644 --- a/compiler/rustc_data_structures/src/sync/freeze.rs +++ b/compiler/rustc_data_structures/src/sync/freeze.rs @@ -1,5 +1,5 @@ use std::cell::UnsafeCell; -use std::intrinsics::likely; +use std::hint; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; @@ -60,10 +60,11 @@ impl FreezeLock { /// Get the inner value if frozen. #[inline] pub fn get(&self) -> Option<&T> { - if likely(self.frozen.load(Ordering::Acquire)) { + if self.frozen.load(Ordering::Acquire) { // SAFETY: This is frozen so the data cannot be modified. unsafe { Some(&*self.data.get()) } } else { + hint::cold_path(); None } } diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index a8161c515115..f183af0c0dab 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -1,7 +1,7 @@ //! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true. //! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits. -use std::fmt; +use std::{fmt, hint}; #[derive(Clone, Copy, PartialEq)] pub enum Mode { @@ -10,7 +10,6 @@ pub enum Mode { } use std::cell::{Cell, UnsafeCell}; -use std::intrinsics::unlikely; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; @@ -92,7 +91,8 @@ pub struct Lock { impl Lock { #[inline(always)] pub fn new(inner: T) -> Self { - let (mode, mode_union) = if unlikely(mode::might_be_dyn_thread_safe()) { + let (mode, mode_union) = if mode::might_be_dyn_thread_safe() { + hint::cold_path(); // Create the lock with synchronization enabled using the `RawMutex` type. (Mode::Sync, ModeUnion { sync: ManuallyDrop::new(RawMutex::INIT) }) } else { @@ -150,7 +150,8 @@ impl Lock { unsafe { match mode { Mode::NoSync => { - if unlikely(self.mode_union.no_sync.replace(LOCKED) == LOCKED) { + if self.mode_union.no_sync.replace(LOCKED) == LOCKED { + hint::cold_path(); lock_held() } } diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index b515c0bee8a6..23f5cbc43452 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -56,41 +56,6 @@ where (a.unwrap(), b.unwrap()) } -/// Runs a list of blocks in parallel. The first block is executed immediately on -/// the current thread. Use that for the longest running block. -#[macro_export] -macro_rules! parallel { - (impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => { - parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) - }; - (impl $fblock:block [$($blocks:expr,)*] []) => { - $crate::sync::parallel_guard(|guard| { - $crate::sync::scope(|s| { - $( - let block = $crate::sync::FromDyn::from(|| $blocks); - s.spawn(move |_| { - guard.run(move || block.into_inner()()); - }); - )* - guard.run(|| $fblock); - }); - }); - }; - ($fblock:block, $($blocks:block),*) => { - if $crate::sync::is_dyn_thread_safe() { - // Reverse the order of the later blocks since Rayon executes them in reverse order - // when using a single thread. This ensures the execution order matches that - // of a single threaded rustc. - parallel!(impl $fblock [] [$($blocks),*]); - } else { - $crate::sync::parallel_guard(|guard| { - guard.run(|| $fblock); - $(guard.run(|| $blocks);)* - }); - } - }; - } - pub fn spawn(func: impl FnOnce() + DynSend + 'static) { if mode::is_dyn_thread_safe() { let func = FromDyn::from(func); @@ -102,18 +67,43 @@ pub fn spawn(func: impl FnOnce() + DynSend + 'static) { } } -// This function only works when `mode::is_dyn_thread_safe()`. -pub fn scope<'scope, OP, R>(op: OP) -> R -where - OP: FnOnce(&rustc_thread_pool::Scope<'scope>) -> R + DynSend, - R: DynSend, -{ - let op = FromDyn::from(op); - rustc_thread_pool::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() +/// Runs the functions in parallel. +/// +/// The first function is executed immediately on the current thread. +/// Use that for the longest running function for better scheduling. +pub fn par_fns(funcs: &mut [&mut (dyn FnMut() + DynSend)]) { + parallel_guard(|guard: &ParallelGuard| { + if mode::is_dyn_thread_safe() { + let funcs = FromDyn::from(funcs); + rustc_thread_pool::scope(|s| { + let Some((first, rest)) = funcs.into_inner().split_at_mut_checked(1) else { + return; + }; + + // Reverse the order of the later functions since Rayon executes them in reverse + // order when using a single thread. This ensures the execution order matches + // that of a single threaded rustc. + for f in rest.iter_mut().rev() { + let f = FromDyn::from(f); + s.spawn(|_| { + guard.run(|| (f.into_inner())()); + }); + } + + // Run the first function without spawning to + // ensure it executes immediately on this thread. + guard.run(|| first[0]()); + }); + } else { + for f in funcs { + guard.run(|| f()); + } + } + }); } #[inline] -pub fn join(oper_a: A, oper_b: B) -> (RA, RB) +pub fn par_join(oper_a: A, oper_b: B) -> (RA, RB) where A: FnOnce() -> RA + DynSend, B: FnOnce() -> RB + DynSend, @@ -138,34 +128,21 @@ fn par_slice( guard: &ParallelGuard, for_each: impl Fn(&mut I) + DynSync + DynSend, ) { - struct State<'a, F> { - for_each: FromDyn, - guard: &'a ParallelGuard, - group: usize, - } - - fn par_rec( - items: &mut [I], - state: &State<'_, F>, - ) { - if items.len() <= state.group { - for item in items { - state.guard.run(|| (state.for_each)(item)); - } - } else { - let (left, right) = items.split_at_mut(items.len() / 2); - let mut left = state.for_each.derive(left); - let mut right = state.for_each.derive(right); - rustc_thread_pool::join(move || par_rec(*left, state), move || par_rec(*right, state)); + let for_each = FromDyn::from(for_each); + let mut items = for_each.derive(items); + rustc_thread_pool::scope(|s| { + let proof = items.derive(()); + let group_size = std::cmp::max(items.len() / 128, 1); + for group in items.chunks_exact_mut(group_size) { + let group = proof.derive(group); + s.spawn(|_| { + let mut group = group; + for i in group.iter_mut() { + guard.run(|| for_each(i)); + } + }); } - } - - let state = State { - for_each: FromDyn::from(for_each), - guard, - group: std::cmp::max(items.len() / 128, 1), - }; - par_rec(items, &state) + }); } pub fn par_for_each_in>( diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs index 599970663db8..f9f5871c8d61 100644 --- a/compiler/rustc_data_structures/src/vec_cache.rs +++ b/compiler/rustc_data_structures/src/vec_cache.rs @@ -29,8 +29,6 @@ struct Slot { struct SlotIndex { // the index of the bucket in VecCache (0 to 20) bucket_idx: usize, - // number of entries in that bucket - entries: usize, // the index of the slot within the bucket index_in_bucket: usize, } @@ -39,12 +37,12 @@ struct SlotIndex { // compile-time. Visiting all powers of two is enough to hit all the buckets. // // We confirm counts are accurate in the slot_index_exhaustive test. -const ENTRIES_BY_BUCKET: [usize; 21] = { - let mut entries = [0; 21]; +const ENTRIES_BY_BUCKET: [usize; BUCKETS] = { + let mut entries = [0; BUCKETS]; let mut key = 0; loop { let si = SlotIndex::from_index(key); - entries[si.bucket_idx] = si.entries; + entries[si.bucket_idx] = si.entries(); if key == 0 { key = 1; } else if key == (1 << 31) { @@ -56,7 +54,14 @@ const ENTRIES_BY_BUCKET: [usize; 21] = { entries }; +const BUCKETS: usize = 21; + impl SlotIndex { + /// The total possible number of entries in the bucket + const fn entries(&self) -> usize { + if self.bucket_idx == 0 { 1 << 12 } else { 1 << (self.bucket_idx + 11) } + } + // This unpacks a flat u32 index into identifying which bucket it belongs to and the offset // within that bucket. As noted in the VecCache docs, buckets double in size with each index. // Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce @@ -70,18 +75,13 @@ impl SlotIndex { const fn from_index(idx: u32) -> Self { const FIRST_BUCKET_SHIFT: usize = 12; if idx < (1 << FIRST_BUCKET_SHIFT) { - return SlotIndex { - bucket_idx: 0, - entries: 1 << FIRST_BUCKET_SHIFT, - index_in_bucket: idx as usize, - }; + return SlotIndex { bucket_idx: 0, index_in_bucket: idx as usize }; } // We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away) let bucket = idx.ilog2() as usize; let entries = 1 << bucket; SlotIndex { bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1, - entries, index_in_bucket: idx as usize - entries, } } @@ -98,7 +98,7 @@ impl SlotIndex { if ptr.is_null() { return None; } - assert!(self.index_in_bucket < self.entries); + debug_assert!(self.index_in_bucket < self.entries()); // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this // must be inbounds. let slot = unsafe { ptr.add(self.index_in_bucket) }; @@ -126,11 +126,12 @@ impl SlotIndex { fn bucket_ptr(&self, bucket: &AtomicPtr>) -> *mut Slot { let ptr = bucket.load(Ordering::Acquire); - if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr } + if ptr.is_null() { Self::initialize_bucket(bucket, self.bucket_idx) } else { ptr } } #[cold] - fn initialize_bucket(&self, bucket: &AtomicPtr>) -> *mut Slot { + #[inline(never)] + fn initialize_bucket(bucket: &AtomicPtr>, bucket_idx: usize) -> *mut Slot { static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); // If we are initializing the bucket, then acquire a global lock. @@ -144,8 +145,8 @@ impl SlotIndex { // OK, now under the allocator lock, if we're still null then it's definitely us that will // initialize this bucket. if ptr.is_null() { - let bucket_layout = - std::alloc::Layout::array::>(self.entries as usize).unwrap(); + let bucket_len = SlotIndex { bucket_idx, index_in_bucket: 0 }.entries(); + let bucket_layout = std::alloc::Layout::array::>(bucket_len).unwrap(); // This is more of a sanity check -- this code is very cold, so it's safe to pay a // little extra cost here. assert!(bucket_layout.size() > 0); @@ -171,7 +172,7 @@ impl SlotIndex { let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) }; let ptr = self.bucket_ptr(bucket); - assert!(self.index_in_bucket < self.entries); + debug_assert!(self.index_in_bucket < self.entries()); // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this // must be inbounds. let slot = unsafe { ptr.add(self.index_in_bucket) }; @@ -204,6 +205,31 @@ impl SlotIndex { Err(_) => false, } } + + /// Inserts into the map, given that the slot is unique, so it won't race with other threads. + #[inline] + unsafe fn put_unique(&self, buckets: &[AtomicPtr>; 21], value: V, extra: u32) { + // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e., + // in-bounds of buckets. + let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) }; + let ptr = self.bucket_ptr(bucket); + + debug_assert!(self.index_in_bucket < self.entries()); + // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this + // must be inbounds. + let slot = unsafe { ptr.add(self.index_in_bucket) }; + + // SAFETY: We known our slot is unique as a precondition of this function, so this can't race. + unsafe { + (&raw mut (*slot).value).write(value); + } + + // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for + // AtomicU32 access. + let index_and_lock = unsafe { &(*slot).index_and_lock }; + + index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release); + } } /// In-memory cache for queries whose keys are densely-numbered IDs @@ -229,11 +255,11 @@ pub struct VecCache { // Bucket 19: 1073741824 // Bucket 20: 2147483648 // The total number of entries if all buckets are initialized is u32::MAX-1. - buckets: [AtomicPtr>; 21], + buckets: [AtomicPtr>; BUCKETS], // In the compiler's current usage these are only *read* during incremental and self-profiling. // They are an optimization over iterating the full buckets array. - present: [AtomicPtr>; 21], + present: [AtomicPtr>; BUCKETS], len: AtomicUsize, key: PhantomData<(K, I)>, @@ -307,9 +333,11 @@ where let slot_idx = SlotIndex::from_index(key); if slot_idx.put(&self.buckets, value, index.index() as u32) { let present_idx = self.len.fetch_add(1, Ordering::Relaxed); - let slot = SlotIndex::from_index(present_idx as u32); - // We should always be uniquely putting due to `len` fetch_add returning unique values. - assert!(slot.put(&self.present, (), key)); + let slot = SlotIndex::from_index(u32::try_from(present_idx).unwrap()); + // SAFETY: We should always be uniquely putting due to `len` fetch_add returning unique values. + // We can't get here if `len` overflows because `put` will not succeed u32::MAX + 1 times + // as it will run out of slots. + unsafe { slot.put_unique(&self.present, (), key) }; } } @@ -331,6 +359,10 @@ where } } } + + pub fn len(&self) -> usize { + self.len.load(Ordering::Acquire) + } } #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/vec_cache/tests.rs b/compiler/rustc_data_structures/src/vec_cache/tests.rs index 9b60913ec922..f588442eee62 100644 --- a/compiler/rustc_data_structures/src/vec_cache/tests.rs +++ b/compiler/rustc_data_structures/src/vec_cache/tests.rs @@ -68,6 +68,13 @@ fn slot_entries_table() { ); } +#[test] +fn bucket_entries_matches() { + for i in 0..BUCKETS { + assert_eq!(SlotIndex { bucket_idx: i, index_in_bucket: 0 }.entries(), ENTRIES_BY_BUCKET[i]); + } +} + #[test] #[cfg(not(miri))] fn slot_index_exhaustive() { @@ -81,14 +88,18 @@ fn slot_index_exhaustive() { let mut prev = slot_idx; for idx in 1..=u32::MAX { let slot_idx = SlotIndex::from_index(idx); + + // SAFETY: Ensure indices don't go out of bounds of buckets. + assert!(slot_idx.index_in_bucket < slot_idx.entries()); + if prev.bucket_idx == slot_idx.bucket_idx { assert_eq!(prev.index_in_bucket + 1, slot_idx.index_in_bucket); } else { assert_eq!(slot_idx.index_in_bucket, 0); } - assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32); - assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx); + assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries() as u32); + assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries(), "{}", idx); prev = slot_idx; } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a7..10e1b1987194 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -9,25 +9,16 @@ anstyle = "1.0.13" jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } -rustc_ast_lowering = { path = "../rustc_ast_lowering" } -rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_attr_parsing = { path = "../rustc_attr_parsing" } -rustc_borrowck = { path = "../rustc_borrowck" } -rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } -rustc_hir_typeck = { path = "../rustc_hir_typeck" } -rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } -rustc_infer = { path = "../rustc_infer" } rustc_interface = { path = "../rustc_interface" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint = { path = "../rustc_lint" } @@ -36,21 +27,13 @@ rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } -rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_mir_transform = { path = "../rustc_mir_transform" } -rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_parse = { path = "../rustc_parse" } -rustc_passes = { path = "../rustc_passes" } -rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } -rustc_privacy = { path = "../rustc_privacy" } rustc_public = { path = "../rustc_public", features = ["rustc_internal"] } -rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl deleted file mode 100644 index b62cdc35f513..000000000000 --- a/compiler/rustc_driver_impl/messages.ftl +++ /dev/null @@ -1,29 +0,0 @@ -driver_impl_cant_emit_mir = could not emit MIR: {$error} - -driver_impl_ice = the compiler unexpectedly panicked. this is a bug. -driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} -driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly -driver_impl_ice_bug_report_update_note = please make sure that you have updated to the latest nightly -driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden - -driver_impl_ice_flags = compiler flags: {$flags} -driver_impl_ice_path = please attach the file at `{$path}` to your bug report -driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error} -driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}` -driver_impl_ice_version = rustc {$version} running on {$triple} - -driver_impl_rlink_corrupt_file = corrupt metadata encountered in `{$file}` - -driver_impl_rlink_empty_version_number = the input does not contain version number - -driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` - -driver_impl_rlink_no_a_file = rlink must be a file - -driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` - -driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}` - -driver_impl_rlink_wrong_file_type = the input does not look like a .rlink file - -driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..a235d3e0aecd 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -20,7 +20,7 @@ use std::fs::{self, File}; use std::io::{self, IsTerminal, Read, Write}; use std::panic::{self, PanicHookInfo}; use std::path::{Path, PathBuf}; -use std::process::{self, Command, Stdio}; +use std::process::{Command, ExitCode, Stdio, Termination}; use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Instant; @@ -34,7 +34,6 @@ use rustc_data_structures::profiling::{ }; pub use rustc_errors::catch_fatal_errors; use rustc_errors::emitter::stderr_destination; -use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown}; use rustc_feature::find_gated_cfg; @@ -108,48 +107,10 @@ use crate::session_diagnostics::{ RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn default_translator() -> Translator { - Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) + Translator::new() } -pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ - // tidy-alphabetical-start - crate::DEFAULT_LOCALE_RESOURCE, - rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE, - rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, - rustc_attr_parsing::DEFAULT_LOCALE_RESOURCE, - rustc_borrowck::DEFAULT_LOCALE_RESOURCE, - rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, - rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, - rustc_const_eval::DEFAULT_LOCALE_RESOURCE, - rustc_errors::DEFAULT_LOCALE_RESOURCE, - rustc_expand::DEFAULT_LOCALE_RESOURCE, - rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, - rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, - rustc_incremental::DEFAULT_LOCALE_RESOURCE, - rustc_infer::DEFAULT_LOCALE_RESOURCE, - rustc_interface::DEFAULT_LOCALE_RESOURCE, - rustc_lint::DEFAULT_LOCALE_RESOURCE, - rustc_metadata::DEFAULT_LOCALE_RESOURCE, - rustc_middle::DEFAULT_LOCALE_RESOURCE, - rustc_mir_build::DEFAULT_LOCALE_RESOURCE, - rustc_mir_dataflow::DEFAULT_LOCALE_RESOURCE, - rustc_mir_transform::DEFAULT_LOCALE_RESOURCE, - rustc_monomorphize::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_passes::DEFAULT_LOCALE_RESOURCE, - rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, - rustc_privacy::DEFAULT_LOCALE_RESOURCE, - rustc_query_system::DEFAULT_LOCALE_RESOURCE, - rustc_resolve::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, - rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, - rustc_ty_utils::DEFAULT_LOCALE_RESOURCE, - // tidy-alphabetical-end -]; - /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -210,10 +171,6 @@ impl Callbacks for TimePassesCallbacks { } } -pub fn diagnostics_registry() -> Registry { - Registry::new(rustc_errors::codes::DIAGNOSTICS) -} - /// This is the primary entry point for rustc. pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) { let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); @@ -241,7 +198,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(&default_early_dcx, diagnostics_registry(), code, sopts.color); + handle_explain(&default_early_dcx, code, sopts.color); return; } @@ -260,7 +217,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) output_dir: odir, ice_file, file_loader: None, - locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, @@ -268,7 +224,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) override_queries: None, extra_symbols: Vec::new(), make_codegen_backend: None, - registry: diagnostics_registry(), using_internal_features: &USING_INTERNAL_FEATURES, }; @@ -468,12 +423,12 @@ pub enum Compilation { Continue, } -fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) { +fn handle_explain(early_dcx: &EarlyDiagCtxt, code: &str, color: ColorConfig) { // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); if let Ok(code) = upper_cased_code.trim_prefix('E').parse::() && code <= ErrCode::MAX_AS_U32 - && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code)) + && let Ok(description) = rustc_errors::codes::try_find_description(ErrCode::from_u32(code)) { let mut is_in_code_block = false; let mut text = String::new(); @@ -491,10 +446,18 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col } text.push('\n'); } + + // If output is a terminal, use a pager to display the content. if io::stdout().is_terminal() { show_md_content_with_pager(&text, color); } else { - safe_print!("{text}"); + // Otherwise, if the user has requested colored output + // print the content in color, else print the md content. + if color == ColorConfig::Always { + show_colored_md_content(&text); + } else { + safe_print!("{text}"); + } } } else { early_dcx.early_fatal(format!("{code} is not a valid error code")); @@ -537,7 +500,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { }; // Try to print via the pager, pretty output if possible. - let pager_res: Option<()> = try { + let pager_res = try { let mut pager = cmd.stdin(Stdio::piped()).spawn().ok()?; let pager_stdin = pager.stdin.as_mut()?; @@ -564,6 +527,33 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { safe_print!("{content}"); } +/// Prints the markdown content with colored output. +/// +/// This function is used when the output is not a terminal, +/// but the user has requested colored output with `--color=always`. +fn show_colored_md_content(content: &str) { + // Try to prettify the raw markdown text. + let mut pretty_data = { + let mdstream = markdown::MdStream::parse_str(content); + let bufwtr = markdown::create_stdout_bufwtr(); + let mut mdbuf = Vec::new(); + if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() { + Some((bufwtr, mdbuf)) + } else { + None + } + }; + + if let Some((bufwtr, mdbuf)) = &mut pretty_data + && bufwtr.write_all(&mdbuf).is_ok() + { + return; + } + + // Everything failed. Print the raw markdown text. + safe_print!("{content}"); +} + fn process_rlink(sess: &Session, compiler: &interface::Compiler) { assert!(sess.opts.unstable_opts.link_only); let dcx = sess.dcx(); @@ -1382,10 +1372,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { /// Variant of `catch_fatal_errors` for the `interface::Result` return type /// that also computes the exit code. -pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 { +pub fn catch_with_exit_code(f: impl FnOnce() -> T) -> ExitCode { match catch_fatal_errors(f) { - Ok(()) => EXIT_SUCCESS, - _ => EXIT_FAILURE, + Ok(status) => status.report(), + _ => ExitCode::FAILURE, } } @@ -1535,7 +1525,7 @@ fn report_ice( extra_info: fn(&DiagCtxt), using_internal_features: &AtomicBool, ) { - let translator = default_translator(); + let translator = Translator::new(); let emitter = Box::new(rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new( stderr_destination(rustc_errors::ColorConfig::Auto), @@ -1670,7 +1660,7 @@ pub fn install_ctrlc_handler() { .expect("Unable to install ctrlc handler"); } -pub fn main() -> ! { +pub fn main() -> ExitCode { let start_time = Instant::now(); let start_rss = get_resident_set_size(); @@ -1690,5 +1680,5 @@ pub fn main() -> ! { print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss, format); } - process::exit(exit_code) + exit_code } diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 774221fd396a..97972185ebc4 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -3,82 +3,88 @@ use std::error::Error; use rustc_macros::{Diagnostic, Subdiagnostic}; #[derive(Diagnostic)] -#[diag(driver_impl_cant_emit_mir)] +#[diag("could not emit MIR: {$error}")] pub struct CantEmitMIR { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_unable_to_read)] +#[diag("failed to read rlink file: `{$err}`")] pub(crate) struct RlinkUnableToRead { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_wrong_file_type)] +#[diag("the input does not look like a .rlink file")] pub(crate) struct RLinkWrongFileType; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_empty_version_number)] +#[diag("the input does not contain version number")] pub(crate) struct RLinkEmptyVersionNumber; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_encoding_version_mismatch)] +#[diag( + ".rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`" +)] pub(crate) struct RLinkEncodingVersionMismatch { pub version_array: String, pub rlink_version: u32, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_rustc_version_mismatch)] +#[diag( + ".rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`" +)] pub(crate) struct RLinkRustcVersionMismatch<'a> { pub rustc_version: String, pub current_version: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_no_a_file)] +#[diag("rlink must be a file")] pub(crate) struct RlinkNotAFile; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_corrupt_file)] +#[diag("corrupt metadata encountered in `{$file}`")] pub(crate) struct RlinkCorruptFile<'a> { pub file: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(driver_impl_ice)] +#[diag("the compiler unexpectedly panicked. This is a bug")] pub(crate) struct Ice; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report)] +#[diag("we would appreciate a bug report: {$bug_report_url}")] pub(crate) struct IceBugReport<'a> { pub bug_report_url: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_update_note)] +#[diag("please make sure that you have updated to the latest nightly")] pub(crate) struct UpdateNightlyNote; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_internal_feature)] +#[diag( + "using internal features is not supported and expected to cause internal compiler errors when used incorrectly" +)] pub(crate) struct IceBugReportInternalFeature; #[derive(Diagnostic)] -#[diag(driver_impl_ice_version)] +#[diag("rustc {$version} running on {$triple}")] pub(crate) struct IceVersion<'a> { pub version: &'a str, pub triple: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path)] +#[diag("please attach the file at `{$path}` to your bug report")] pub(crate) struct IcePath { pub path: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path_error)] +#[diag("the ICE couldn't be written to `{$path}`: {$error}")] pub(crate) struct IcePathError { pub path: std::path::PathBuf, pub error: String, @@ -87,23 +93,23 @@ pub(crate) struct IcePathError { } #[derive(Subdiagnostic)] -#[note(driver_impl_ice_path_error_env)] +#[note("the environment variable `RUSTC_ICE` is set to `{$env_var}`")] pub(crate) struct IcePathErrorEnv { pub env_var: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_flags)] +#[diag("compiler flags: {$flags}")] pub(crate) struct IceFlags { pub flags: String, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_exclude_cargo_defaults)] +#[diag("some of the compiler flags provided by cargo are hidden")] pub(crate) struct IceExcludeCargoDefaults; #[derive(Diagnostic)] -#[diag(driver_impl_unstable_feature_usage)] +#[diag("cannot dump feature usage metrics: {$error}")] pub(crate) struct UnstableFeatureUsage { pub error: Box, } diff --git a/compiler/rustc_error_codes/src/error_codes/E0264.md b/compiler/rustc_error_codes/src/error_codes/E0264.md index 33ddf3405acc..b8d0f7d4d6af 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0264.md +++ b/compiler/rustc_error_codes/src/error_codes/E0264.md @@ -7,8 +7,8 @@ Erroneous code example: #![allow(internal_features)] extern "C" { - #[lang = "cake"] // error: unknown external lang item: `cake` - fn cake(); + #[lang = "copy"] // error: unknown external lang item: `copy` + fn copy(); } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0423.md b/compiler/rustc_error_codes/src/error_codes/E0423.md index a98ada17a469..4af17b1221b9 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0423.md +++ b/compiler/rustc_error_codes/src/error_codes/E0423.md @@ -44,3 +44,14 @@ fn h1() -> i32 { // did you mean `a::I`? } ``` + +### Enum types used as values + +Enums are types and cannot be used directly as values. + +```compile_fail,E0423 +fn main(){ + let x = Option::; + //~^ ERROR expected value,found enum `Option` +} +``` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index c0737edd7d65..0b30102eb992 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -192,7 +192,7 @@ pub fn fluent_bundle( Ok(Some(bundle)) } -fn register_functions(bundle: &mut FluentBundle) { +pub fn register_functions(bundle: &mut fluent_bundle::bundle::FluentBundle) { bundle .add_function("STREQ", |positional, _named| match positional { [FluentValue::String(a), FluentValue::String(b)] => format!("{}", (a == b)).into(), @@ -230,47 +230,6 @@ pub fn fallback_fluent_bundle( }))) } -/// Identifier for the Fluent message/attribute corresponding to a diagnostic message. -type FluentId = Cow<'static, str>; - -/// Abstraction over a message in a subdiagnostic (i.e. label, note, help, etc) to support both -/// translatable and non-translatable diagnostic messages. -/// -/// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent -/// message so messages of this type must be combined with a `DiagMessage` (using -/// `DiagMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from -/// the `Subdiagnostic` derive refer to Fluent identifiers directly. -#[rustc_diagnostic_item = "SubdiagMessage"] -pub enum SubdiagMessage { - /// Non-translatable diagnostic message. - Str(Cow<'static, str>), - /// Identifier of a Fluent message. Instances of this variant are generated by the - /// `Subdiagnostic` derive. - FluentIdentifier(FluentId), - /// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an - /// actual translated message. Instances of this variant are generated by the `fluent_messages` - /// macro. - /// - /// - FluentAttr(FluentId), -} - -impl From for SubdiagMessage { - fn from(s: String) -> Self { - SubdiagMessage::Str(Cow::Owned(s)) - } -} -impl From<&'static str> for SubdiagMessage { - fn from(s: &'static str) -> Self { - SubdiagMessage::Str(Cow::Borrowed(s)) - } -} -impl From> for SubdiagMessage { - fn from(s: Cow<'static, str>) -> Self { - SubdiagMessage::Str(s) - } -} - /// Abstraction over a message in a diagnostic to support both translatable and non-translatable /// diagnostic messages. /// @@ -285,41 +244,15 @@ pub enum DiagMessage { /// are translated when they are added to the parent diagnostic. This is one of the ways /// this variant of `DiagMessage` is produced. Str(Cow<'static, str>), - /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic - /// message. Yet to be translated. - /// - /// - /// - FluentIdentifier(FluentId, Option), + /// An inline Fluent message, containing the to be translated diagnostic message. + Inline(Cow<'static, str>), } impl DiagMessage { - /// Given a `SubdiagMessage` which may contain a Fluent attribute, create a new - /// `DiagMessage` that combines that attribute with the Fluent identifier of `self`. - /// - /// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`. - /// - If `self` is non-translatable then return `self`'s message. - pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self { - let attr = match sub { - SubdiagMessage::Str(s) => return DiagMessage::Str(s), - SubdiagMessage::FluentIdentifier(id) => { - return DiagMessage::FluentIdentifier(id, None); - } - SubdiagMessage::FluentAttr(attr) => attr, - }; - - match self { - DiagMessage::Str(s) => DiagMessage::Str(s.clone()), - DiagMessage::FluentIdentifier(id, _) => { - DiagMessage::FluentIdentifier(id.clone(), Some(attr)) - } - } - } - pub fn as_str(&self) -> Option<&str> { match self { DiagMessage::Str(s) => Some(s), - DiagMessage::FluentIdentifier(_, _) => None, + DiagMessage::Inline(_) => None, } } } @@ -340,23 +273,6 @@ impl From> for DiagMessage { } } -/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but -/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the -/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be -/// able to convert between these, as much as they'll be converted back into `DiagMessage` -/// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive. -impl From for SubdiagMessage { - fn from(val: DiagMessage) -> Self { - match val { - DiagMessage::Str(s) => SubdiagMessage::Str(s), - DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id), - // There isn't really a sensible behaviour for this because it loses information but - // this is the most sensible of the behaviours. - DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr), - } - } -} - /// A span together with some additional data. #[derive(Clone, Debug)] pub struct SpanLabel { diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 81eecca3199f..a81fc496c828 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -14,7 +14,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_codes = { path = "../rustc_error_codes" } rustc_error_messages = { path = "../rustc_error_messages" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hashes = { path = "../rustc_hashes" } rustc_index = { path = "../rustc_index" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl deleted file mode 100644 index ad2e206260d5..000000000000 --- a/compiler/rustc_errors/messages.ftl +++ /dev/null @@ -1,48 +0,0 @@ -errors_delayed_at_with_newline = - delayed at {$emitted_at} - {$note} - -errors_delayed_at_without_newline = - delayed at {$emitted_at} - {$note} - -errors_expected_lifetime_parameter = - expected lifetime {$count -> - [1] parameter - *[other] parameters - } - -errors_indicate_anonymous_lifetime = - indicate the anonymous {$count -> - [1] lifetime - *[other] lifetimes - } - -errors_invalid_flushed_delayed_diagnostic_level = - `flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug` - -errors_target_inconsistent_architecture = - inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}` - -errors_target_inconsistent_pointer_width = - inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}` - -errors_target_invalid_address_space = - invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err} - -errors_target_invalid_alignment = - invalid alignment for `{$cause}` in "data-layout": `{$align}` is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {""} - } - -errors_target_invalid_bits = - invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err} - -errors_target_invalid_bits_size = {$err} - -errors_target_invalid_datalayout_pointer_spec = - unknown pointer specification `{$err}` in datalayout string - -errors_target_missing_alignment = - missing alignment for `{$cause}` in "data-layout" diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 9bb318973958..bdd3266adb66 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -27,7 +27,6 @@ use crate::emitter::{ ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different, normalize_whitespace, should_show_source_code, }; -use crate::registry::Registry; use crate::translation::{Translator, to_fluent_args}; use crate::{ CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag, @@ -73,7 +72,7 @@ impl Debug for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { + fn emit_diagnostic(&mut self, mut diag: DiagInner) { let fluent_args = to_fluent_args(diag.args.iter()); if self.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() { diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs index 924924f285eb..c1e7b7c184c1 100644 --- a/compiler/rustc_errors/src/codes.rs +++ b/compiler/rustc_errors/src/codes.rs @@ -5,6 +5,9 @@ //! long description text. use std::fmt; +use std::sync::LazyLock; + +use rustc_data_structures::fx::FxHashMap; rustc_index::newtype_index! { #[max = 9999] // Because all error codes have four digits. @@ -27,15 +30,28 @@ macro_rules! define_error_code_constants_and_diagnostics_table { $( pub const ${concat(E, $num)}: $crate::ErrCode = $crate::ErrCode::from_u32($num); )* - pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[ - $( ( - ${concat(E, $num)}, - include_str!( - concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md") - ) - ), )* - ]; + static DIAGNOSTICS: LazyLock> = LazyLock::new(|| { + [ + $( ( + ${concat(E, $num)}, + include_str!( + concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md") + ) + ), )* + ] + .iter() + .copied() + .collect() + }); ) } rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table); + +#[derive(Debug)] +pub struct InvalidErrorCode; + +/// Returns `InvalidErrorCode` if the code requested does not exist. +pub fn try_find_description(code: ErrCode) -> Result<&'static str, InvalidErrorCode> { + DIAGNOSTICS.get(&code).copied().ok_or(InvalidErrorCode) +} diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a9e81354fc6a..087c5e700df0 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -17,8 +17,7 @@ use tracing::debug; use crate::{ CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, - MultiSpan, StashKey, Style, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle, - Suggestions, + MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions, }; pub type DiagArgMap = FxIndexMap; @@ -325,30 +324,8 @@ impl DiagInner { } } - // See comment on `Diag::subdiagnostic_message_to_diagnostic_message`. - pub(crate) fn subdiagnostic_message_to_diagnostic_message( - &self, - attr: impl Into, - ) -> DiagMessage { - let msg = - self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); - msg.with_subdiagnostic_message(attr.into()) - } - - pub(crate) fn sub( - &mut self, - level: Level, - message: impl Into, - span: MultiSpan, - ) { - let sub = Subdiag { - level, - messages: vec![( - self.subdiagnostic_message_to_diagnostic_message(message), - Style::NoStyle, - )], - span, - }; + pub(crate) fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { + let sub = Subdiag { level, messages: vec![(message.into(), Style::NoStyle)], span }; self.children.push(sub); } @@ -609,9 +586,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// the diagnostic was constructed. However, the label span is *not* considered a /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { - let msg = self.subdiagnostic_message_to_diagnostic_message(label); - self.span.push_span_label(span, msg); + pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { + self.span.push_span_label(span, label.into()); self } } @@ -713,7 +689,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_note, /// Add a note attached to this diagnostic. - pub fn note(&mut self, msg: impl Into) -> &mut Self { + pub fn note(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self } } @@ -733,7 +709,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// This is like [`Diag::note()`], but it's only printed once. - pub fn note_once(&mut self, msg: impl Into) -> &mut Self { + pub fn note_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self } @@ -744,7 +720,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_note( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Note, msg, sp.into()); self @@ -755,7 +731,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_note_once>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::OnceNote, msg, sp.into()); self @@ -763,7 +739,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_warn, /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: impl Into) -> &mut Self { + pub fn warn(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new()); self } } @@ -773,7 +749,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_warn>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Warning, msg, sp.into()); self @@ -781,13 +757,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_help, /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: impl Into) -> &mut Self { + pub fn help(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new()); self } } /// This is like [`Diag::help()`], but it's only printed once. - pub fn help_once(&mut self, msg: impl Into) -> &mut Self { + pub fn help_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } @@ -814,7 +790,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_help( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Help, msg, sp.into()); self @@ -866,7 +842,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -882,7 +858,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion_verbose( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -897,7 +873,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, - msg: impl Into, + msg: impl Into, mut suggestion: Vec<(Span, String)>, applicability: Applicability, style: SuggestionStyle, @@ -924,7 +900,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.push_suggestion(CodeSuggestion { substitutions: vec![Substitution { parts }], - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -939,7 +915,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// improve understandability. pub fn tool_only_multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -972,7 +948,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -990,7 +966,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, style: SuggestionStyle, @@ -1003,7 +979,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { substitutions: vec![Substitution { parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }], }], - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -1015,7 +991,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1035,7 +1011,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestions( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, ) -> &mut Self { @@ -1051,7 +1027,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestions_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, style: SuggestionStyle, @@ -1068,7 +1044,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { .collect(); self.push_suggestion(CodeSuggestion { substitutions, - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -1080,7 +1056,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// See also [`Diag::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator>, applicability: Applicability, ) -> &mut Self { @@ -1112,7 +1088,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.push_suggestion(CodeSuggestion { substitutions, - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style: SuggestionStyle::ShowAlways, applicability, }); @@ -1127,7 +1103,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_short( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1150,7 +1126,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1172,7 +1148,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1200,10 +1176,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// one value will clobber the other. Eagerly translating the /// diagnostic uses the variables defined right then, before the /// clobbering occurs. - pub fn eagerly_translate(&self, msg: impl Into) -> SubdiagMessage { + pub fn eagerly_translate(&self, msg: impl Into) -> DiagMessage { let args = self.args.iter(); - let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into()); - self.dcx.eagerly_translate(msg, args) + self.dcx.eagerly_translate(msg.into(), args) } with_fn! { with_span, @@ -1256,31 +1231,18 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } - /// Helper function that takes a `SubdiagMessage` and returns a `DiagMessage` by - /// combining it with the primary message of the diagnostic (if translatable, otherwise it just - /// passes the user's string along). - pub(crate) fn subdiagnostic_message_to_diagnostic_message( - &self, - attr: impl Into, - ) -> DiagMessage { - self.deref().subdiagnostic_message_to_diagnostic_message(attr) - } - /// Convenience function for internal use, clients should use one of the /// public methods above. /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. - pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { + pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { self.deref_mut().sub(level, message, span); } /// Convenience function for internal use, clients should use one of the /// public methods above. fn sub_with_highlights(&mut self, level: Level, messages: Vec, span: MultiSpan) { - let messages = messages - .into_iter() - .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style)) - .collect(); + let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect(); let sub = Subdiag { level, messages, span }; self.children.push(sub); } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 435d16a83806..42c605d34814 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -6,10 +6,7 @@ use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; use crate::diagnostic::DiagLocation; -use crate::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, - fluent_generated as fluent, -}; +use crate::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, msg}; impl IntoDiagArg for DiagLocation { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { @@ -44,43 +41,50 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { - Diag::new(dcx, level, fluent::errors_target_invalid_address_space) + Diag::new(dcx, level, msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}")) .with_arg("addr_space", addr_space) .with_arg("cause", cause) .with_arg("err", err) } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_bits) + Diag::new(dcx, level, msg!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}")) .with_arg("kind", kind) .with_arg("bit", bit) .with_arg("cause", cause) .with_arg("err", err) } TargetDataLayoutErrors::MissingAlignment { cause } => { - Diag::new(dcx, level, fluent::errors_target_missing_alignment) + Diag::new(dcx, level, msg!("missing alignment for `{$cause}` in \"data-layout\"")) .with_arg("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_alignment) - .with_arg("cause", cause) - .with_arg("err_kind", err.diag_ident()) - .with_arg("align", err.align()) + Diag::new(dcx, level, msg!( + "invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" + )) + .with_arg("cause", cause) + .with_arg("err_kind", err.diag_ident()) + .with_arg("align", err.align()) } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - Diag::new(dcx, level, fluent::errors_target_inconsistent_architecture) - .with_arg("dl", dl) - .with_arg("target", target) + Diag::new(dcx, level, msg!( + "inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`" + )) + .with_arg("dl", dl).with_arg("target", target) } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - Diag::new(dcx, level, fluent::errors_target_inconsistent_pointer_width) - .with_arg("pointer_size", pointer_size) - .with_arg("target", target) + Diag::new(dcx, level, msg!( + "inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`" + )).with_arg("pointer_size", pointer_size).with_arg("target", target) } TargetDataLayoutErrors::InvalidBitsSize { err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err) + Diag::new(dcx, level, msg!("{$err}")).with_arg("err", err) } TargetDataLayoutErrors::UnknownPointerSpecification { err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec) + Diag::new(dcx, level, msg!("unknown pointer specification `{$err}` in datalayout string")) .with_arg("err", err) } } @@ -99,7 +103,12 @@ impl Subdiagnostic for SingleLabelManySpans { } #[derive(Subdiagnostic)] -#[label(errors_expected_lifetime_parameter)] +#[label( + "expected lifetime {$count -> + [1] parameter + *[other] parameters + }" +)] pub struct ExpectedLifetimeParameter { #[primary_span] pub span: Span, @@ -107,7 +116,14 @@ pub struct ExpectedLifetimeParameter { } #[derive(Subdiagnostic)] -#[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")] +#[suggestion( + "indicate the anonymous {$count -> + [1] lifetime + *[other] lifetimes + }", + code = "{suggestion}", + style = "verbose" +)] pub struct IndicateAnonymousLifetime { #[primary_span] pub span: Span, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3433db1e0704..4ceb5cf06f93 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -24,7 +24,6 @@ use rustc_span::source_map::SourceMap; use rustc_span::{FileName, SourceFile, Span}; use tracing::{debug, warn}; -use crate::registry::Registry; use crate::timings::TimingRecord; use crate::translation::Translator; use crate::{ @@ -54,7 +53,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors and other structured information. pub trait Emitter { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry); + fn emit_diagnostic(&mut self, diag: DiagInner); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -66,7 +65,7 @@ pub trait Emitter { /// Emit a report about future breakage. /// Currently only supported for the JSON format. - fn emit_future_breakage_report(&mut self, _diags: Vec, _registry: &Registry) {} + fn emit_future_breakage_report(&mut self, _diags: Vec) {} /// Emit list of unused externs. /// Currently only supported for the JSON format. @@ -380,9 +379,9 @@ impl Emitter for EmitterWithNote { None } - fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) { + fn emit_diagnostic(&mut self, mut diag: DiagInner) { diag.sub(Level::Note, self.note.clone(), MultiSpan::new()); - self.emitter.emit_diagnostic(diag, registry); + self.emitter.emit_diagnostic(diag); } fn translator(&self) -> &Translator { @@ -399,7 +398,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {} + fn emit_diagnostic(&mut self, _diag: DiagInner) {} fn translator(&self) -> &Translator { &self.translator diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 85801245bea9..310a64745bad 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -31,7 +31,6 @@ use crate::emitter::{ ColorConfig, Destination, Emitter, HumanReadableErrorType, OutputTheme, TimingEvent, should_show_source_code, }; -use crate::registry::Registry; use crate::timings::{TimingRecord, TimingSection}; use crate::translation::{Translator, to_fluent_args}; use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl}; @@ -107,8 +106,8 @@ enum EmitTyped<'a> { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) { - let data = Diagnostic::from_errors_diagnostic(diag, self, registry); + fn emit_diagnostic(&mut self, diag: crate::DiagInner) { + let data = Diagnostic::from_errors_diagnostic(diag, self); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { panic!("failed to print diagnostics: {e:?}"); @@ -139,7 +138,7 @@ impl Emitter for JsonEmitter { } } - fn emit_future_breakage_report(&mut self, diags: Vec, registry: &Registry) { + fn emit_future_breakage_report(&mut self, diags: Vec) { let data: Vec> = diags .into_iter() .map(|mut diag| { @@ -153,7 +152,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - diag, self, registry, + diag, self, )), } }) @@ -307,11 +306,7 @@ struct UnusedExterns<'a> { impl Diagnostic { /// Converts from `rustc_errors::DiagInner` to `Diagnostic`. - fn from_errors_diagnostic( - diag: crate::DiagInner, - je: &JsonEmitter, - registry: &Registry, - ) -> Diagnostic { + fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args.iter()); let sugg_to_diag = |sugg: &CodeSuggestion| { let translated_message = @@ -351,7 +346,7 @@ impl Diagnostic { let code = if let Some(code) = diag.code { Some(DiagnosticCode { code: code.to_string(), - explanation: registry.try_find_description(code).ok(), + explanation: crate::codes::try_find_description(code).ok(), }) } else if let Some(IsLint { name, .. }) = &diag.is_lint { Some(DiagnosticCode { code: name.to_string(), explanation: None }) @@ -388,7 +383,7 @@ impl Diagnostic { .ui_testing(je.ui_testing) .ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone()) .theme(if je.json_rendered.unicode { OutputTheme::Unicode } else { OutputTheme::Ascii }) - .emit_diagnostic(diag, registry); + .emit_diagnostic(diag); let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap(); let buf = String::from_utf8(buf).unwrap(); diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index c1c9ecf7198f..ffcf9947a7a8 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -45,8 +45,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { rustc_span::create_default_session_globals_then(|| { let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(filename(&sm, "test.rs"), code.to_owned()); - let translator = - Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::new(); let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68d825a4514a..989d28eac455 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] @@ -14,8 +14,6 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] -#![feature(try_blocks)] -#![feature(yeet_expr)] // tidy-alphabetical-end extern crate self as rustc_errors; @@ -57,12 +55,13 @@ use rustc_data_structures::sync::{DynSend, Lock}; use rustc_data_structures::{AtomicRef, assert_matches}; pub use rustc_error_messages::{ DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, FluentBundle, IntoDiagArg, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, - fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display, + LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, fallback_fluent_bundle, + fluent_bundle, into_diag_arg_using_display, }; use rustc_hashes::Hash128; use rustc_lint_defs::LintExpectationId; pub use rustc_lint_defs::{Applicability, listify, pluralize}; +pub use rustc_macros::msg; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors}; @@ -71,7 +70,6 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::debug; use crate::emitter::TimingEvent; -use crate::registry::Registry; use crate::timings::TimingRecord; pub mod annotate_snippet_emitter_writer; @@ -84,16 +82,11 @@ pub mod error; pub mod json; mod lock; pub mod markdown; -pub mod registry; -#[cfg(test)] -mod tests; pub mod timings; pub mod translation; pub type PResult<'a, T> = Result>; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24); @@ -299,8 +292,6 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { struct DiagCtxtInner { flags: DiagCtxtFlags, - registry: Registry, - /// The error guarantees from all emitted errors. The length gives the error count. err_guars: Vec, /// The error guarantee from all emitted lint errors. The length gives the @@ -482,11 +473,6 @@ impl DiagCtxt { self } - pub fn with_registry(mut self, registry: Registry) -> Self { - self.inner.get_mut().registry = registry; - self - } - pub fn new(emitter: Box) -> Self { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } @@ -501,12 +487,12 @@ impl DiagCtxt { self.inner.borrow_mut().emitter = emitter; } - /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. + /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. pub fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator>, - ) -> SubdiagMessage { + ) -> DiagMessage { let inner = self.inner.borrow(); inner.eagerly_translate(message, args) } @@ -539,7 +525,6 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); let DiagCtxtInner { flags: _, - registry: _, err_guars, lint_err_guars, delayed_bugs, @@ -813,7 +798,7 @@ impl<'a> DiagCtxtHandle<'a> { .emitted_diagnostic_codes .iter() .filter_map(|&code| { - if inner.registry.try_find_description(code).is_ok() { + if crate::codes::try_find_description(code).is_ok() { Some(code.to_string()) } else { None @@ -885,7 +870,7 @@ impl<'a> DiagCtxtHandle<'a> { let inner = &mut *self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.future_breakage_diagnostics); if !diags.is_empty() { - inner.emitter.emit_future_breakage_report(diags, &inner.registry); + inner.emitter.emit_future_breakage_report(diags); } } @@ -1186,7 +1171,6 @@ impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, - registry: Registry::new(&[]), err_guars: Vec::new(), lint_err_guars: Vec::new(), delayed_bugs: Vec::new(), @@ -1362,7 +1346,7 @@ impl DiagCtxtInner { } self.has_printed = true; - self.emitter.emit_diagnostic(diagnostic, &self.registry); + self.emitter.emit_diagnostic(diagnostic); } if is_error { @@ -1438,13 +1422,13 @@ impl DiagCtxtInner { self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } - /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. + /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator>, - ) -> SubdiagMessage { - SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) + ) -> DiagMessage { + DiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) } /// Translate `message` eagerly with `args` to `String`. @@ -1465,10 +1449,9 @@ impl DiagCtxtInner { fn eagerly_translate_for_subdiag( &self, diag: &DiagInner, - msg: impl Into, - ) -> SubdiagMessage { - let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); - self.eagerly_translate(msg, diag.args.iter()) + msg: impl Into, + ) -> DiagMessage { + self.eagerly_translate(msg.into(), diag.args.iter()) } fn flush_delayed(&mut self) { @@ -1531,7 +1514,9 @@ impl DiagCtxtInner { // the usual `Diag`/`DiagCtxt` level, so we must augment `bug` // in a lower-level fashion. bug.arg("level", bug.level); - let msg = crate::fluent_generated::errors_invalid_flushed_delayed_diagnostic_level; + let msg = msg!( + "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`" + ); let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call bug.sub(Note, msg, bug.span.primary_span().unwrap().into()); } @@ -1573,10 +1558,13 @@ impl DelayedDiagInner { // lower-level fashion. let mut diag = self.inner; let msg = match self.note.status() { - BacktraceStatus::Captured => crate::fluent_generated::errors_delayed_at_with_newline, + BacktraceStatus::Captured => msg!( + "delayed at {$emitted_at} + {$note}" + ), // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. - _ => crate::fluent_generated::errors_delayed_at_without_newline, + _ => msg!("delayed at {$emitted_at} - {$note}"), }; diag.arg("emitted_at", diag.emitted_at.clone()); diag.arg("note", self.note); diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs deleted file mode 100644 index baca7700d90e..000000000000 --- a/compiler/rustc_errors/src/registry.rs +++ /dev/null @@ -1,23 +0,0 @@ -use rustc_data_structures::fx::FxHashMap; - -use crate::ErrCode; - -#[derive(Debug)] -pub struct InvalidErrorCode; - -#[derive(Clone)] -pub struct Registry { - long_descriptions: FxHashMap, -} - -impl Registry { - pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry { - Registry { long_descriptions: long_descriptions.iter().copied().collect() } - } - - /// Returns `InvalidErrorCode` if the code requested does not exist in the - /// registry. - pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> { - self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode) - } -} diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs deleted file mode 100644 index 34ebac0fde11..000000000000 --- a/compiler/rustc_errors/src/tests.rs +++ /dev/null @@ -1,182 +0,0 @@ -use std::sync::{Arc, LazyLock}; - -use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; -use rustc_error_messages::{DiagMessage, langid}; - -use crate::FluentBundle; -use crate::error::{TranslateError, TranslateErrorKind}; -use crate::fluent_bundle::*; -use crate::translation::Translator; - -fn make_translator(ftl: &'static str) -> Translator { - let resource = FluentResource::try_new(ftl.into()).expect("Failed to parse an FTL string."); - - let langid_en = langid!("en-US"); - - let mut bundle: FluentBundle = - IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![ - langid_en, - ])); - - bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle."); - - Translator { - fluent_bundle: None, - fallback_fluent_bundle: Arc::new(LazyLock::new(Box::new(|| bundle))), - } -} - -#[test] -fn wellformed_fluent() { - let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{$name}` here - .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait - .value_borrowed_label = value borrowed here after move - .suggestion = borrow this binding in the pattern to avoid moving the value"); - - let mut args = FluentArgs::new(); - args.set("name", "Foo"); - args.set("ty", "std::string::String"); - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("suggestion".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "borrow this binding in the pattern to avoid moving the value" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("value_borrowed_label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "value borrowed here after move" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("occurs_because_label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "move occurs because `\u{2068}Foo\u{2069}` has type `\u{2068}std::string::String\u{2069}` which does not implement the `Copy` trait" - ); - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "value moved into `\u{2068}Foo\u{2069}` here" - ); - } - } -} - -#[test] -fn misformed_fluent() { - let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{name}` here - .occurs_because_label = move occurs because `{$oops}` has type `{$ty}` which does not implement the `Copy` trait - .suggestion = borrow this binding in the pattern to avoid moving the value"); - - let mut args = FluentArgs::new(); - args.set("name", "Foo"); - args.set("ty", "std::string::String"); - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("value_borrowed_label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - assert!( - matches!( - &err, - TranslateError::Two { - primary: box TranslateError::One { - kind: TranslateErrorKind::PrimaryBundleMissing, - .. - }, - fallback: box TranslateError::One { - kind: TranslateErrorKind::AttributeMissing { attr: "value_borrowed_label" }, - .. - } - } - ), - "{err:#?}" - ); - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe attribute `value_borrowed_label` was missing\nhelp: add `.value_borrowed_label = `\n" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - if let TranslateError::Two { - primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, - fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, - } = &err - && let [ - FluentError::ResolverError(ResolverError::Reference( - ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. }, - )), - ] = &**errs - && id == "name" - { - } else { - panic!("{err:#?}") - }; - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nargument `name` exists but was not referenced correctly\nhelp: try using `{$name}` instead\n" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("occurs_because_label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - if let TranslateError::Two { - primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, - fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, - } = &err - && let [ - FluentError::ResolverError(ResolverError::Reference( - ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. }, - )), - ] = &**errs - && id == "oops" - { - } else { - panic!("{err:#?}") - }; - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe fluent string has an argument `oops` that was not found.\nhelp: the arguments `name` and `ty` are available\n" - ); - } -} diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 43d5fca301ec..c6d30032f1af 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,13 +1,14 @@ use std::borrow::Cow; -use std::env; use std::error::Report; use std::sync::Arc; pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; +use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; -use crate::error::{TranslateError, TranslateErrorKind}; -use crate::{DiagArg, DiagMessage, FluentBundle, Style}; +use crate::error::TranslateError; +use crate::fluent_bundle::FluentResource; +use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle}; /// Convert diagnostic arguments (a rustc internal type that exists to implement /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. @@ -33,24 +34,11 @@ pub struct Translator { /// Localized diagnostics for the locale requested by the user. If no language was requested by /// the user then this will be `None` and `fallback_fluent_bundle` should be used. pub fluent_bundle: Option>, - /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. - /// Used when the user has not requested a specific language or when a localized diagnostic is - /// unavailable for the requested locale. - pub fallback_fluent_bundle: LazyFallbackBundle, } impl Translator { - pub fn with_fallback_bundle( - resources: Vec<&'static str>, - with_directionality_markers: bool, - ) -> Translator { - Translator { - fluent_bundle: None, - fallback_fluent_bundle: crate::fallback_fluent_bundle( - resources, - with_directionality_markers, - ), - } + pub fn new() -> Translator { + Translator { fluent_bundle: None } } /// Convert `DiagMessage`s to a string, performing translation if necessary. @@ -74,70 +62,30 @@ impl Translator { args: &'a FluentArgs<'_>, ) -> Result, TranslateError<'a>> { trace!(?message, ?args); - let (identifier, attr) = match message { - DiagMessage::Str(msg) => { - return Ok(Cow::Borrowed(msg)); - } - DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr), - }; - let translate_with_bundle = - |bundle: &'a FluentBundle| -> Result, TranslateError<'_>> { - let message = bundle - .get_message(identifier) - .ok_or(TranslateError::message(identifier, args))?; - let value = match attr { - Some(attr) => message - .get_attribute(attr) - .ok_or(TranslateError::attribute(identifier, args, attr))? - .value(), - None => message.value().ok_or(TranslateError::value(identifier, args))?, - }; - debug!(?message, ?value); + match message { + DiagMessage::Str(msg) => Ok(Cow::Borrowed(msg)), + // This translates an inline fluent diagnostic message + // It does this by creating a new `FluentBundle` with only one message, + // and then translating using this bundle. + DiagMessage::Inline(msg) => { + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = + FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap(); + let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); + bundle.set_use_isolating(false); + bundle.add_resource(resource).unwrap(); + register_functions(&mut bundle); + let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); + let value = message.value().unwrap(); let mut errs = vec![]; - let translated = bundle.format_pattern(value, Some(args), &mut errs); + let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string(); debug!(?translated, ?errs); if errs.is_empty() { - Ok(translated) + Ok(Cow::Owned(translated)) } else { - Err(TranslateError::fluent(identifier, args, errs)) + Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs)) } - }; - - try { - match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) { - // The primary bundle was present and translation succeeded - Some(Ok(t)) => t, - - // If `translate_with_bundle` returns `Err` with the primary bundle, this is likely - // just that the primary bundle doesn't contain the message being translated, so - // proceed to the fallback bundle. - Some(Err( - primary @ TranslateError::One { - kind: TranslateErrorKind::MessageMissing, .. - }, - )) => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| primary.and(fallback))?, - - // Always yeet out for errors on debug (unless - // `RUSTC_TRANSLATION_NO_DEBUG_ASSERT` is set in the environment - this allows - // local runs of the test suites, of builds with debug assertions, to test the - // behaviour in a normal build). - Some(Err(primary)) - if cfg!(debug_assertions) - && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() => - { - do yeet primary - } - - // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so - // just hide it and try with the fallback bundle. - Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| primary.and(fallback))?, - - // The primary bundle is missing, proceed to the fallback bundle - None => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?, } } } diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index a18506c42afc..12b0c384a8ae 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -16,7 +16,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } 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_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl deleted file mode 100644 index 851d78e0b105..000000000000 --- a/compiler/rustc_expand/messages.ftl +++ /dev/null @@ -1,207 +0,0 @@ -expand_attributes_on_expressions_experimental = - attributes on expressions are experimental - .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//` - .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !` - -expand_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes - -expand_count_repetition_misplaced = - `count` can not be placed inside the innermost repetition - -expand_crate_name_in_cfg_attr = - `crate_name` within an `#![cfg_attr]` attribute is forbidden - -expand_crate_type_in_cfg_attr = - `crate_type` within an `#![cfg_attr]` attribute is forbidden - -expand_custom_attribute_panicked = - custom attribute panicked - .help = message: {$message} - -expand_duplicate_matcher_binding = duplicate matcher binding - .label = duplicate binding - .label2 = previous binding - -expand_empty_delegation_mac = - empty {$kind} delegation is not supported - -expand_expected_paren_or_brace = - expected `(` or `{"{"}`, found `{$token}` - -expand_explain_doc_comment_inner = - inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match - -expand_explain_doc_comment_outer = - outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match - -expand_expr_repeat_no_syntax_vars = - attempted to repeat an expression containing no syntax variables matched as repeating at this depth - -expand_feature_not_allowed = - the feature `{$name}` is not in the list of allowed features - -expand_feature_removed = - feature has been removed - .label = feature has been removed - .note = removed in {$removed_rustc_version}{$pull_note} - .reason = {$reason} - -expand_file_modules_in_proc_macro_input_are_unstable = - file modules in proc macro input are unstable - -expand_glob_delegation_outside_impls = - glob delegation is only supported in impls - -expand_glob_delegation_traitless_qpath = - qualified path without a trait in glob delegation - -expand_incomplete_parse = - macro expansion ignores {$descr} and any tokens following - .label = caused by the macro expansion here - .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context - .suggestion_add_semi = you might be missing a semicolon here - -expand_invalid_cfg_expected_syntax = expected syntax is - -expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified -expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses -expand_invalid_cfg_no_predicate = `cfg` predicate is not specified -expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal - -expand_invalid_fragment_specifier = - invalid fragment specifier `{$fragment}` - .help = {$help} - -expand_macro_args_bad_delim = `{$rule_kw}` rule argument matchers require parentheses -expand_macro_args_bad_delim_sugg = the delimiters should be `(` and `)` - -expand_macro_body_stability = - macros cannot have body stability attributes - .label = invalid body stability attribute - .label2 = body stability attribute affects this macro - -expand_macro_call_unused_doc_comment = unused doc comment - .label = rustdoc does not generate documentation for macro invocations - .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion - -expand_macro_const_stability = - macros cannot have const stability attributes - .label = invalid const stability attribute - .label2 = const stability attribute affects this macro - -expand_macro_expands_to_match_arm = macros cannot expand to match arms - -expand_malformed_feature_attribute = - malformed `feature` attribute input - .expected = expected just one word - -expand_meta_var_dif_seq_matchers = {$msg} - -expand_metavar_still_repeating = variable `{$ident}` is still repeating at this depth - .label = expected repetition - -expand_metavariable_wrong_operator = meta-variable repeats with different Kleene operator - .binder_label = expected repetition - .occurrence_label = conflicting repetition - -expand_missing_fragment_specifier = missing fragment specifier - .note = fragment specifiers must be provided - .suggestion_add_fragspec = try adding a specifier here - .valid = {$valid} - -expand_module_circular = - circular modules: {$modules} - -expand_module_file_not_found = - file not found for module `{$name}` - .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}" - .note = if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead - -expand_module_in_block = - cannot declare a file module inside a block unless it has a path attribute - .help = maybe `use` the module `{$name}` instead of redeclaring it - .note = file modules are usually placed outside of blocks, at the top level of the file - -expand_module_multiple_candidates = - file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}" - .help = delete or rename one of them to remove the ambiguity - -expand_must_repeat_once = - this must repeat at least once - -expand_mve_extra_tokens = - unexpected trailing tokens - .label = for this metavariable expression - .range = the `{$name}` metavariable expression takes between {$min_or_exact_args} and {$max_args} arguments - .exact = the `{$name}` metavariable expression takes {$min_or_exact_args -> - [zero] no arguments - [one] a single argument - *[other] {$min_or_exact_args} arguments - } - .suggestion = try removing {$extra_count -> - [one] this token - *[other] these tokens - } - -expand_mve_missing_paren = - expected `(` - .label = for this this metavariable expression - .unexpected = unexpected token - .note = metavariable expressions use function-like parentheses syntax - .suggestion = try adding parentheses - -expand_mve_unrecognized_expr = - unrecognized metavariable expression - .label = not a valid metavariable expression - .note = valid metavariable expressions are {$valid_expr_list} - -expand_mve_unrecognized_var = - variable `{$key}` is not recognized in meta-variable expression - -expand_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - .suggestion = use pat_param to preserve semantics - -expand_proc_macro_back_compat = using an old version of `{$crate_name}` - .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives - -expand_proc_macro_derive_panicked = - proc-macro derive panicked - .help = message: {$message} - -expand_proc_macro_derive_tokens = - proc-macro derive produced unparsable tokens - -expand_proc_macro_panicked = - proc macro panicked - .help = message: {$message} - -expand_recursion_limit_reached = - recursion limit reached while expanding `{$descr}` - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) - -expand_remove_expr_not_supported = - removing an expression is not supported in this position - -expand_remove_node_not_supported = - removing {$descr} is not supported in this position - -expand_resolve_relative_path = - cannot resolve relative path in non-file source `{$path}` - -expand_trace_macro = trace_macro - -expand_trailing_semi_macro = trailing semicolon in macro used in expression position - .note1 = macro invocations at the end of a block are treated as expressions - .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` - -expand_unknown_macro_variable = unknown macro variable `{$name}` - -expand_unsupported_key_value = - key-value macro attributes are not supported - -expand_unused_builtin_attribute = unused attribute `{$attr_name}` - .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}` - .suggestion = remove the attribute - -expand_wrong_fragment_kind = - non-{$kind} macro in {$kind} position: {$name} diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 653f2071d898..5efaea44b3b9 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -919,7 +919,7 @@ impl SyntaxExtension { fn get_hide_backtrace(attrs: &[hir::Attribute]) -> bool { // FIXME(estebank): instead of reusing `#[rustc_diagnostic_item]` as a proxy, introduce a // new attribute purely for this under the `#[diagnostic]` namespace. - ast::attr::find_by_name(attrs, sym::rustc_diagnostic_item).is_some() + find_attr!(attrs, AttributeKind::RustcDiagnosticItem(..)) } /// Constructs a syntax extension with the given properties @@ -962,14 +962,8 @@ impl SyntaxExtension { let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability); - // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) { - sess.dcx().emit_err(errors::MacroConstStability { - span: sp, - head_span: sess.source_map().guess_head_span(span), - }); - } - if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) { + if let Some(sp) = find_attr!(attrs, AttributeKind::RustcBodyStability{ span, .. } => *span) + { sess.dcx().emit_err(errors::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index e5c06889f3e0..7320ee12abe3 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -727,7 +727,7 @@ impl<'a> ExtCtxt<'a> { span: Span, ident: Ident, ty: Box, - rhs: ast::ConstItemRhs, + rhs_kind: ast::ConstItemRhsKind, ) -> Box { let defaultness = ast::Defaultness::Final; self.item( @@ -740,7 +740,7 @@ impl<'a> ExtCtxt<'a> { // FIXME(generic_const_items): Pass the generics as a parameter. generics: ast::Generics::default(), ty, - rhs: Some(rhs), + rhs_kind, define_opaque: None, } .into(), diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 4887bfa44588..c7d2e273a76f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -15,11 +15,13 @@ use rustc_attr_parsing::{ AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; +use rustc_errors::msg; use rustc_feature::{ ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES, }; use rustc_hir::Target; +use rustc_parse::parser::Recovery; use rustc_session::Session; use rustc_session::parse::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; @@ -395,7 +397,9 @@ impl<'a> StripUnconfigured<'a> { fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { !is_cfg(attr) - || self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool() + || self + .cfg_true(attr, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }) + .as_bool() }) } @@ -429,14 +433,14 @@ impl<'a> StripUnconfigured<'a> { &self.sess, sym::stmt_expr_attributes, attr.span, - crate::fluent_generated::expand_attributes_on_expressions_experimental, + msg!("attributes on expressions are experimental"), ); if attr.is_doc_comment() { err.help(if attr.style == AttrStyle::Outer { - crate::fluent_generated::expand_help_outer_doc + msg!("`///` is used for outer documentation comments; for a plain comment, use `//`") } else { - crate::fluent_generated::expand_help_inner_doc + msg!("`//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`") }); } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 9f9764e060d1..b6fcc13321ee 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -7,32 +7,34 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol}; #[derive(LintDiagnostic)] -#[diag(expand_cfg_attr_no_attributes)] +#[diag("`#[cfg_attr]` does not expand to any attributes")] pub(crate) struct CfgAttrNoAttributes; #[derive(Diagnostic)] -#[diag(expand_expr_repeat_no_syntax_vars)] +#[diag( + "attempted to repeat an expression containing no syntax variables matched as repeating at this depth" +)] pub(crate) struct NoSyntaxVarsExprRepeat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_must_repeat_once)] +#[diag("this must repeat at least once")] pub(crate) struct MustRepeatOnce { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_count_repetition_misplaced)] +#[diag("`count` can not be placed inside the innermost repetition")] pub(crate) struct CountRepetitionMisplaced { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_metavar_still_repeating)] +#[diag("variable `{$ident}` is still repeating at this depth")] pub(crate) struct MacroVarStillRepeating { #[primary_span] pub span: Span, @@ -40,24 +42,24 @@ pub(crate) struct MacroVarStillRepeating { } #[derive(LintDiagnostic)] -#[diag(expand_metavar_still_repeating)] +#[diag("variable `{$ident}` is still repeating at this depth")] pub(crate) struct MetaVarStillRepeatingLint { - #[label] + #[label("expected repetition")] pub label: Span, pub ident: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] -#[diag(expand_metavariable_wrong_operator)] +#[diag("meta-variable repeats with different Kleene operator")] pub(crate) struct MetaVariableWrongOperator { - #[label(expand_binder_label)] + #[label("expected repetition")] pub binder: Span, - #[label(expand_occurrence_label)] + #[label("conflicting repetition")] pub occurrence: Span, } #[derive(Diagnostic)] -#[diag(expand_meta_var_dif_seq_matchers)] +#[diag("{$msg}")] pub(crate) struct MetaVarsDifSeqMatchers { #[primary_span] pub span: Span, @@ -65,13 +67,13 @@ pub(crate) struct MetaVarsDifSeqMatchers { } #[derive(LintDiagnostic)] -#[diag(expand_unknown_macro_variable)] +#[diag("unknown macro variable `{$name}`")] pub(crate) struct UnknownMacroVariable { pub name: MacroRulesNormalizedIdent, } #[derive(Diagnostic)] -#[diag(expand_resolve_relative_path)] +#[diag("cannot resolve relative path in non-file source `{$path}`")] pub(crate) struct ResolveRelativePath { #[primary_span] pub span: Span, @@ -79,31 +81,21 @@ pub(crate) struct ResolveRelativePath { } #[derive(Diagnostic)] -#[diag(expand_macro_const_stability)] -pub(crate) struct MacroConstStability { - #[primary_span] - #[label] - pub span: Span, - #[label(expand_label2)] - pub head_span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_macro_body_stability)] +#[diag("macros cannot have body stability attributes")] pub(crate) struct MacroBodyStability { #[primary_span] - #[label] + #[label("invalid body stability attribute")] pub span: Span, - #[label(expand_label2)] + #[label("body stability attribute affects this macro")] pub head_span: Span, } #[derive(Diagnostic)] -#[diag(expand_feature_removed, code = E0557)] -#[note] +#[diag("feature has been removed", code = E0557)] +#[note("removed in {$removed_rustc_version}{$pull_note}")] pub(crate) struct FeatureRemoved<'a> { #[primary_span] - #[label] + #[label("feature has been removed")] pub span: Span, #[subdiagnostic] pub reason: Option>, @@ -112,13 +104,13 @@ pub(crate) struct FeatureRemoved<'a> { } #[derive(Subdiagnostic)] -#[note(expand_reason)] +#[note("{$reason}")] pub(crate) struct FeatureRemovedReason<'a> { pub reason: &'a str, } #[derive(Diagnostic)] -#[diag(expand_feature_not_allowed, code = E0725)] +#[diag("the feature `{$name}` is not in the list of allowed features", code = E0725)] pub(crate) struct FeatureNotAllowed { #[primary_span] pub span: Span, @@ -126,8 +118,10 @@ pub(crate) struct FeatureNotAllowed { } #[derive(Diagnostic)] -#[diag(expand_recursion_limit_reached)] -#[help] +#[diag("recursion limit reached while expanding `{$descr}`")] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] pub(crate) struct RecursionLimitReached { #[primary_span] pub span: Span, @@ -137,7 +131,7 @@ pub(crate) struct RecursionLimitReached { } #[derive(Diagnostic)] -#[diag(expand_malformed_feature_attribute, code = E0556)] +#[diag("malformed `feature` attribute input", code = E0556)] pub(crate) struct MalformedFeatureAttribute { #[primary_span] pub span: Span, @@ -147,12 +141,16 @@ pub(crate) struct MalformedFeatureAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedFeatureAttributeHelp { - #[label(expand_expected)] + #[label("expected just one word")] Label { #[primary_span] span: Span, }, - #[suggestion(expand_expected, code = "{suggestion}", applicability = "maybe-incorrect")] + #[suggestion( + "expected just one word", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] Suggestion { #[primary_span] span: Span, @@ -161,7 +159,7 @@ pub(crate) enum MalformedFeatureAttributeHelp { } #[derive(Diagnostic)] -#[diag(expand_remove_expr_not_supported)] +#[diag("removing an expression is not supported in this position")] pub(crate) struct RemoveExprNotSupported { #[primary_span] pub span: Span, @@ -169,32 +167,32 @@ pub(crate) struct RemoveExprNotSupported { #[derive(Diagnostic)] pub(crate) enum InvalidCfg { - #[diag(expand_invalid_cfg_no_parens)] + #[diag("`cfg` is not followed by parentheses")] NotFollowedByParens { #[primary_span] #[suggestion( - expand_invalid_cfg_expected_syntax, + "expected syntax is", code = "cfg(/* predicate */)", applicability = "has-placeholders" )] span: Span, }, - #[diag(expand_invalid_cfg_no_predicate)] + #[diag("`cfg` predicate is not specified")] NoPredicate { #[primary_span] #[suggestion( - expand_invalid_cfg_expected_syntax, + "expected syntax is", code = "cfg(/* predicate */)", applicability = "has-placeholders" )] span: Span, }, - #[diag(expand_invalid_cfg_multiple_predicates)] + #[diag("multiple `cfg` predicates are specified")] MultiplePredicates { #[primary_span] span: Span, }, - #[diag(expand_invalid_cfg_predicate_literal)] + #[diag("`cfg` predicate key cannot be a literal")] PredicateLiteral { #[primary_span] span: Span, @@ -202,7 +200,7 @@ pub(crate) enum InvalidCfg { } #[derive(Diagnostic)] -#[diag(expand_wrong_fragment_kind)] +#[diag("non-{$kind} macro in {$kind} position: {$name}")] pub(crate) struct WrongFragmentKind<'a> { #[primary_span] pub span: Span, @@ -211,28 +209,28 @@ pub(crate) struct WrongFragmentKind<'a> { } #[derive(Diagnostic)] -#[diag(expand_unsupported_key_value)] +#[diag("key-value macro attributes are not supported")] pub(crate) struct UnsupportedKeyValue { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_incomplete_parse)] -#[note] +#[diag("macro expansion ignores {$descr} and any tokens following")] +#[note("the usage of `{$macro_path}!` is likely invalid in {$kind_name} context")] pub(crate) struct IncompleteParse<'a> { #[primary_span] pub span: Span, pub descr: String, - #[label] + #[label("caused by the macro expansion here")] pub label_span: Span, pub macro_path: &'a ast::Path, pub kind_name: &'a str, - #[note(expand_macro_expands_to_match_arm)] + #[note("macros cannot expand to match arms")] pub expands_to_match_arm: bool, #[suggestion( - expand_suggestion_add_semi, + "you might be missing a semicolon here", style = "verbose", code = ";", applicability = "maybe-incorrect" @@ -241,7 +239,7 @@ pub(crate) struct IncompleteParse<'a> { } #[derive(Diagnostic)] -#[diag(expand_remove_node_not_supported)] +#[diag("removing {$descr} is not supported in this position")] pub(crate) struct RemoveNodeNotSupported { #[primary_span] pub span: Span, @@ -249,7 +247,7 @@ pub(crate) struct RemoveNodeNotSupported { } #[derive(Diagnostic)] -#[diag(expand_module_circular)] +#[diag("circular modules: {$modules}")] pub(crate) struct ModuleCircular { #[primary_span] pub span: Span, @@ -257,8 +255,8 @@ pub(crate) struct ModuleCircular { } #[derive(Diagnostic)] -#[diag(expand_module_in_block)] -#[note] +#[diag("cannot declare a file module inside a block unless it has a path attribute")] +#[note("file modules are usually placed outside of blocks, at the top level of the file")] pub(crate) struct ModuleInBlock { #[primary_span] pub span: Span, @@ -267,7 +265,7 @@ pub(crate) struct ModuleInBlock { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("maybe `use` the module `{$name}` instead of redeclaring it")] pub(crate) struct ModuleInBlockName { #[primary_span] pub span: Span, @@ -275,9 +273,11 @@ pub(crate) struct ModuleInBlockName { } #[derive(Diagnostic)] -#[diag(expand_module_file_not_found, code = E0583)] -#[help] -#[note] +#[diag("file not found for module `{$name}`", code = E0583)] +#[help("to create the module `{$name}`, create file \"{$default_path}\" or \"{$secondary_path}\"")] +#[note( + "if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead" +)] pub(crate) struct ModuleFileNotFound { #[primary_span] pub span: Span, @@ -287,8 +287,8 @@ pub(crate) struct ModuleFileNotFound { } #[derive(Diagnostic)] -#[diag(expand_module_multiple_candidates, code = E0761)] -#[help] +#[diag("file for module `{$name}` found at both \"{$default_path}\" and \"{$secondary_path}\"", code = E0761)] +#[help("delete or rename one of them to remove the ambiguity")] pub(crate) struct ModuleMultipleCandidates { #[primary_span] pub span: Span, @@ -298,14 +298,14 @@ pub(crate) struct ModuleMultipleCandidates { } #[derive(Diagnostic)] -#[diag(expand_trace_macro)] +#[diag("trace_macro")] pub(crate) struct TraceMacro { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_panicked)] +#[diag("proc macro panicked")] pub(crate) struct ProcMacroPanicked { #[primary_span] pub span: Span, @@ -314,13 +314,13 @@ pub(crate) struct ProcMacroPanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct ProcMacroPanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_derive_panicked)] +#[diag("proc-macro derive panicked")] pub(crate) struct ProcMacroDerivePanicked { #[primary_span] pub span: Span, @@ -329,13 +329,13 @@ pub(crate) struct ProcMacroDerivePanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct ProcMacroDerivePanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_custom_attribute_panicked)] +#[diag("custom attribute panicked")] pub(crate) struct CustomAttributePanicked { #[primary_span] pub span: Span, @@ -344,46 +344,46 @@ pub(crate) struct CustomAttributePanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct CustomAttributePanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_derive_tokens)] +#[diag("proc-macro derive produced unparsable tokens")] pub(crate) struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_duplicate_matcher_binding)] +#[diag("duplicate matcher binding")] pub(crate) struct DuplicateMatcherBinding { #[primary_span] - #[label] + #[label("duplicate binding")] pub span: Span, - #[label(expand_label2)] + #[label("previous binding")] pub prev: Span, } #[derive(LintDiagnostic)] -#[diag(expand_duplicate_matcher_binding)] +#[diag("duplicate matcher binding")] pub(crate) struct DuplicateMatcherBindingLint { - #[label] + #[label("duplicate binding")] pub span: Span, - #[label(expand_label2)] + #[label("previous binding")] pub prev: Span, } #[derive(Diagnostic)] -#[diag(expand_missing_fragment_specifier)] -#[note] -#[help(expand_valid)] +#[diag("missing fragment specifier")] +#[note("fragment specifiers must be provided")] +#[help("{$valid}")] pub(crate) struct MissingFragmentSpecifier { #[primary_span] pub span: Span, #[suggestion( - expand_suggestion_add_fragspec, + "try adding a specifier here", style = "verbose", code = ":spec", applicability = "maybe-incorrect" @@ -393,8 +393,8 @@ pub(crate) struct MissingFragmentSpecifier { } #[derive(Diagnostic)] -#[diag(expand_invalid_fragment_specifier)] -#[help] +#[diag("invalid fragment specifier `{$fragment}`")] +#[help("{$help}")] pub(crate) struct InvalidFragmentSpecifier { #[primary_span] pub span: Span, @@ -403,7 +403,7 @@ pub(crate) struct InvalidFragmentSpecifier { } #[derive(Diagnostic)] -#[diag(expand_expected_paren_or_brace)] +#[diag("expected `(` or `{\"{\"}`, found `{$token}`")] pub(crate) struct ExpectedParenOrBrace<'a> { #[primary_span] pub span: Span, @@ -411,7 +411,7 @@ pub(crate) struct ExpectedParenOrBrace<'a> { } #[derive(Diagnostic)] -#[diag(expand_empty_delegation_mac)] +#[diag("empty {$kind} delegation is not supported")] pub(crate) struct EmptyDelegationMac { #[primary_span] pub span: Span, @@ -419,28 +419,28 @@ pub(crate) struct EmptyDelegationMac { } #[derive(Diagnostic)] -#[diag(expand_glob_delegation_outside_impls)] +#[diag("glob delegation is only supported in impls")] pub(crate) struct GlobDelegationOutsideImpls { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_crate_name_in_cfg_attr)] +#[diag("`crate_name` within an `#![cfg_attr]` attribute is forbidden")] pub(crate) struct CrateNameInCfgAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_crate_type_in_cfg_attr)] +#[diag("`crate_type` within an `#![cfg_attr]` attribute is forbidden")] pub(crate) struct CrateTypeInCfgAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_glob_delegation_traitless_qpath)] +#[diag("qualified path without a trait in glob delegation")] pub(crate) struct GlobDelegationTraitlessQpath { #[primary_span] pub span: Span, @@ -449,8 +449,10 @@ pub(crate) struct GlobDelegationTraitlessQpath { // This used to be the `proc_macro_back_compat` lint (#83125). It was later // turned into a hard error. #[derive(Diagnostic)] -#[diag(expand_proc_macro_back_compat)] -#[note] +#[diag("using an old version of `{$crate_name}`")] +#[note( + "older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives" +)] pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, @@ -461,20 +463,35 @@ mod metavar_exprs { use super::*; #[derive(Diagnostic, Default)] - #[diag(expand_mve_extra_tokens)] + #[diag("unexpected trailing tokens")] pub(crate) struct MveExtraTokens { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "try removing {$extra_count -> + [one] this token + *[other] these tokens + }", + code = "", + applicability = "machine-applicable" + )] pub span: Span, - #[label] + #[label("for this metavariable expression")] pub ident_span: Span, pub extra_count: usize, // The rest is only used for specific diagnostics and can be default if neither // `note` is `Some`. - #[note(expand_exact)] + #[note( + "the `{$name}` metavariable expression takes {$min_or_exact_args -> + [zero] no arguments + [one] a single argument + *[other] {$min_or_exact_args} arguments + }" + )] pub exact_args_note: Option<()>, - #[note(expand_range)] + #[note( + "the `{$name}` metavariable expression takes between {$min_or_exact_args} and {$max_args} arguments" + )] pub range_args_note: Option<()>, pub min_or_exact_args: usize, pub max_args: usize, @@ -482,30 +499,34 @@ mod metavar_exprs { } #[derive(Diagnostic)] - #[note] - #[diag(expand_mve_missing_paren)] + #[note("metavariable expressions use function-like parentheses syntax")] + #[diag("expected `(`")] pub(crate) struct MveMissingParen { #[primary_span] - #[label] + #[label("for this this metavariable expression")] pub ident_span: Span, - #[label(expand_unexpected)] + #[label("unexpected token")] pub unexpected_span: Option, - #[suggestion(code = "( /* ... */ )", applicability = "has-placeholders")] + #[suggestion( + "try adding parentheses", + code = "( /* ... */ )", + applicability = "has-placeholders" + )] pub insert_span: Option, } #[derive(Diagnostic)] - #[note] - #[diag(expand_mve_unrecognized_expr)] + #[note("valid metavariable expressions are {$valid_expr_list}")] + #[diag("unrecognized metavariable expression")] pub(crate) struct MveUnrecognizedExpr { #[primary_span] - #[label] + #[label("not a valid metavariable expression")] pub span: Span, pub valid_expr_list: &'static str, } #[derive(Diagnostic)] - #[diag(expand_mve_unrecognized_var)] + #[diag("variable `{$key}` is not recognized in meta-variable expression")] pub(crate) struct MveUnrecognizedVar { #[primary_span] pub span: Span, @@ -514,7 +535,7 @@ mod metavar_exprs { } #[derive(Diagnostic)] -#[diag(expand_macro_args_bad_delim)] +#[diag("`{$rule_kw}` rule argument matchers require parentheses")] pub(crate) struct MacroArgsBadDelim { #[primary_span] pub span: Span, @@ -524,7 +545,10 @@ pub(crate) struct MacroArgsBadDelim { } #[derive(Subdiagnostic)] -#[multipart_suggestion(expand_macro_args_bad_delim_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "the delimiters should be `(` and `)`", + applicability = "machine-applicable" +)] pub(crate) struct MacroArgsBadDelimSugg { #[suggestion_part(code = "(")] pub open: Span, @@ -533,37 +557,54 @@ pub(crate) struct MacroArgsBadDelimSugg { } #[derive(LintDiagnostic)] -#[diag(expand_macro_call_unused_doc_comment)] -#[help] +#[diag("unused doc comment")] +#[help( + "to document an item produced by a macro, the macro must produce the documentation as part of its expansion" +)] pub(crate) struct MacroCallUnusedDocComment { - #[label] + #[label("rustdoc does not generate documentation for macro invocations")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(expand_or_patterns_back_compat)] +#[diag( + "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro" +)] pub(crate) struct OrPatternsBackCompat { - #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] + #[suggestion( + "use pat_param to preserve semantics", + code = "{suggestion}", + applicability = "machine-applicable" + )] pub span: Span, pub suggestion: String, } #[derive(LintDiagnostic)] -#[diag(expand_trailing_semi_macro)] +#[diag("trailing semicolon in macro used in expression position")] pub(crate) struct TrailingMacro { - #[note(expand_note1)] - #[note(expand_note2)] + #[note("macro invocations at the end of a block are treated as expressions")] + #[note( + "to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`" + )] pub is_trailing: bool, pub name: Ident, } #[derive(LintDiagnostic)] -#[diag(expand_unused_builtin_attribute)] +#[diag("unused attribute `{$attr_name}`")] pub(crate) struct UnusedBuiltinAttribute { - #[note] + #[note( + "the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`" + )] pub invoc_span: Span, pub attr_name: Symbol, pub macro_name: String, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub attr_span: Span, } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index cfa7725c7400..76a9a6f9d03d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -19,14 +19,14 @@ use rustc_attr_parsing::{ }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::PResult; +use rustc_errors::{PResult, msg}; use rustc_feature::Features; use rustc_hir::Target; use rustc_hir::def::MacroKinds; use rustc_hir::limit::Limit; use rustc_parse::parser::{ AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, - RecoverColon, RecoverComma, token_descr, + RecoverColon, RecoverComma, Recovery, token_descr, }; use rustc_session::Session; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; @@ -42,7 +42,6 @@ use crate::errors::{ RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, }; -use crate::fluent_generated; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{ DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod, @@ -508,6 +507,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); + let mut expanded_fragments_len = 0; let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -602,6 +602,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { expanded_fragments.push(Vec::new()); } expanded_fragments[depth - 1].push((expn_id, expanded_fragment)); + expanded_fragments_len += 1; invocations.extend(derive_invocations.into_iter().rev()); } ExpandResult::Retry(invoc) => { @@ -622,7 +623,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = orig_force_mode; // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::default(); + let mut placeholder_expander = PlaceholderExpander::with_capacity(expanded_fragments_len); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { placeholder_expander @@ -1050,7 +1051,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.sess, sym::proc_macro_hygiene, item.span, - fluent_generated::expand_file_modules_in_proc_macro_input_are_unstable, + msg!("file modules in proc macro input are unstable"), ) .emit(); } @@ -2170,7 +2171,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { call.span(), self.cx.current_expansion.lint_node_id, Some(self.cx.ecfg.features), - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; @@ -2220,7 +2221,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Target doesn't matter for `cfg` parsing. Target::Crate, self.cfg().features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, parse_cfg, &CFG_TEMPLATE, ) else { diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 89540a9a5c5b..96f17418b8d2 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -26,5 +26,3 @@ pub mod proc_macro; pub fn provide(providers: &mut rustc_middle::query::Providers) { providers.derive_macro_expansion = proc_macro::provide_derive_macro_expansion; } - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index f5edaf50edd5..df6903dc4937 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -302,12 +302,16 @@ pub(crate) fn annotate_err_with_kind(err: &mut Diag<'_>, kind: AstFragmentKind, #[derive(Subdiagnostic)] enum ExplainDocComment { - #[label(expand_explain_doc_comment_inner)] + #[label( + "inner doc comments expand to `#![doc = \"...\"]`, which is what this macro attempted to match" + )] Inner { #[primary_span] span: Span, }, - #[label(expand_explain_doc_comment_outer)] + #[label( + "outer doc comments expand to `#[doc = \"...\"]`, which is what this macro attempted to match" + )] Outer { #[primary_span] span: Span, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8d2cc23f9763..7cd96211de50 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -819,7 +819,7 @@ pub fn compile_declarative_macro( } assert!(!kinds.is_empty()); - let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) + let transparency = find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(macro_rules)); if let Some(guar) = guar { diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 05f9a5aa43f7..2db18429a521 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -218,12 +218,17 @@ pub(crate) fn placeholder( } } -#[derive(Default)] pub(crate) struct PlaceholderExpander { expanded_fragments: FxHashMap, } impl PlaceholderExpander { + pub(crate) fn with_capacity(capacity: usize) -> Self { + PlaceholderExpander { + expanded_fragments: FxHashMap::with_capacity_and_hasher(capacity, Default::default()), + } + } + pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index ea63ff7bfc46..e67855700813 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -11,32 +11,11 @@ use {rustc_ast as ast, rustc_proc_macro as pm}; use crate::base::{self, *}; use crate::{errors, proc_macro_server}; -struct MessagePipe { - tx: std::sync::mpsc::SyncSender, - rx: std::sync::mpsc::Receiver, -} - -impl pm::bridge::server::MessagePipe for MessagePipe { - fn new() -> (Self, Self) { - let (tx1, rx1) = std::sync::mpsc::sync_channel(1); - let (tx2, rx2) = std::sync::mpsc::sync_channel(1); - (MessagePipe { tx: tx1, rx: rx2 }, MessagePipe { tx: tx2, rx: rx1 }) - } - - fn send(&mut self, value: T) { - self.tx.send(value).unwrap(); - } - - fn recv(&mut self) -> Option { - self.rx.recv().ok() - } -} - fn exec_strategy(sess: &Session) -> impl pm::bridge::server::ExecutionStrategy + 'static { - pm::bridge::server::MaybeCrossThread::>::new( - sess.opts.unstable_opts.proc_macro_execution_strategy + pm::bridge::server::MaybeCrossThread { + cross_thread: sess.opts.unstable_opts.proc_macro_execution_strategy == ProcMacroExecutionStrategy::CrossThread, - ) + } } pub struct BangProcMacro { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 12490880ab0e..947b8a6e3e5e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -7,7 +7,7 @@ use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream}; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; +use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan}; use rustc_parse::lexer::{StripTokens, nfc_normalize}; use rustc_parse::parser::Parser; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; @@ -591,7 +591,7 @@ impl server::Server for Rustc<'_, '_> { fn ts_expand_expr(&mut self, stream: &Self::TokenStream) -> Result { // Parse the expression from our tokenstream. - let expr: PResult<'_, _> = try { + let expr = try { let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr")); let expr = p.parse_expr()?; if p.token != token::Eof { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ded8a5a4ae51..2c2dae0fef52 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -862,13 +862,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ register_tool, CrateLevel, template!(List: &["tool1, tool2, ..."]), DuplicatesOk, EncodeCrossCrate::No, experimental!(register_tool), ), - - // lang-team MCP 147 - gated!( - deprecated_safe, Normal, template!(List: &[r#"since = "version", note = "...""#]), ErrorFollowing, - EncodeCrossCrate::Yes, experimental!(deprecated_safe), - ), - // `#[cfi_encoding = ""]` gated!( cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding, @@ -888,13 +881,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, experimental!(patchable_function_entry) ), - // Probably temporary component of min_generic_const_args. - // `#[type_const] const ASSOC: usize;` - gated!( - type_const, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const), - ), - // The `#[loop_match]` and `#[const_continue]` attributes are part of the // lang experiment for RFC 3720 tracked in: // @@ -1329,6 +1315,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" ), + rustc_attr!( + rustc_non_const_trait_method, AttributeType::Normal, template!(Word), + ErrorFollowing, EncodeCrossCrate::No, + "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ + as non-const to allow large traits an easier transition to const" + ), BuiltinAttribute { name: sym::rustc_diagnostic_item, diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 4ba50d03d707..619726f0d5d8 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -136,5 +136,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, + UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 4f4691468911..71a735cd8cc7 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -102,6 +102,8 @@ declare_features! ( /// Allows default type parameters to influence type inference. (removed, default_type_parameter_fallback, "1.82.0", Some(27336), Some("never properly implemented; requires significant design work"), 127655), + /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait + (removed, deprecated_safe, "CURRENT_RUSTC_VERSION", Some(94978), Some("never properly implemented, in the way of attribute refactor"), 152554), /// Allows deriving traits as per `SmartPointer` specification (removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c99af9658cde..082558cf9a93 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -373,6 +373,8 @@ declare_features! ( (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows `async` trait bound modifier. (unstable, async_trait_bounds, "1.85.0", Some(62290)), + /// Target features on avr. + (unstable, avr_target_feature, "CURRENT_RUSTC_VERSION", Some(146889)), /// Allows using Intel AVX10 target features and intrinsics (unstable, avx10_target_feature, "1.88.0", Some(138843)), /// Target features on bpf. @@ -392,6 +394,8 @@ declare_features! ( (unstable, cfg_sanitize, "1.41.0", Some(39699)), /// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. (unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)), + /// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times. + (unstable, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)), /// Allows `cfg(target(abi = "..."))`. (unstable, cfg_target_compact, "1.63.0", Some(96901)), /// Allows `cfg(target_has_atomic_load_store = "...")`. @@ -450,8 +454,6 @@ declare_features! ( /// Allows the use of default values on struct definitions and the construction of struct /// literals with the functional update syntax without a base. (unstable, default_field_values, "1.85.0", Some(132162)), - /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait - (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), /// Allows deref patterns. @@ -557,6 +559,8 @@ declare_features! ( (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), + /// Enable mgca `type const` syntax before expansion. + (incomplete, mgca_type_const_syntax, "CURRENT_RUSTC_VERSION", Some(132980)), /// Enables the generic const args MVP (only bare paths, not arbitrary computation). (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the @@ -601,6 +605,8 @@ declare_features! ( (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! (unstable, offset_of_slice, "1.81.0", Some(126151)), + /// Allows using generics in more complex const expressions, based on definitional equality. + (unstable, opaque_generic_const_args, "CURRENT_RUSTC_VERSION", Some(151972)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows specifying nop padding on functions for dynamic patching. @@ -778,3 +784,9 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ // boolean logic required to tell which typing rules to use. (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; + +/// Some features require one or more other features to be enabled. +pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ + (sym::opaque_generic_const_args, &[sym::min_generic_const_args]), + (sym::unsized_const_params, &[sym::adt_const_params]), +]; diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml deleted file mode 100644 index d7ef4280aef0..000000000000 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rustc_fluent_macro" -version = "0.0.0" -edition = "2024" - -[lib] -proc-macro = true - -[dependencies] -# tidy-alphabetical-start -annotate-snippets = "0.11" -fluent-bundle = "0.16" -fluent-syntax = "0.12" -proc-macro2 = "1" -quote = "1" -syn = { version = "2", features = ["full"] } -unic-langid = { version = "0.9.0", features = ["macros"] } -# tidy-alphabetical-end diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs deleted file mode 100644 index 41357bb1ac76..000000000000 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ /dev/null @@ -1,315 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::fs::read_to_string; -use std::path::{Path, PathBuf}; - -use annotate_snippets::{Renderer, Snippet}; -use fluent_bundle::{FluentBundle, FluentError, FluentResource}; -use fluent_syntax::ast::{ - Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement, -}; -use fluent_syntax::parser::ParserError; -use proc_macro::tracked::path; -use proc_macro::{Diagnostic, Level, Span}; -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Ident, LitStr, parse_macro_input}; -use unic_langid::langid; - -/// Helper function for returning an absolute path for macro-invocation relative file paths. -/// -/// If the input is already absolute, then the input is returned. If the input is not absolute, -/// then it is appended to the directory containing the source file with this macro invocation. -fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf { - let path = Path::new(path); - if path.is_absolute() { - path.to_path_buf() - } else { - // `/a/b/c/foo/bar.rs` contains the current macro invocation - let mut source_file_path = span.local_file().unwrap(); - // `/a/b/c/foo/` - source_file_path.pop(); - // `/a/b/c/foo/../locales/en-US/example.ftl` - source_file_path.push(path); - source_file_path - } -} - -/// Final tokens. -fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream { - 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 = #resource; - - #[allow(non_upper_case_globals)] - #[doc(hidden)] - /// Auto-generated constants for type-checked references to Fluent messages. - pub(crate) mod fluent_generated { - #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: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); - /// Default for `#[note]` - pub const note: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); - /// Default for `#[warn]` - pub const warn: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); - /// Default for `#[label]` - pub const label: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); - /// Default for `#[suggestion]` - pub const suggestion: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); - } - } - } - .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_CRATE_NAME") - // If `CARGO_CRATE_NAME` is missing, then we're probably running in a test, so use - // `no_crate`. - .unwrap_or_else(|_| "no_crate".to_string()) - .replace("rustc_", ""); - - // Cannot iterate over individual messages in a bundle, so do that using the - // `FluentResource` instead. Construct a bundle anyway to find out if there are conflicting - // messages in the resources. - let mut bundle = FluentBundle::new(vec![langid!("en-US")]); - - // Set of Fluent attribute names already output, to avoid duplicate type errors - any given - // constant created for a given attribute is the same. - let mut previous_attrs = HashSet::new(); - - let resource_str = parse_macro_input!(input as LitStr); - let resource_span = resource_str.span().unwrap(); - let relative_ftl_path = resource_str.value(); - let absolute_ftl_path = invocation_relative_path_to_absolute(resource_span, &relative_ftl_path); - - let crate_name = Ident::new(&crate_name, resource_str.span()); - - path(absolute_ftl_path.to_str().unwrap()); - let resource_contents = match read_to_string(absolute_ftl_path) { - Ok(resource_contents) => resource_contents, - Err(e) => { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("could not open Fluent resource: {e}"), - ) - .emit(); - return failed(&crate_name); - } - }; - let mut bad = false; - for esc in ["\\n", "\\\"", "\\'"] { - for _ in resource_contents.matches(esc) { - bad = true; - Diagnostic::spanned(resource_span, Level::Error, format!("invalid escape `{esc}` in Fluent resource")) - .note("Fluent does not interpret these escape sequences ()") - .emit(); - } - } - if bad { - return failed(&crate_name); - } - - let resource = match FluentResource::try_new(resource_contents) { - Ok(resource) => resource, - Err((this, errs)) => { - Diagnostic::spanned(resource_span, Level::Error, "could not parse Fluent resource") - .help("see additional errors emitted") - .emit(); - for ParserError { pos, slice: _, kind } in errs { - let mut err = kind.to_string(); - // Entirely unnecessary string modification so that the error message starts - // with a lowercase as rustc errors do. - err.replace_range(0..1, &err.chars().next().unwrap().to_lowercase().to_string()); - - let message = annotate_snippets::Level::Error.title(&err).snippet( - Snippet::source(this.source()) - .origin(&relative_ftl_path) - .fold(true) - .annotation(annotate_snippets::Level::Error.span(pos.start..pos.end - 1)), - ); - let renderer = Renderer::plain(); - eprintln!("{}\n", renderer.render(message)); - } - - return failed(&crate_name); - } - }; - - let mut constants = TokenStream::new(); - let mut previous_defns = HashMap::new(); - let mut message_refs = Vec::new(); - for entry in resource.entries() { - if let Entry::Message(msg) = entry { - let Message { id: Identifier { name }, attributes, value, .. } = msg; - let _ = previous_defns.entry(name.to_string()).or_insert(resource_span); - if name.contains('-') { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("name `{name}` contains a '-' character"), - ) - .help("replace any '-'s with '_'s") - .emit(); - } - - if let Some(Pattern { elements }) = value { - for elt in elements { - if let PatternElement::Placeable { - expression: - Expression::Inline(InlineExpression::MessageReference { id, .. }), - } = elt - { - message_refs.push((id.name, *name)); - } - } - } - - // `typeck_foo_bar` => `foo_bar` (in `typeck.ftl`) - // `const_eval_baz` => `baz` (in `const_eval.ftl`) - // `const-eval-hyphen-having` => `hyphen_having` (in `const_eval.ftl`) - // The last case we error about above, but we want to fall back gracefully - // so that only the error is being emitted and not also one about the macro - // failing. - let crate_prefix = format!("{crate_name}_"); - - let snake_name = name.replace('-', "_"); - if !snake_name.starts_with(&crate_prefix) { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("name `{name}` does not start with the crate name"), - ) - .help(format!( - "prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`" - )) - .emit(); - }; - let snake_name = Ident::new(&snake_name, resource_str.span()); - - if !previous_attrs.insert(snake_name.clone()) { - continue; - } - - let docstr = - format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); - constants.extend(quote! { - #[doc = #docstr] - pub const #snake_name: rustc_errors::DiagMessage = - rustc_errors::DiagMessage::FluentIdentifier( - std::borrow::Cow::Borrowed(#name), - None - ); - }); - - for Attribute { id: Identifier { name: attr_name }, .. } in attributes { - let snake_name = Ident::new( - &format!("{crate_prefix}{}", attr_name.replace('-', "_")), - resource_str.span(), - ); - if !previous_attrs.insert(snake_name.clone()) { - continue; - } - - if attr_name.contains('-') { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("attribute `{attr_name}` contains a '-' character"), - ) - .help("replace any '-'s with '_'s") - .emit(); - } - - let msg = format!( - "Constant referring to Fluent message `{name}.{attr_name}` from `{crate_name}`" - ); - constants.extend(quote! { - #[doc = #msg] - pub const #snake_name: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name)); - }); - } - - // Record variables referenced by these messages so we can produce - // tests in the derive diagnostics to validate them. - let ident = quote::format_ident!("{snake_name}_refs"); - let vrefs = variable_references(msg); - constants.extend(quote! { - #[cfg(test)] - pub const #ident: &[&str] = &[#(#vrefs),*]; - }) - } - } - - for (mref, name) in message_refs.into_iter() { - if !previous_defns.contains_key(mref) { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("referenced message `{mref}` does not exist (in message `{name}`)"), - ) - .help(format!("you may have meant to use a variable reference (`{{${mref}}}`)")) - .emit(); - } - } - - if let Err(errs) = bundle.add_resource(resource) { - for e in errs { - match e { - FluentError::Overriding { kind, id } => { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("overrides existing {kind}: `{id}`"), - ) - .emit(); - } - FluentError::ResolverError(_) | FluentError::ParserError(_) => unreachable!(), - } - } - } - - finish(constants, quote! { include_str!(#relative_ftl_path) }) -} - -fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> { - let mut refs = vec![]; - if let Some(Pattern { elements }) = &msg.value { - for elt in elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); - } - } - } - for attr in &msg.attributes { - for elt in &attr.value.elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); - } - } - } - refs -} diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs deleted file mode 100644 index 9cd947c4c672..000000000000 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -// tidy-alphabetical-start -#![allow(rustc::default_hash_types)] -#![feature(proc_macro_diagnostic)] -#![feature(proc_macro_tracked_path)] -// tidy-alphabetical-end - -use proc_macro::TokenStream; - -mod fluent; - -/// Implements the `fluent_messages` macro, which performs compile-time validation of the -/// compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same -/// messages) and generates constants that make using those messages in diagnostics more ergonomic. -/// -/// For example, given the following invocation of the macro.. -/// -/// ```ignore (rust) -/// fluent_messages! { "./typeck.ftl" } -/// ``` -/// ..where `typeck.ftl` has the following contents.. -/// -/// ```fluent -/// typeck_field_multiply_specified_in_initializer = -/// field `{$ident}` specified more than once -/// .label = used more than once -/// .label_previous_use = first use of `{$ident}` -/// ``` -/// ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and -/// will generate the following code: -/// -/// ```ignore (rust) -/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl"); -/// -/// mod fluent_generated { -/// mod typeck { -/// pub const field_multiply_specified_in_initializer: DiagMessage = -/// DiagMessage::fluent("typeck_field_multiply_specified_in_initializer"); -/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagMessage = -/// DiagMessage::fluent_attr( -/// "typeck_field_multiply_specified_in_initializer", -/// "previous_use_label" -/// ); -/// } -/// } -/// ``` -/// When emitting a diagnostic, the generated constants can be used as follows: -/// -/// ```ignore (rust) -/// let mut err = sess.struct_span_err( -/// span, -/// fluent::typeck::field_multiply_specified_in_initializer -/// ); -/// err.span_default_label(span); -/// err.span_label( -/// previous_use_span, -/// fluent::typeck::field_multiply_specified_in_initializer_label_previous_use -/// ); -/// err.emit(); -/// ``` -/// -/// Note: any crate using this macro must also have a dependency on -/// `rustc_errors`, because the generated code refers to things from that -/// crate. -#[proc_macro] -pub fn fluent_messages(input: TokenStream) -> TokenStream { - fluent::fluent_messages(input) -} diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 8a7dee15d4f4..3798a586c051 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -5,9 +5,10 @@ pub use ReprAttr::*; use rustc_abi::Align; pub use rustc_ast::attr::data_structures::*; use rustc_ast::token::DocFragmentKind; -use rustc_ast::{AttrStyle, ast}; +use rustc_ast::{AttrStyle, Path, ast}; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; +use rustc_hir::LangItem; use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute}; use rustc_span::def_id::DefId; use rustc_span::hygiene::Transparency; @@ -49,6 +50,57 @@ pub struct EiiDecl { pub name: Ident, } +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] +pub enum CguKind { + No, + PreDashLto, + PostDashLto, + Any, +} + +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] +pub enum CguFields { + PartitionReused { cfg: Symbol, module: Symbol }, + PartitionCodegened { cfg: Symbol, module: Symbol }, + ExpectedCguReuse { cfg: Symbol, module: Symbol, kind: CguKind }, +} + +#[derive(Copy, Clone, PartialEq, Debug, PrintAttribute)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum DivergingFallbackBehavior { + /// Always fallback to `()` (aka "always spontaneous decay") + ToUnit, + /// Always fallback to `!` (which should be equivalent to never falling back + not making + /// never-to-any coercions unless necessary) + ToNever, + /// Don't fallback at all + NoFallback, +} + +#[derive(Copy, Clone, PartialEq, Debug, PrintAttribute, Default)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum DivergingBlockBehavior { + /// This is the current stable behavior: + /// + /// ```rust + /// { + /// return; + /// } // block has type = !, even though we are supposedly dropping it with `;` + /// ``` + #[default] + Never, + + /// Alternative behavior: + /// + /// ```ignore (very-unstable-new-attribute) + /// #![rustc_never_type_options(diverging_block_default = "unit")] + /// { + /// return; + /// } // block has type = (), since we are dropping `!` from `return` with `;` + /// ``` + Unit, +} + #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] pub enum InlineAttr { None, @@ -167,6 +219,14 @@ pub enum CoverageAttrKind { Off, } +/// Successfully-parsed value of a `#[rustc_abi(..)]` attribute. +#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum RustcAbiAttrKind { + Debug, + AssertEq, +} + impl Deprecation { /// Whether an item marked with #[deprecated(since = "X")] is currently /// deprecated (i.e., whether X is not greater than the current rustc @@ -331,6 +391,8 @@ pub enum NativeLibKind { bundle: Option, /// Whether to link static library without throwing any object files away whole_archive: Option, + /// Whether to export c static library symbols + export_symbols: Option, }, /// Dynamic library (e.g. `libfoo.so` on Linux) /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC). @@ -363,8 +425,8 @@ pub enum NativeLibKind { impl NativeLibKind { pub fn has_modifiers(&self) -> bool { match self { - NativeLibKind::Static { bundle, whole_archive } => { - bundle.is_some() || whole_archive.is_some() + NativeLibKind::Static { bundle, whole_archive, export_symbols } => { + bundle.is_some() || whole_archive.is_some() || export_symbols.is_some() } NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } @@ -690,6 +752,47 @@ impl IntoDiagArg for CrateType { } } +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub enum RustcLayoutType { + Abi, + Align, + Size, + HomogenousAggregate, + Debug, +} + +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)] +pub enum RustcMirKind { + PeekMaybeInit, + PeekMaybeUninit, + PeekLiveness, + StopAfterDataflow, + BorrowckGraphvizPostflow { path: PathBuf }, + BorrowckGraphvizFormat { format: BorrowckGraphvizFormatKind }, +} + +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)] +pub enum BorrowckGraphvizFormatKind { + TwoPhase, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub struct RustcCleanAttribute { + pub span: Span, + pub cfg: Symbol, + pub except: Option, + pub loaded_from_disk: Option, +} + +/// Represents the `except=` or `loaded_from_disk=` argument of `#[rustc_clean]` +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub struct RustcCleanQueries { + pub entries: ThinVec, + pub span: Span, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -746,31 +849,15 @@ pub enum AttributeKind { // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity Align { align: Align, span: Span }, - /// Represents `#[rustc_allow_const_fn_unstable]`. - AllowConstFnUnstable(ThinVec, Span), - - /// Represents `#[rustc_allow_incoherent_impl]`. - AllowIncoherentImpl(Span), - /// Represents `#[allow_internal_unsafe]`. AllowInternalUnsafe(Span), /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), - /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). - AsPtr(Span), - /// Represents `#[automatically_derived]` AutomaticallyDerived(Span), - /// Represents `#[rustc_default_body_unstable]`. - BodyStability { - stability: DefaultBodyStability, - /// Span of the `#[rustc_default_body_unstable(...)]` attribute - span: Span, - }, - /// Represents the trace attribute of `#[cfg_attr]` CfgAttrTrace, @@ -780,9 +867,6 @@ pub enum AttributeKind { /// Represents `#[cfi_encoding]` CfiEncoding { encoding: Symbol }, - /// Represents `#[rustc_coinductive]`. - Coinductive(Span), - /// Represents `#[cold]`. Cold(Span), @@ -792,26 +876,9 @@ pub enum AttributeKind { /// Represents `#[compiler_builtins]`. CompilerBuiltins, - /// Represents `#[rustc_confusables]`. - Confusables { - symbols: ThinVec, - // FIXME(jdonszelmann): remove when target validation code is moved - first_span: Span, - }, - /// Represents `#[const_continue]`. ConstContinue(Span), - /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. - ConstStability { - stability: PartialConstStability, - /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute - span: Span, - }, - - /// Represents `#[rustc_const_stable_indirect]`. - ConstStabilityIndirect, - /// Represents `#[coroutine]`. Coroutine(Span), @@ -830,9 +897,6 @@ pub enum AttributeKind { /// Represents `#[debugger_visualizer]`. DebuggerVisualizer(ThinVec), - /// Represents `#[rustc_deny_explicit_impl]`. - DenyExplicitImpl(Span), - /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute). Deprecation { deprecation: Deprecation, span: Span }, @@ -848,12 +912,6 @@ pub enum AttributeKind { /// i.e. doc comments. DocComment { style: AttrStyle, kind: DocFragmentKind, span: Span, comment: Symbol }, - /// Represents `#[rustc_dummy]`. - Dummy, - - /// Represents `#[rustc_dyn_incompatible_trait]`. - DynIncompatibleTrait(Span), - /// Implementation detail of `#[eii]` EiiDeclaration(EiiDecl), @@ -896,6 +954,9 @@ pub enum AttributeKind { /// Represents `#[instruction_set]` InstructionSet(InstructionSetAttr), + /// Represents `#[lang]` + Lang(LangItem, Span), + /// Represents `#[link]`. Link(ThinVec, Span), @@ -920,9 +981,6 @@ pub enum AttributeKind { /// Represents [`#[macro_export]`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path). MacroExport { span: Span, local_inner_macros: bool }, - /// Represents `#[rustc_macro_transparency]`. - MacroTransparency(Transparency), - /// Represents `#[macro_use]`. MacroUse { span: Span, arguments: MacroUseArgs }, @@ -978,24 +1036,12 @@ pub enum AttributeKind { /// Represents `#[non_exhaustive]` NonExhaustive(Span), - /// Represents `#[rustc_objc_class]` - ObjcClass { classname: Symbol, span: Span }, - - /// Represents `#[rustc_objc_selector]` - ObjcSelector { methname: Symbol, span: Span }, - /// Represents `#[optimize(size|speed)]` Optimize(OptimizeAttr, Span), /// Represents `#[panic_runtime]` PanicRuntime, - /// Represents `#[rustc_paren_sugar]`. - ParenSugar(Span), - - /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint). - PassByValue(Span), - /// Represents `#[patchable_function_entry]` PatchableFunctionEntry { prefix: u8, entry: u8 }, @@ -1011,6 +1057,9 @@ pub enum AttributeKind { /// Represents `#[pointee]` Pointee(Span), + /// Represents `#[prelude_import]` + PreludeImport, + /// Represents `#[proc_macro]` ProcMacro(Span), @@ -1023,15 +1072,18 @@ pub enum AttributeKind { /// Represents `#[profiler_runtime]` ProfilerRuntime, - /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). - PubTransparent(Span), - /// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[reexport_test_harness_main]` + ReexportTestHarnessMain(Symbol), + /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, + /// Represents `#[rustc_abi(..)]` + RustcAbi { attr_span: Span, kind: RustcAbiAttrKind }, + /// Represents `#[rustc_allocator]` RustcAllocator, @@ -1041,15 +1093,79 @@ pub enum AttributeKind { /// Represents `#[rustc_allocator_zeroed_variant]` RustcAllocatorZeroedVariant { name: Symbol }, + /// Represents `#[rustc_allow_const_fn_unstable]`. + RustcAllowConstFnUnstable(ThinVec, Span), + + /// Represents `#[rustc_allow_incoherent_impl]`. + RustcAllowIncoherentImpl(Span), + + /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). + RustcAsPtr(Span), + + /// Represents `#[rustc_default_body_unstable]`. + RustcBodyStability { + stability: DefaultBodyStability, + /// Span of the `#[rustc_default_body_unstable(...)]` attribute + span: Span, + }, /// Represents `#[rustc_builtin_macro]`. RustcBuiltinMacro { builtin_name: Option, helper_attrs: ThinVec, span: Span }, + /// Represents `#[rustc_capture_analysis]` + RustcCaptureAnalysis, + + /// Represents `#[rustc_expected_cgu_reuse]`, `#[rustc_partition_codegened]` and `#[rustc_partition_reused]`. + RustcCguTestAttr(ThinVec<(Span, CguFields)>), + + /// Represents `#[rustc_clean]` + RustcClean(ThinVec), + /// Represents `#[rustc_coherence_is_core]` RustcCoherenceIsCore(Span), + /// Represents `#[rustc_coinductive]`. + RustcCoinductive(Span), + + /// Represents `#[rustc_confusables]`. + RustcConfusables { + symbols: ThinVec, + // FIXME(jdonszelmann): remove when target validation code is moved + first_span: Span, + }, + /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. + RustcConstStability { + stability: PartialConstStability, + /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute + span: Span, + }, + + /// Represents `#[rustc_const_stable_indirect]`. + RustcConstStabilityIndirect, + + /// Represents `#[rustc_conversion_suggestion]` + RustcConversionSuggestion, + /// Represents `#[rustc_deallocator]` RustcDeallocator, + /// Represents `#[rustc_def_path]` + RustcDefPath(Span), + + /// Represents `#[rustc_delayed_bug_from_inside_query]` + RustcDelayedBugFromInsideQuery, + + /// Represents `#[rustc_deny_explicit_impl]`. + RustcDenyExplicitImpl(Span), + + /// Represents `#[rustc_deprecated_safe_2024]` + RustcDeprecatedSafe2024 { suggestion: Symbol }, + + /// Represents `#[rustc_diagnostic_item]` + RustcDiagnosticItem(Symbol), + + /// Represents `#[rustc_dummy]`. + RustcDummy, + /// Represents `#[rustc_dump_def_parents]` RustcDumpDefParents, @@ -1065,9 +1181,36 @@ pub enum AttributeKind { /// Represents `#[rustc_dump_vtable]` RustcDumpVtable(Span), + /// Represents `#[rustc_dyn_incompatible_trait]`. + RustcDynIncompatibleTrait(Span), + + /// Represents `#[rustc_effective_visibility]`. + RustcEffectiveVisibility, + + /// Represents `#[rustc_evaluate_where_clauses]` + RustcEvaluateWhereClauses, + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, + /// Represents `#[rustc_hidden_type_of_opaques]` + RustcHiddenTypeOfOpaques, + + /// Represents `#[rustc_if_this_changed]` + RustcIfThisChanged(Span, Option), + + /// Represents `#[rustc_insignificant_dtor]` + RustcInsignificantDtor, + + /// Represents `#[rustc_intrinsic]` + RustcIntrinsic, + + /// Represents `#[rustc_intrinsic_const_stable_indirect]` + RustcIntrinsicConstStableIndirect, + + /// Represents `#[rustc_layout]` + RustcLayout(ThinVec), + /// Represents `#[rustc_layout_scalar_valid_range_end]`. RustcLayoutScalarValidRangeEnd(Box, Span), @@ -1089,33 +1232,84 @@ pub enum AttributeKind { /// Represents `#[rustc_lint_untracked_query_information]` RustcLintUntrackedQueryInformation, + /// Represents `#[rustc_macro_transparency]`. + RustcMacroTransparency(Transparency), + /// Represents `#[rustc_main]`. RustcMain, + /// Represents `#[rustc_mir]`. + RustcMir(ThinVec), + /// Represents `#[rustc_must_implement_one_of]` RustcMustImplementOneOf { attr_span: Span, fn_names: ThinVec }, /// Represents `#[rustc_never_returns_null_ptr]` RustcNeverReturnsNullPointer, + /// Represents `#[rustc_never_type_options]`. + RustcNeverTypeOptions { + fallback: Option, + diverging_block_default: Option, + }, + /// Represents `#[rustc_no_implicit_autorefs]` RustcNoImplicitAutorefs, + /// Represents `#[rustc_no_implicit_bounds]` + RustcNoImplicitBounds, + + /// Represents `#[rustc_no_mir_inline]` + RustcNoMirInline, + + /// Represents `#[rustc_non_const_trait_method]`. + RustcNonConstTraitMethod, + /// Represents `#[rustc_nounwind]` RustcNounwind, + /// Represents `#[rustc_objc_class]` + RustcObjcClass { classname: Symbol, span: Span }, + + /// Represents `#[rustc_objc_selector]` + RustcObjcSelector { methname: Symbol, span: Span }, + /// Represents `#[rustc_object_lifetime_default]`. RustcObjectLifetimeDefault, /// Represents `#[rustc_offload_kernel]` RustcOffloadKernel, + /// Represents `#[rustc_outlives]` + RustcOutlives, + + /// Represents `#[rustc_paren_sugar]`. + RustcParenSugar(Span), + + /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint). + RustcPassByValue(Span), + /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]` RustcPassIndirectlyInNonRusticAbis(Span), + /// Represents `#[rustc_preserve_ub_checks]` + RustcPreserveUbChecks, + + /// Represents `#[rustc_proc_macro_decls]` + RustcProcMacroDecls, + + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). + RustcPubTransparent(Span), + /// Represents `#[rustc_reallocator]` RustcReallocator, + /// Represents `#[rustc_regions]` + RustcRegions, + + /// Represents `#[rustc_reservation_impl]` + RustcReservationImpl(Span, Symbol), + /// Represents `#[rustc_scalable_vector(N)]` RustcScalableVector { /// The base multiple of lanes that are in a scalable vector, if provided. `element_count` @@ -1130,6 +1324,33 @@ pub enum AttributeKind { /// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`. RustcSimdMonomorphizeLaneLimit(Limit), + /// Represents `#[rustc_skip_during_method_dispatch]`. + RustcSkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span }, + + /// Represents `#[rustc_specialization_trait]`. + RustcSpecializationTrait(Span), + + /// Represents `#[rustc_std_internal_symbol]`. + RustcStdInternalSymbol(Span), + + /// Represents `#[rustc_strict_coherence]`. + RustcStrictCoherence(Span), + + /// Represents `#[rustc_symbol_name]` + RustcSymbolName(Span), + + /// Represents `#[rustc_test_marker]` + RustcTestMarker(Symbol), + + /// Represents `#[rustc_then_this_would_need]` + RustcThenThisWouldNeed(Span, ThinVec), + + /// Represents `#[rustc_trivial_field_reads]` + RustcTrivialFieldReads, + + /// Represents `#[rustc_unsafe_specialization_marker]`. + RustcUnsafeSpecializationMarker(Span), + /// Represents `#[rustc_variance]` RustcVariance, @@ -1151,12 +1372,6 @@ pub enum AttributeKind { /// Represents `#[should_panic]` ShouldPanic { reason: Option, span: Span }, - /// Represents `#[rustc_skip_during_method_dispatch]`. - SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span }, - - /// Represents `#[rustc_specialization_trait]`. - SpecializationTrait(Span), - /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`. Stability { stability: Stability, @@ -1164,28 +1379,22 @@ pub enum AttributeKind { span: Span, }, - /// Represents `#[rustc_std_internal_symbol]`. - StdInternalSymbol(Span), - /// Represents `#[target_feature(enable = "...")]` and /// `#[unsafe(force_target_feature(enable = "...")]`. TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool }, + /// Represents `#![test_runner(path)]` + TestRunner(Path), + /// Represents `#[thread_local]` ThreadLocal, /// Represents `#[track_caller]` TrackCaller(Span), - /// Represents `#[type_const]`. - TypeConst(Span), - /// Represents `#[type_length_limit]` TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit }, - /// Represents `#[rustc_unsafe_specialization_marker]`. - UnsafeSpecializationMarker(Span), - /// Represents `#[unstable_feature_bound]`. UnstableFeatureBound(ThinVec<(Symbol, Span)>), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 356575416ade..d8b8ca90660a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -19,37 +19,26 @@ impl AttributeKind { match self { // tidy-alphabetical-start Align { .. } => No, - AllowConstFnUnstable(..) => No, - AllowIncoherentImpl(..) => No, AllowInternalUnsafe(..) => Yes, AllowInternalUnstable(..) => Yes, - AsPtr(..) => Yes, AutomaticallyDerived(..) => Yes, - BodyStability { .. } => No, CfgAttrTrace => Yes, CfgTrace(..) => Yes, CfiEncoding { .. } => Yes, - Coinductive(..) => No, Cold(..) => No, CollapseDebugInfo(..) => Yes, CompilerBuiltins => No, - Confusables { .. } => Yes, ConstContinue(..) => No, - ConstStability { .. } => Yes, - ConstStabilityIndirect => No, Coroutine(..) => No, Coverage(..) => No, CrateName { .. } => No, CrateType(_) => No, CustomMir(_, _, _) => Yes, DebuggerVisualizer(..) => No, - DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotRecommend { .. } => Yes, Doc(_) => Yes, DocComment { .. } => Yes, - Dummy => No, - DynIncompatibleTrait(..) => No, EiiDeclaration(_) => Yes, EiiForeignItem => No, EiiImpls(..) => No, @@ -61,6 +50,7 @@ impl AttributeKind { Ignore { .. } => No, Inline(..) => No, InstructionSet(..) => No, + Lang(..) => Yes, Link(..) => No, LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, @@ -69,7 +59,6 @@ impl AttributeKind { LoopMatch(..) => No, MacroEscape(..) => No, MacroExport { .. } => Yes, - MacroTransparency(..) => Yes, MacroUse { .. } => No, Marker(..) => No, MayDangle(..) => No, @@ -87,36 +76,61 @@ impl AttributeKind { NoMangle(..) => Yes, // Needed for rustdoc NoStd(..) => No, NonExhaustive(..) => Yes, // Needed for rustdoc - ObjcClass { .. } => No, - ObjcSelector { .. } => No, Optimize(..) => No, PanicRuntime => No, - ParenSugar(..) => No, - PassByValue(..) => Yes, PatchableFunctionEntry { .. } => Yes, Path(..) => No, PatternComplexityLimit { .. } => No, PinV2(..) => Yes, Pointee(..) => No, + PreludeImport => No, ProcMacro(..) => No, ProcMacroAttribute(..) => No, ProcMacroDerive { .. } => No, ProfilerRuntime => No, - PubTransparent(..) => Yes, RecursionLimit { .. } => No, + ReexportTestHarnessMain(..) => No, Repr { .. } => No, + RustcAbi { .. } => No, RustcAllocator => No, RustcAllocatorZeroed => No, RustcAllocatorZeroedVariant { .. } => Yes, + RustcAllowConstFnUnstable(..) => No, + RustcAllowIncoherentImpl(..) => No, + RustcAsPtr(..) => Yes, + RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, + RustcCaptureAnalysis => No, + RustcCguTestAttr { .. } => No, + RustcClean { .. } => No, RustcCoherenceIsCore(..) => No, + RustcCoinductive(..) => No, + RustcConfusables { .. } => Yes, + RustcConstStability { .. } => Yes, + RustcConstStabilityIndirect => No, + RustcConversionSuggestion => Yes, RustcDeallocator => No, + RustcDefPath(..) => No, + RustcDelayedBugFromInsideQuery => No, + RustcDenyExplicitImpl(..) => No, + RustcDeprecatedSafe2024 { .. } => Yes, + RustcDiagnosticItem(..) => Yes, + RustcDummy => No, RustcDumpDefParents => No, RustcDumpItemBounds => No, RustcDumpPredicates => No, RustcDumpUserArgs => No, RustcDumpVtable(..) => No, + RustcDynIncompatibleTrait(..) => No, + RustcEffectiveVisibility => Yes, + RustcEvaluateWhereClauses => Yes, RustcHasIncoherentInherentImpls => Yes, + RustcHiddenTypeOfOpaques => No, + RustcIfThisChanged(..) => No, + RustcInsignificantDtor => Yes, + RustcIntrinsic => Yes, + RustcIntrinsicConstStableIndirect => No, + RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcLegacyConstGenerics { .. } => Yes, @@ -124,32 +138,53 @@ impl AttributeKind { RustcLintOptTy => Yes, RustcLintQueryInstability => Yes, RustcLintUntrackedQueryInformation => Yes, + RustcMacroTransparency(..) => Yes, RustcMain => No, + RustcMir(..) => Yes, RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, + RustcNeverTypeOptions { .. } => No, RustcNoImplicitAutorefs => Yes, + RustcNoImplicitBounds => No, + RustcNoMirInline => Yes, + RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNounwind => No, + RustcObjcClass { .. } => No, + RustcObjcSelector { .. } => No, RustcObjectLifetimeDefault => No, RustcOffloadKernel => Yes, + RustcOutlives => No, + RustcParenSugar(..) => No, + RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, + RustcPreserveUbChecks => No, + RustcProcMacroDecls => No, + RustcPubTransparent(..) => Yes, RustcReallocator => No, + RustcRegions => No, + RustcReservationImpl(..) => Yes, RustcScalableVector { .. } => Yes, RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate + RustcSkipDuringMethodDispatch { .. } => No, + RustcSpecializationTrait(..) => No, + RustcStdInternalSymbol(..) => No, + RustcStrictCoherence(..) => Yes, + RustcSymbolName(..) => Yes, + RustcTestMarker(..) => No, + RustcThenThisWouldNeed(..) => No, + RustcTrivialFieldReads => Yes, + RustcUnsafeSpecializationMarker(..) => No, RustcVariance => No, RustcVarianceOfOpaques => No, Sanitize { .. } => No, ShouldPanic { .. } => No, - SkipDuringMethodDispatch { .. } => No, - SpecializationTrait(..) => No, Stability { .. } => Yes, - StdInternalSymbol(..) => No, TargetFeature { .. } => No, + TestRunner(..) => Yes, ThreadLocal => No, TrackCaller(..) => Yes, - TypeConst(..) => Yes, TypeLengthLimit { .. } => No, - UnsafeSpecializationMarker(..) => No, UnstableFeatureBound(..) => No, Used { .. } => No, WindowsSubsystem(..) => No, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index c2ad644688fc..8fce52901015 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -1,11 +1,13 @@ use std::num::NonZero; use std::ops::Deref; +use std::path::PathBuf; use rustc_abi::Align; +use rustc_ast::ast::{Path, join_path_idents}; use rustc_ast::attr::data_structures::CfgEntry; use rustc_ast::attr::version::RustcVersion; use rustc_ast::token::{CommentKind, DocFragmentKind}; -use rustc_ast::{AttrStyle, IntTy, UintTy}; +use rustc_ast::{AttrId, AttrStyle, IntTy, UintTy}; use rustc_ast_pretty::pp::Printer; use rustc_data_structures::fx::FxIndexMap; use rustc_span::def_id::DefId; @@ -96,6 +98,24 @@ impl PrintAttribute for FxIndexMap { p.word("]"); } } +impl PrintAttribute for PathBuf { + fn should_render(&self) -> bool { + true + } + + fn print_attribute(&self, p: &mut Printer) { + p.word(self.display().to_string()); + } +} +impl PrintAttribute for Path { + fn should_render(&self) -> bool { + true + } + + fn print_attribute(&self, p: &mut Printer) { + p.word(join_path_idents(self.segments.iter().map(|seg| seg.ident))); + } +} macro_rules! print_skip { ($($t: ty),* $(,)?) => {$( @@ -170,7 +190,7 @@ macro_rules! print_tup { } print_tup!(A B C D E F G H); -print_skip!(Span, (), ErrorGuaranteed); +print_skip!(Span, (), ErrorGuaranteed, AttrId); print_disp!(u8, u16, u128, usize, bool, NonZero, Limit); print_debug!( Symbol, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index e93deaa84944..dd2cd4939432 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -990,7 +990,7 @@ pub enum LifetimeRes { /// `'static` lifetime. Static, /// Resolution failure. - Error, + Error(rustc_span::ErrorGuaranteed), /// HACK: This is used to recover the NodeId of an elided lifetime. ElidedAnchor { start: NodeId, end: NodeId }, } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4..f1f7350c1e79 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::Not; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -237,7 +238,7 @@ pub enum LifetimeKind { /// Indicates an error during lowering (usually `'_` in wrong place) /// that was already reported. - Error, + Error(ErrorGuaranteed), /// User wrote an anonymous lifetime, either `'_` or nothing (which gets /// converted to `'_`). The semantics of this lifetime should be inferred @@ -257,7 +258,7 @@ impl LifetimeKind { // -- but this is because, as far as the code in the compiler is // concerned -- `Fresh` variants act equivalently to "some fresh name". // They correspond to early-bound regions on an impl, in other words. - LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false, + LifetimeKind::Error(..) | LifetimeKind::Param(..) | LifetimeKind::Static => false, } } } @@ -520,7 +521,10 @@ pub enum ConstArgKind<'hir, Unambig = ()> { /// This variant is not always used to represent inference consts, sometimes /// [`GenericArg::Infer`] is used instead. Infer(Unambig), - Literal(LitKind), + Literal { + lit: LitKind, + negated: bool, + }, } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -1012,10 +1016,14 @@ impl<'hir> Generics<'hir> { span_for_parentheses.map_or_else( || { - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. + // We include bounds that come from a `#[derive(_)]` but point at the user's + // code, as we use this method to get a span appropriate for suggestions. let bs = bound.span(); - bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None)) + // We use `from_expansion` instead of `can_be_used_for_suggestions` because + // the trait bound from imperfect derives do point at the type parameter, + // but expanded to a where clause, so we want to ignore those. This is only + // true for derive intrinsics. + bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None)) }, |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))), ) @@ -1953,8 +1961,6 @@ pub struct PatExpr<'hir> { pub enum PatExprKind<'hir> { Lit { lit: Lit, - // FIXME: move this into `Lit` and handle negated literal expressions - // once instead of matching on unop neg expressions everywhere. negated: bool, }, /// A path pattern for a unit struct/variant or a (maybe-associated) constant. @@ -3193,7 +3199,7 @@ impl<'hir> TraitItem<'hir> { expect_methods_self_kind! { expect_const, (&'hir Ty<'hir>, Option>), - TraitItemKind::Const(ty, rhs), (ty, *rhs); + TraitItemKind::Const(ty, rhs, _), (ty, *rhs); expect_fn, (&FnSig<'hir>, &TraitFn<'hir>), TraitItemKind::Fn(ty, trfn), (ty, trfn); @@ -3213,11 +3219,32 @@ pub enum TraitFn<'hir> { Provided(BodyId), } +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub enum IsTypeConst { + No, + Yes, +} + +impl From for IsTypeConst { + fn from(value: bool) -> Self { + if value { Self::Yes } else { Self::No } + } +} + +impl From for bool { + fn from(value: IsTypeConst) -> Self { + matches!(value, IsTypeConst::Yes) + } +} + /// Represents a trait method or associated constant or type #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TraitItemKind<'hir> { + // FIXME(mgca) eventually want to move the option that is around `ConstItemRhs<'hir>` + // into `ConstItemRhs`, much like `ast::ConstItemRhsKind`, but for now mark whether + // this node is a TypeConst with a flag. /// An associated constant with an optional value (otherwise `impl`s must contain a value). - Const(&'hir Ty<'hir>, Option>), + Const(&'hir Ty<'hir>, Option>, IsTypeConst), /// An associated function with an optional body. Fn(FnSig<'hir>, TraitFn<'hir>), /// An associated type with (possibly empty) bounds and optional concrete @@ -4680,7 +4707,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Provided(body)) - | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))), + | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _), .. }) | OwnerNode::ImplItem(ImplItem { @@ -4907,7 +4934,7 @@ impl<'hir> Node<'hir> { _ => None, }, Node::TraitItem(it) => match it.kind { - TraitItemKind::Const(ty, _) => Some(ty), + TraitItemKind::Const(ty, _, _) => Some(ty), TraitItemKind::Type(_, ty) => ty, _ => None, }, @@ -4950,7 +4977,7 @@ impl<'hir> Node<'hir> { | Node::TraitItem(TraitItem { owner_id, kind: - TraitItemKind::Const(.., Some(ConstItemRhs::Body(body))) + TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _) | TraitItemKind::Fn(_, TraitFn::Provided(body)), .. }) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index d1b75325af26..21bcf53b5619 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1110,7 +1110,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), ConstArgKind::Error(_) => V::Result::output(), // errors and spans are not important - ConstArgKind::Literal(..) => V::Result::output(), // FIXME(mcga) + ConstArgKind::Literal { .. } => V::Result::output(), // FIXME(mcga) } } @@ -1271,7 +1271,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_defaultness(&defaultness)); try_visit!(visitor.visit_id(hir_id)); match *kind { - TraitItemKind::Const(ref ty, default) => { + TraitItemKind::Const(ref ty, default, _) => { try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_const_item_rhs, default); } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 557f76208bfe..0325fd2ceab9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -7,12 +7,12 @@ //! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. //! * Functions called by the compiler itself. -use rustc_ast::attr::AttributeExt; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_macros::{BlobDecodable, Encodable, HashStable_Generic}; -use rustc_span::{Span, Symbol, kw, sym}; +use rustc_macros::{BlobDecodable, Encodable, HashStable_Generic, PrintAttribute}; +use rustc_span::{Symbol, kw, sym}; +use crate::attrs::PrintAttribute; use crate::def_id::DefId; use crate::{MethodKind, Target}; @@ -75,7 +75,7 @@ macro_rules! language_item_table { $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )* ) => { /// A representation of all the valid lang items in Rust. - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, BlobDecodable)] + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, BlobDecodable, PrintAttribute)] pub enum LangItem { $( #[doc = concat!("The `", stringify!($name), "` lang item.")] @@ -150,18 +150,6 @@ impl HashStable for LangItem { } } -/// Extracts the first `lang = "$name"` out of a list of attributes. -/// The `#[panic_handler]` attribute is also extracted out when found. -pub fn extract(attrs: &[impl AttributeExt]) -> Option<(Symbol, Span)> { - attrs.iter().find_map(|attr| { - Some(match attr { - _ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span()), - _ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span()), - _ => return None, - }) - }) -} - language_item_table! { // Variant name, Name, Getter method name, Target Generic requirements; Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 16e8bac3d8a4..a3f4415ec343 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -11,9 +11,7 @@ use crate::lints::DelayedLints; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext { - fn hash_attr_id(&mut self, id: &HashIgnoredAttrId, hasher: &mut StableHasher); -} +pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {} impl ToStableHashKey for BodyId { type KeyType = (DefPathHash, ItemLocalId); @@ -104,7 +102,7 @@ impl HashStable for Crate<'_> { } impl HashStable for HashIgnoredAttrId { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_attr_id(self, hasher) + fn hash_stable(&self, _hcx: &mut HirCtx, _hasher: &mut StableHasher) { + /* we don't hash HashIgnoredAttrId, we ignore them */ } } diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 8d114862b3fe..0ce93561ddd4 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -16,7 +16,6 @@ rustc_ast = { path = "../rustc_ast" } 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_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl deleted file mode 100644 index d9f8eba65c4a..000000000000 --- a/compiler/rustc_hir_analysis/messages.ftl +++ /dev/null @@ -1,601 +0,0 @@ -hir_analysis_abi_custom_clothed_function = - items with the "custom" ABI can only be declared externally or defined via naked functions - .suggestion = convert this to an `#[unsafe(naked)]` function - -hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}` - .label = ambiguous associated {$assoc_kind} `{$assoc_ident}` - -hir_analysis_ambiguous_lifetime_bound = - ambiguous lifetime bound, explicit lifetime bound required - -hir_analysis_assoc_item_constraints_not_allowed_here = - associated item constraints are not allowed here - .label = associated item constraint not allowed here - -hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private - .label = private {$kind} - .defined_here_label = the {$kind} is defined here - -hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_ident}` not found for `{$qself}` - -hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> - [true] an - *[false] a similarly named - } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` -hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_ident}` not found -hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind} -hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg = - consider fully qualifying{$identically_named -> - [true] {""} - *[false] {" "}and renaming - } the associated {$assoc_kind} -hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg = change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}` -hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg = ...and changing the associated {$assoc_kind} name -hir_analysis_assoc_item_not_found_similar_sugg = there is an associated {$assoc_kind} with a similar name - -hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} - .label = unexpected {$got} - .expected_because_label = expected a {$expected} because of this associated {$expected} - .note = the associated {$assoc_kind} is defined here - .bound_on_assoc_const_label = bounds are not allowed on associated constants - -hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here - -hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$what} of a trait with uninferred generic parameters - .suggestion = use a fully qualified path with inferred lifetimes - -hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes - -hir_analysis_async_drop_without_sync_drop = `AsyncDrop` impl without `Drop` impl - .help = type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds - -hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` - .label = deref recursion limit reached - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) - -hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found} - -hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet - -hir_analysis_cannot_capture_late_bound_const = - cannot capture late-bound const parameter in {$what} - .label = parameter defined here - -hir_analysis_cannot_capture_late_bound_lifetime = - cannot capture late-bound lifetime in {$what} - .label = lifetime defined here - -hir_analysis_cannot_capture_late_bound_ty = - cannot capture late-bound type parameter in {$what} - .label = parameter defined here - -hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present - .label = `for<...>` is here - -hir_analysis_cmse_generic = - generics are not allowed in `extern {$abi}` signatures - -hir_analysis_cmse_impl_trait = - `impl Trait` is not allowed in `extern {$abi}` signatures - -hir_analysis_cmse_inputs_stack_spill = - arguments for `{$abi}` function too large to pass via registers - .label = does not fit in the available registers - .note = functions with the `{$abi}` ABI must pass all their arguments via the 4 32-bit argument registers - -hir_analysis_cmse_output_stack_spill = - return value of `{$abi}` function too large to pass via registers - .label = this type doesn't fit in the available registers - .note1 = functions with the `{$abi}` ABI must pass their result via the available return registers - .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size - -hir_analysis_coerce_multi = implementing `{$trait_name}` does not allow multiple fields to be coerced - .note = the trait `{$trait_name}` may only be implemented when a single field is being coerced - .label = these fields must be coerced for `{$trait_name}` to be valid - -hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field - -hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden - -hir_analysis_coerce_pointee_not_concrete_ty = `derive(CoercePointee)` is only applicable to `struct` - -hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}` - -hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout - -hir_analysis_coerce_same_pat_kind = only pattern types with the same pattern can be coerced between each other - -hir_analysis_coerce_unsized_field_validity = for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}` - .label = `{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized - -hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures - -hir_analysis_coerce_zero = implementing `{$trait_name}` requires a field to be coerced - -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 = `{$modifier}` can only be applied to `const` traits - .label = can't be applied to `{$trait_name}` - .note = `{$trait_name}` can't be used with `{$modifier}` because it isn't `const` - .suggestion = {$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations - -hir_analysis_const_impl_for_non_const_trait = const `impl` for trait `{$trait_name}` which is not `const` - .label = this trait is not `const` - .suggestion = {$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations - .note = marking a trait with `const` ensures all default method bodies are `const` - .adding = adding a non-const method body in the future would be a breaking change - -hir_analysis_const_param_ty_impl_on_non_adt = - the trait `ConstParamTy` may not be implemented for this type - .label = type is not a structure or enumeration - -hir_analysis_const_param_ty_impl_on_unsized = - the trait `ConstParamTy` may not be implemented for this type - .label = type is not `Sized` - -hir_analysis_copy_impl_on_non_adt = - the trait `Copy` cannot be implemented for this type - .label = type is not a structure or enumeration - -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_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` - .label = can't implement cross-crate trait with a default impl for non-struct/enum type - -hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate - .label = can't implement cross-crate trait for type in another crate - -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 that don't mention type/const generics, 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 = - the `{$trait_}` trait may only be implemented for local structs, enums, and unions - .label = must be a struct, enum, or union in the current crate - -hir_analysis_drop_impl_reservation = reservation `Drop` impls are not supported - -hir_analysis_duplicate_precise_capture = cannot capture parameter `{$name}` twice - .label = parameter captured again here - -hir_analysis_dyn_trait_assoc_item_binding_mentions_self = - {$kind} binding in trait object type mentions `Self` - .label = contains a mention of `Self` - .binding_label = this binding mentions `Self` - -hir_analysis_eii_with_generics = - `{$impl_name}` cannot have generic parameters other than lifetimes - .label = required by this attribute - .help = `#[{$eii_name}]` marks the implementation of an "externally implementable item" - -hir_analysis_empty_specialization = specialization impl does not specialize any associated items - .note = impl is a specialization of this impl - -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_escaping_bound_var_in_ty_of_assoc_const_binding = - the type of the associated constant `{$assoc_const}` cannot capture late-bound generic parameters - .label = its type cannot capture the late-bound {$var_def_kind} `{$var_name}` - .var_defined_here_label = the late-bound {$var_def_kind} `{$var_name}` is defined here - -hir_analysis_field_already_declared = - field `{$field_name}` is already declared - .label = field already declared - .previous_decl_label = `{$field_name}` first declared here - -hir_analysis_field_already_declared_both_nested = - field `{$field_name}` is already declared - .label = field `{$field_name}` declared in this unnamed field - .nested_field_decl_note = field `{$field_name}` declared here - .previous_decl_label = `{$field_name}` first declared here in this unnamed field - .previous_nested_field_decl_note = field `{$field_name}` first declared here - -hir_analysis_field_already_declared_current_nested = - field `{$field_name}` is already declared - .label = field `{$field_name}` declared in this unnamed field - .nested_field_decl_note = field `{$field_name}` declared here - .previous_decl_label = `{$field_name}` first declared here - -hir_analysis_field_already_declared_nested_help = - fields from the type of this unnamed field are considered fields of the outer type - -hir_analysis_field_already_declared_previous_nested = - field `{$field_name}` is already declared - .label = field already declared - .previous_decl_label = `{$field_name}` first declared here in this unnamed field - .previous_nested_field_decl_note = field `{$field_name}` first declared here - -hir_analysis_generic_args_on_overridden_impl = could not resolve generic parameters on overridden impl - -hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default` - .label = cannot specialize default item `{$ident}` - .ok_label = parent `impl` is here - .note = to specialize, `{$ident}` in the parent `impl` must be marked `default` - -hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default` - .note = parent implementation is in crate `{$cname}` - -hir_analysis_inherent_dyn = cannot define inherent `impl` for a dyn auto trait - .label = impl requires at least one non-auto trait - .note = define and implement a new trait or type instead - -hir_analysis_inherent_nominal = no nominal type found for inherent implementation - .label = impl requires a nominal type - .note = either implement a trait on it or create a newtype to wrap it instead -hir_analysis_inherent_primitive_ty = cannot define inherent `impl` for primitive types - .help = consider using an extension trait instead - -hir_analysis_inherent_primitive_ty_note = you could also try moving the reference to uses of `{$subty}` (such as `self`) within the implementation - -hir_analysis_inherent_ty_outside = cannot define inherent `impl` for a type outside of the crate where the type is defined - .help = consider moving this inherent impl into the crate defining the type if possible - .span_help = alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items - -hir_analysis_inherent_ty_outside_new = cannot define inherent `impl` for a type outside of the crate where the type is defined - .label = impl for type defined outside of crate - .note = define and implement a trait or new type instead - -hir_analysis_inherent_ty_outside_primitive = cannot define inherent `impl` for primitive types outside of `core` - .help = consider moving this inherent impl into `core` if possible - .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items - -hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a type outside of the crate where the type is defined - .help = consider moving this inherent impl into the crate defining the type if possible - .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items - -hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}` - .note = type of `self` must not be a method generic parameter type - -hir_analysis_invalid_generic_receiver_ty_help = - use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - -hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}` - .note = type of `self` must be `Self` or some type implementing `Receiver` - -hir_analysis_invalid_receiver_ty_help = - consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` - -hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types = - consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - -hir_analysis_invalid_receiver_ty_help_nonnull_note = - `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` - -hir_analysis_invalid_receiver_ty_help_weak_note = - `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver` - -hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}` - .note = type of `self` must be `Self` or a type that dereferences to it - -hir_analysis_invalid_union_field = - field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union - .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` - -hir_analysis_invalid_union_field_sugg = - wrap the field type in `ManuallyDrop<...>` - -hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl - .label = const parameter declared here - -hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl - .label = lifetime declared here - -hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl - .label = type parameter declared here - -hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - .param_label = all lifetime parameters originating from a trait are captured implicitly - -hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters - .label = move the lifetime before this parameter - -hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - .label = lifetime captured due to being mentioned in the bounds of the `impl Trait` - .param_label = this lifetime parameter is captured - -hir_analysis_lifetimes_or_bounds_mismatch_on_eii = - lifetime parameters or bounds of `{$ident}` do not match the declaration - .label = lifetimes do not match - .generics_label = lifetimes in impl do not match this signature - .where_label = this `where` clause might not match the one in the declaration - .bounds_label = this bound might be missing in the implementation - -hir_analysis_lifetimes_or_bounds_mismatch_on_trait = - lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration - .label = lifetimes do not match {$item_kind} in trait - .generics_label = lifetimes in impl do not match this {$item_kind} in trait - .where_label = this `where` clause might not match the one in the trait - .bounds_label = this bound might be missing in the impl - -hir_analysis_linkage_type = - invalid type for variable with `#[linkage]` attribute - -hir_analysis_main_function_async = `main` function is not allowed to be `async` - .label = `main` function is not allowed to be `async` - -hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters - .label = `main` cannot have generic parameters - -hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters - -hir_analysis_manual_implementation = - manual implementations of `{$trait_name}` are experimental - .label = manual implementations of `{$trait_name}` are experimental - .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable - -hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous - .note = this method is `async` so it expects a future to be returned - -hir_analysis_missing_generic_params = - the {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } {$parameters} must be explicitly specified - .label = {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } {$parameters} must be specified for this - .suggestion = explicitly specify the {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } - .no_suggestion_label = missing {$parameterCount -> - [one] reference - *[other] references - } to {$parameters} - .note = because the parameter {$parameterCount -> - [one] default references - *[other] defaults reference - } `Self`, the {$parameterCount -> - [one] parameter - *[other] parameters - } must be specified on the trait object type - -hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` - .label = missing one of `{$missing_items_msg}` in implementation - .note = required because of this annotation - -hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}` - .label = missing `{$missing_items_msg}` in implementation - -hir_analysis_missing_trait_item_label = `{$item}` from trait - -hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}` - -hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` - .note = default implementation of `{$missing_item_name}` is unstable - .some_note = use of unstable library feature `{$feature}`: {$reason} - .none_note = use of unstable library feature `{$feature}` - -hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}` - -hir_analysis_not_supported_delegation = {$descr} - .label = callee defined here - -hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate - -hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types - -hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait - -hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign - -hir_analysis_only_current_traits_note = define and implement a trait or new type instead - -hir_analysis_only_current_traits_note_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules - -hir_analysis_only_current_traits_note_uncovered = impl doesn't have any local type before any uncovered type parameters - -hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate - -hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate - -hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign - -hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type - -hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types - -hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate - -hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place} - .label = `impl Trait` implicitly captures all lifetimes in scope - .note = lifetime declared here - -hir_analysis_param_in_ty_of_assoc_const_binding = - the type of the associated constant `{$assoc_const}` must not depend on {$param_category -> - [self] `Self` - [synthetic] `impl Trait` - *[normal] generic parameters - } - .label = its type must not depend on {$param_category -> - [self] `Self` - [synthetic] `impl Trait` - *[normal] the {$param_def_kind} `{$param_name}` - } - .param_defined_here_label = {$param_category -> - [synthetic] the `impl Trait` is specified here - *[normal] the {$param_def_kind} `{$param_name}` is defined here - } - -hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope in `use<...>` - .label = {$kind} parameter is implicitly captured by this `impl Trait` - .note = currently, all {$kind} parameters are required to be mentioned in the precise captures list - -hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation - .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it - -hir_analysis_parenthesized_fn_trait_expansion = - parenthesized trait syntax expands to `{$expanded_type}` - -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_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias - .label = `Self` is not a generic argument, but an alias to the type of the {$what} - -hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively - .label = {$param_def_kind} must be used non-recursively in the definition - .note = all type parameters must be used in a non-recursive way in order to constrain their variance - -hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` - .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` - -hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` - -hir_analysis_return_type_notation_equality_bound = - return type notation is not allowed to use type equality - -hir_analysis_return_type_notation_illegal_param_const = - return type notation is not allowed for functions that have const parameters - .label = const parameter declared here -hir_analysis_return_type_notation_illegal_param_type = - return type notation is not allowed for functions that have type parameters - .label = type parameter declared here - -hir_analysis_return_type_notation_on_non_rpitit = - return type notation used on function that is not `async` and does not return `impl Trait` - .note = function returns `{$ty}`, which is not compatible with associated type return bounds - .label = this function must be `async` or return `impl Trait` - -hir_analysis_rpitit_refined = impl trait in impl method signature does not match trait method signature - .suggestion = replace the return type so that it matches the trait - .label = return type from trait method defined here - .unmatched_bound_label = this bound is stronger than that defined on the trait - .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - .feedback_note = we are soliciting feedback, see issue #121718 for more information - -hir_analysis_rpitit_refined_lifetimes = impl trait in impl method captures fewer lifetimes than in trait - .suggestion = modify the `use<..>` bound to capture the same lifetimes that the trait does - .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - .feedback_note = we are soliciting feedback, see issue #121718 for more information - -hir_analysis_self_in_impl_self = - `Self` is not valid in the self type of an impl block - .note = replace `Self` with a different type - -hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>` - .label = `Self` type parameter is implicitly captured by this `impl Trait` - .note = currently, all type parameters are required to be mentioned in the precise captures list - -hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code - .help = add `#![feature(simd_ffi)]` to the crate attributes to enable - -hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable - .help = add `#![feature(min_specialization)]` to the crate attributes to enable - -hir_analysis_static_specialize = cannot specialize on `'static` lifetime - -hir_analysis_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits} - -hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item - -hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait - -hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` - -hir_analysis_too_large_static = extern static is too large for the target architecture - -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 - -hir_analysis_traits_with_default_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` - .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds - -hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} - .label = needs exactly one variant, but has {$number} - .many_label = too many variants in `{$path}` - .multi_label = variant here - -hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count} - .label = needs at most one field with non-trivial size or alignment, but has {$field_count} - .labels = this field has non-zero size or requires alignment - -hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count} - .label = needs at most one field with non-trivial size or alignment, but has {$field_count} - .labels = this field has non-zero size or requires alignment - -hir_analysis_ty_of_assoc_const_binding_note = `{$assoc_const}` has type `{$ty}` - -hir_analysis_ty_param_first_local = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) - .label = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) - .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -hir_analysis_ty_param_some = type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`) - .label = type parameter `{$param}` must be used as the type parameter for some local type - .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local - .only_note = only traits defined in the current crate can be implemented for a type parameter - -hir_analysis_type_of = {$ty} - -hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates - .label = unconstrained {$param_def_kind} - .const_param_note = expressions using a const parameter must map each value to a distinct output value - .const_param_note2 = proving the result of expressions other than the parameter are unique is not supported - -hir_analysis_unconstrained_opaque_type = unconstrained opaque type - .note = `{$name}` must be used in combination with a concrete type within the same {$what} - -hir_analysis_unrecognized_intrinsic_function = - unrecognized intrinsic function: `{$name}` - .label = unrecognized intrinsic - .help = if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -hir_analysis_unused_associated_type_bounds = - unnecessary associated type bound for dyn-incompatible associated type - .note = this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` - .suggestion = remove this bound - -hir_analysis_unused_generic_parameter = - {$param_def_kind} `{$param_name}` is never used - .label = unused {$param_def_kind} - .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead - .usage_spans = `{$param_name}` is named here, but is likely unused in the containing type - -hir_analysis_unused_generic_parameter_adt_help = - consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` -hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = - consider removing `{$param_name}` or referring to it in a field -hir_analysis_unused_generic_parameter_ty_alias_help = - consider removing `{$param_name}` or referring to it in the body of the type alias - -hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type - -hir_analysis_value_of_associated_struct_already_specified = - the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified - .label = re-bound here - .previous_bound_label = `{$item_name}` bound here first - -hir_analysis_variadic_function_compatible_convention = C-variadic functions with the {$convention} calling convention are not supported - .label = C-variadic function must have a compatible calling convention - -hir_analysis_variances_of = {$variances} - -hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause - .label = `main` cannot have a `where` clause - -hir_analysis_within_macro = due to this macro variable - -hir_analysis_wrong_number_of_generic_arguments_to_intrinsic = - intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected} - .label = expected {$expected} {$descr} {$expected -> - [one] parameter - *[other] parameters - } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f2b06e1cde71..1bee7a72229a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ); check_where_clauses(wfcx, def_id); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id) { wfcheck::check_type_const(wfcx, def_id, ty, true)?; } Ok(()) @@ -1701,7 +1701,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Array(ty, _) => check_unsuited(tcx, typing_env, *ty), ty::Adt(def, args) => { if !def.did().is_local() - && !find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::PubTransparent(_)) + && !find_attr!( + tcx.get_all_attrs(def.did()), + AttributeKind::RustcPubTransparent(_) + ) { let non_exhaustive = def.is_variant_list_non_exhaustive() || def.variants().iter().any(ty::VariantDef::is_field_list_non_exhaustive); 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 4534cfcf962e..c29ebe67a158 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,10 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -218,7 +217,7 @@ fn compare_method_predicate_entailment<'tcx>( trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate), ); - let is_conditionally_const = tcx.is_conditionally_const(impl_def_id); + let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id); if is_conditionally_const { // Augment the hybrid param-env with the const conditions // of the impl header and the trait method. @@ -592,7 +591,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ty, Ty::new_placeholder( tcx, - ty::Placeholder::new( + ty::PlaceholderType::new( universe, ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon }, ), @@ -1845,7 +1844,7 @@ fn compare_synthetic_generics<'tcx>( // The case where the impl method uses `impl Trait` but the trait method uses // explicit generics err.span_label(impl_span, "expected generic parameter, found `impl Trait`"); - let _: Option<_> = try { + try { // try taking the name from the trait impl // FIXME: this is obviously suboptimal since the name can already be used // as another generic argument @@ -1882,7 +1881,7 @@ fn compare_synthetic_generics<'tcx>( // The case where the trait method uses `impl Trait`, but the impl method uses // explicit generics. err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); - let _: Option<_> = try { + try { let impl_m = impl_m.def_id.as_local()?; let impl_m = tcx.hir_expect_impl_item(impl_m); let (sig, _) = impl_m.expect_fn(); @@ -2051,12 +2050,8 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = - find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_)); - let trait_type_const_span = find_attr!( - tcx.get_all_attrs(trait_const_item.def_id), - AttributeKind::TypeConst(sp) => *sp - ); + let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); + let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); if let Some(trait_type_const_span) = trait_type_const_span && !impl_is_type_const @@ -2065,14 +2060,14 @@ fn compare_type_const<'tcx>( .dcx() .struct_span_err( tcx.def_span(impl_const_item.def_id), - "implementation of `#[type_const]` const must be marked with `#[type_const]`", + "implementation of a `type const` must also be marked as `type const`", ) .with_span_note( MultiSpan::from_spans(vec![ tcx.def_span(trait_const_item.def_id), trait_type_const_span, ]), - "trait declaration of const is marked with `#[type_const]`", + "trait declaration of const is marked as `type const`", ) .emit()); } @@ -2551,7 +2546,7 @@ fn param_env_with_gat_bounds<'tcx>( } }; - let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = + let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind<'tcx>; 8]> = smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len()); // Extend the impl's identity args with late-bound GAT vars let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id) @@ -2587,7 +2582,7 @@ fn param_env_with_gat_bounds<'tcx>( ty::Const::new_bound( tcx, ty::INNERMOST, - ty::BoundConst { var: ty::BoundVar::from_usize(bound_vars.len() - 1) }, + ty::BoundConst::new(ty::BoundVar::from_usize(bound_vars.len() - 1)), ) .into() } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 22ee490b81a7..6946d1a70040 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -82,6 +82,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::bswap | sym::caller_location | sym::carrying_mul_add + | sym::carryless_mul | sym::ceilf16 | sym::ceilf32 | sym::ceilf64 @@ -564,6 +565,7 @@ pub(crate) fn check_intrinsic_type( (1, 0, vec![param(0), param(0)], param(0)) } sym::saturating_add | sym::saturating_sub => (1, 0, vec![param(0), param(0)], param(0)), + sym::carryless_mul => (1, 0, vec![param(0), param(0)], param(0)), sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { (1, 0, vec![param(0), param(0)], param(0)) } @@ -711,7 +713,8 @@ pub(crate) fn check_intrinsic_type( | sym::simd_fmin | sym::simd_fmax | sym::simd_saturating_add - | sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)), + | sym::simd_saturating_sub + | sym::simd_carryless_mul => (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 diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8b50eceb26e4..b1daf2f2be9c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -5,7 +5,7 @@ use hir::intravisit::{self, Visitor}; use rustc_abi::{ExternAbi, ScalableElt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_errors::{Applicability, ErrorGuaranteed, msg, pluralize, struct_span_code_err}; use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -42,8 +42,8 @@ use {rustc_ast as ast, rustc_hir as hir}; use super::compare_eii::compare_eii_function_types; use crate::autoderef::Autoderef; use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params}; +use crate::errors; use crate::errors::InvalidReceiverTyHint; -use crate::{errors, fluent_generated as fluent}; pub(super) struct WfCheckingCtxt<'a, 'tcx> { pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>, @@ -953,7 +953,7 @@ pub(crate) fn check_associated_item( wfcx.register_wf_obligation(span, loc, ty.into()); let has_value = item.defaultness(tcx).has_value(); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id) { check_type_const(wfcx, def_id, ty, has_value)?; } @@ -1567,11 +1567,40 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: let predicates = predicates.instantiate_identity(tcx); + let assoc_const_obligations: Vec<_> = predicates + .predicates + .iter() + .copied() + .zip(predicates.spans.iter().copied()) + .filter_map(|(clause, sp)| { + let proj = clause.as_projection_clause()?; + let pred_binder = proj + .map_bound(|pred| { + pred.term.as_const().map(|ct| { + let assoc_const_ty = tcx + .type_of(pred.projection_term.def_id) + .instantiate(tcx, pred.projection_term.args); + ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty) + }) + }) + .transpose(); + pred_binder.map(|pred_binder| { + let cause = traits::ObligationCause::new( + sp, + wfcx.body_def_id, + ObligationCauseCode::WhereClause(def_id.to_def_id(), sp), + ); + Obligation::new(tcx, cause, wfcx.param_env, pred_binder) + }) + }) + .collect(); + assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| { traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp) }); - let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); + let obligations: Vec<_> = + wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect(); wfcx.register_obligations(obligations); } @@ -1740,7 +1769,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types` feature", ), ) - .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) .emit() } None | Some(ArbitrarySelfTypesLevel::Basic) @@ -1764,7 +1793,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types_pointers` feature", ), ) - .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) .emit() } _ => @@ -2442,8 +2471,8 @@ fn lint_redundant_lifetimes<'tcx>( } #[derive(LintDiagnostic)] -#[diag(hir_analysis_redundant_lifetime_args)] -#[note] +#[diag("unnecessary lifetime parameter `{$victim}`")] +#[note("you can use the `{$candidate}` lifetime directly, in place of `{$victim}`")] struct RedundantLifetimeArgsLint<'tcx> { /// The lifetime we have found to be redundant. victim: ty::Region<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f3..466dc262764c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -38,6 +38,7 @@ pub(super) fn check_trait<'tcx>( checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?; checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?; checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?; + checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?; checker.check(lang_items.const_param_ty_trait(), |checker| { visit_implementation_of_const_param_ty(checker) })?; @@ -121,9 +122,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } - Err(CopyImplementationError::HasDestructor) => { + Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; - Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) + let impl_ = tcx.def_span(did); + Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; @@ -134,6 +136,41 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran } } +fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let impl_header = checker.impl_header; + let impl_did = checker.impl_def_id; + debug!("visit_implementation_of_unpin: impl_did={:?}", impl_did); + + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); + debug!("visit_implementation_of_unpin: self_type={:?}", self_type); + + let span = tcx.def_span(impl_did); + + if tcx.features().pin_ergonomics() { + match self_type.kind() { + // Soundness concerns: a type `T` annotated with `#[pin_v2]` is allowed to project + // `Pin<&mut T>` to its field `Pin<&mut U>` safely (even if `U: !Unpin`). + // If `T` is allowed to impl `Unpin` manually (note that `Unpin` is a safe trait, + // which cannot carry safety properties), then `&mut U` could be obtained from + // `&mut T` that dereferenced by `Pin<&mut T>`, which breaks the safety contract of + // `Pin<&mut U>` for `U: !Unpin`. + ty::Adt(adt, _) if adt.is_pin_project() => { + return Err(tcx.dcx().emit_err(crate::errors::ImplUnpinForPinProjectedType { + span, + adt_span: tcx.def_span(adt.did()), + adt_name: tcx.item_name(adt.did()), + })); + } + ty::Adt(_, _) => {} + _ => { + return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type")); + } + }; + } + Ok(()) +} + fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; let header = checker.impl_header; diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index fe47f3258846..588747f46d17 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -91,7 +91,7 @@ impl<'tcx> InherentCollect<'tcx> { for &impl_item in items { if !find_attr!( self.tcx.get_all_attrs(impl_item), - AttributeKind::AllowIncoherentImpl(_) + AttributeKind::RustcAllowIncoherentImpl(_) ) { let impl_span = self.tcx.def_span(impl_def_id); return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { @@ -110,7 +110,22 @@ impl<'tcx> InherentCollect<'tcx> { Ok(()) } else { let impl_span = self.tcx.def_span(impl_def_id); - Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span })) + let mut err = errors::InherentTyOutsideNew { span: impl_span, note: None }; + + if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) = + self.tcx.hir_node_by_def_id(impl_def_id).expect_item().expect_impl().self_ty.kind + && let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res + { + let ty_name = self.tcx.def_path_str(def_id); + let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string(); + err.note = Some(errors::InherentTyOutsideNewAliasNote { + span: self.tcx.def_span(def_id), + ty_name, + alias_ty_name, + }); + } + + Err(self.tcx.dcx().emit_err(err)) } } @@ -125,7 +140,7 @@ impl<'tcx> InherentCollect<'tcx> { for &impl_item in items { if !find_attr!( self.tcx.get_all_attrs(impl_item), - AttributeKind::AllowIncoherentImpl(_) + AttributeKind::RustcAllowIncoherentImpl(_) ) { let span = self.tcx.def_span(impl_def_id); return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index dd399f9d90de..2fc1f1ab01d2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -16,22 +16,21 @@ use std::cell::Cell; use std::iter; -use std::ops::Bound; +use std::ops::{Bound, ControlFlow}; use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err, -}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey}; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::DefKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; +use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; +use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ @@ -94,6 +93,7 @@ pub(crate) fn provide(providers: &mut Providers) { const_param_default, anon_const_kind, const_of_item, + is_rhs_type_const, ..*providers }; } @@ -316,16 +316,24 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { - if let RegionInferReason::ObjectLifetimeDefault = reason { - let e = struct_span_code_err!( - self.dcx(), - span, - E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" - ) - .emit(); - ty::Region::new_error(self.tcx(), e) + if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason { + // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in + // `*const dyn Trait` and `Fn() -> *const dyn Trait`. + let guar = self + .dcx() + .struct_span_err( + span, + "cannot deduce the lifetime bound for this trait object type from context", + ) + .with_code(E0228) + .with_span_suggestion_verbose( + sugg_sp, + "please supply an explicit bound", + " + /* 'a */", + Applicability::HasPlaceholders, + ) + .emit(); + ty::Region::new_error(self.tcx(), guar) } else { // This indicates an illegal lifetime in a non-assoc-trait position ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature") @@ -889,7 +897,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let attrs = tcx.get_all_attrs(def_id); - let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_)); + let paren_sugar = find_attr!(attrs, AttributeKind::RustcParenSugar(_)); if paren_sugar && !tcx.features().unboxed_closures() { tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span }); } @@ -897,22 +905,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { // Only regular traits can be marker. let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_)); - let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_)); + let rustc_coinductive = find_attr!(attrs, AttributeKind::RustcCoinductive(_)); let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental); let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!( attrs, - AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice] + AttributeKind::RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice] ) .unwrap_or([false; 2]); - let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) { - ty::trait_def::TraitSpecializationKind::Marker - } else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) { - ty::trait_def::TraitSpecializationKind::AlwaysApplicable - } else { - ty::trait_def::TraitSpecializationKind::None - }; + let specialization_kind = + if find_attr!(attrs, AttributeKind::RustcUnsafeSpecializationMarker(_)) { + ty::trait_def::TraitSpecializationKind::Marker + } else if find_attr!(attrs, AttributeKind::RustcSpecializationTrait(_)) { + ty::trait_def::TraitSpecializationKind::AlwaysApplicable + } else { + ty::trait_def::TraitSpecializationKind::None + }; let must_implement_one_of = find_attr!( attrs, @@ -923,9 +932,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { .collect::>() ); - let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_)); + let deny_explicit_impl = find_attr!(attrs, AttributeKind::RustcDenyExplicitImpl(_)); let force_dyn_incompatible = - find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span); + find_attr!(attrs, AttributeKind::RustcDynIncompatibleTrait(span) => *span); ty::TraitDef { def_id: def_id.to_def_id(), @@ -1054,6 +1063,70 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( ) } +/// Convert `ReLateParam`s in `value` back into `ReBound`s and bind it with `bound_vars`. +fn late_param_regions_to_bound<'tcx, T>( + tcx: TyCtxt<'tcx>, + scope: DefId, + bound_vars: &'tcx ty::List>, + value: T, +) -> ty::Binder<'tcx, T> +where + T: ty::TypeFoldable>, +{ + let value = fold_regions(tcx, value, |r, debruijn| match r.kind() { + ty::ReLateParam(lp) => { + // Should be in scope, otherwise inconsistency happens somewhere. + assert_eq!(lp.scope, scope); + + let br = match lp.kind { + // These variants preserve the bound var index. + kind @ (ty::LateParamRegionKind::Anon(idx) + | ty::LateParamRegionKind::NamedAnon(idx, _)) => { + let idx = idx as usize; + let var = ty::BoundVar::from_usize(idx); + + let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied() + else { + bug!("unexpected late-bound region {kind:?} for bound vars {bound_vars:?}"); + }; + + ty::BoundRegion { var, kind } + } + + // For named regions, look up the corresponding bound var. + ty::LateParamRegionKind::Named(def_id) => bound_vars + .iter() + .enumerate() + .find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did)) + if did == def_id => + { + Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind }) + } + _ => None, + }) + .unwrap(), + + ty::LateParamRegionKind::ClosureEnv => bound_vars + .iter() + .enumerate() + .find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => { + Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind }) + } + _ => None, + }) + .unwrap(), + }; + + ty::Region::new_bound(tcx, debruijn, br) + } + _ => r, + }); + + ty::Binder::bind_with_vars(value, bound_vars) +} + fn recover_infer_ret_ty<'tcx>( icx: &ItemCtxt<'tcx>, infer_ret_ty: &'tcx hir::Ty<'tcx>, @@ -1129,13 +1202,22 @@ fn recover_infer_ret_ty<'tcx>( ); } let guar = diag.emit(); - ty::Binder::dummy(tcx.mk_fn_sig( + + // If we return a dummy binder here, we can ICE later in borrowck when it encounters + // `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the + // signature binder. See #135845. + let bound_vars = tcx.late_bound_vars(hir_id); + let scope = def_id.to_def_id(); + + let fn_sig = tcx.mk_fn_sig( fn_sig.inputs().iter().copied(), recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)), fn_sig.c_variadic, fn_sig.safety, fn_sig.abi, - )) + ); + + late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig) } pub fn suggest_impl_trait<'tcx>( @@ -1273,7 +1355,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader .of_trait .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); let selfty = tcx.type_of(def_id).instantiate_identity(); - let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let is_rustc_reservation = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(..)); check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref); @@ -1510,6 +1593,20 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE + } else if tcx.features().opaque_generic_const_args() { + // Only anon consts that are the RHS of a const item can be OGCA. + // Note: We can't just check tcx.parent because it needs to be EXACTLY + // the RHS, not just part of the RHS. + if !is_anon_const_rhs_of_const_item(tcx, def) { + return ty::AnonConstKind::MCG; + } + + let body = tcx.hir_body_owned_by(def); + let mut visitor = OGCAParamVisitor(tcx); + match visitor.visit_body(body) { + ControlFlow::Break(UsesParam) => ty::AnonConstKind::OGCA, + ControlFlow::Continue(()) => ty::AnonConstKind::MCG, + } } else if tcx.features().min_generic_const_args() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { @@ -1527,6 +1624,50 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } } +fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false }; + let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) + | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) + | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _), + .. + })) = grandparent_node + else { + return false; + }; + let hir::ConstItemRhs::TypeConst(hir::ConstArg { + kind: hir::ConstArgKind::Anon(rhs_anon), .. + }) = ct_rhs + else { + return false; + }; + def_id == rhs_anon.def_id +} + +struct OGCAParamVisitor<'tcx>(TyCtxt<'tcx>); + +struct UsesParam; + +impl<'tcx> Visitor<'tcx> for OGCAParamVisitor<'tcx> { + type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow; + + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { + self.0 + } + + fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow { + if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) = + path.res + { + return ControlFlow::Break(UsesParam); + } + + intravisit::walk_path(self, path) + } +} + #[instrument(level = "debug", skip(tcx), ret)] fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, @@ -1535,7 +1676,7 @@ fn const_of_item<'tcx>( let ct_rhs = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct, hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(.., ct), .. + kind: hir::TraitItemKind::Const(_, ct, _), .. }) => ct.expect("no default value for trait assoc const"), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct, _ => { @@ -1565,3 +1706,22 @@ fn const_of_item<'tcx>( ty::EarlyBinder::bind(ct) } } + +/// Check if a Const or AssocConst is a type const (mgca) +fn is_rhs_type_const<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> bool { + match tcx.hir_node_by_def_id(def) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(_, _, _, hir::ConstItemRhs::TypeConst(_)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Const(_, hir::ConstItemRhs::TypeConst(_)), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(_, _, hir::IsTypeConst::Yes), + .. + }) => return true, + _ => return false, + } +} diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 2dfd4ab6111f..bbf912cd4bde 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -7,10 +7,9 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::sym; pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { - if !tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { + if !find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcHiddenTypeOfOpaques) { return; } - for id in tcx.hir_crate_items(()).opaques() { if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 511d513216eb..0723418d8ddf 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -92,6 +92,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... ty::AnonConstKind::MCG => None, + // OGCA anon consts inherit their parent's generics. + ty::AnonConstKind::OGCA => Some(parent_did), // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 7025f7ac84b0..a01ee2d31a3d 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -241,7 +241,7 @@ struct MapAndCompressBoundVars<'tcx> { binder: ty::DebruijnIndex, /// List of bound vars that remain unsubstituted because they were not /// mentioned in the GAT's args. - still_bound_vars: Vec, + still_bound_vars: Vec>, /// Subtle invariant: If the `GenericArg` is bound, then it should be /// stored with the debruijn index of `INNERMOST` so it can be shifted /// correctly during substitution. @@ -330,7 +330,8 @@ impl<'tcx> TypeFolder> for MapAndCompressBoundVars<'tcx> { } else { let var = ty::BoundVar::from_usize(self.still_bound_vars.len()); self.still_bound_vars.push(ty::BoundVariableKind::Const); - let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst { var }); + let mapped = + ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var)); self.mapping.insert(old_bound.var, mapped.into()); mapped }; 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 02443b577d38..ff919bd58ba1 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -63,9 +63,9 @@ impl ResolvedArg { struct BoundVarContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, - rbv: &'a mut ResolveBoundVars, + rbv: &'a mut ResolveBoundVars<'tcx>, disambiguator: &'a mut DisambiguatorState, - scope: ScopeRef<'a>, + scope: ScopeRef<'a, 'tcx>, opaque_capture_errors: RefCell>, } @@ -76,7 +76,7 @@ struct OpaqueHigherRankedLifetimeCaptureErrors { } #[derive(Debug)] -enum Scope<'a> { +enum Scope<'a, 'tcx> { /// Declares lifetimes, and each can be early-bound or late-bound. /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and /// it should be shifted by the number of `Binder`s in between the @@ -94,7 +94,7 @@ enum Scope<'a> { /// to append to. hir_id: HirId, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, /// If this binder comes from a where clause, specify how it was created. /// This is used to diagnose inaccessible lifetimes in APIT: @@ -110,7 +110,7 @@ enum Scope<'a> { /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`. Body { id: hir::BodyId, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Use a specific lifetime (if `Some`) or leave it unset (to be @@ -118,7 +118,7 @@ enum Scope<'a> { /// for the default choice of lifetime in a trait object type. ObjectLifetimeDefault { lifetime: Option, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// When we have nested trait refs, we concatenate late bound vars for inner @@ -126,12 +126,12 @@ enum Scope<'a> { /// lifetimes encountered when identifying the trait that an associated type /// is declared on. Supertrait { - bound_vars: Vec, - s: ScopeRef<'a>, + bound_vars: Vec>, + s: ScopeRef<'a, 'tcx>, }, TraitRefBoundary { - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given: @@ -148,7 +148,7 @@ enum Scope<'a> { /// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`. captures: &'a RefCell>, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Disallows capturing late-bound vars from parent scopes. @@ -157,7 +157,7 @@ enum Scope<'a> { /// since we don't do something more correct like replacing any captured /// late-bound vars with early-bound params in the const's own generics. LateBoundary { - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, what: &'static str, deny_late_regions: bool, }, @@ -167,7 +167,7 @@ enum Scope<'a> { }, } -impl<'a> Scope<'a> { +impl<'a, 'tcx> Scope<'a, 'tcx> { // A helper for debugging scopes without printing parent scopes fn debug_truncated(&self) -> impl fmt::Debug { fmt::from_fn(move |f| match self { @@ -227,7 +227,7 @@ enum BinderScopeType { Concatenating, } -type ScopeRef<'a> = &'a Scope<'a>; +type ScopeRef<'a, 'tcx> = &'a Scope<'a, 'tcx>; /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] pub(crate) fn provide(providers: &mut Providers) { @@ -253,7 +253,7 @@ pub(crate) fn provide(providers: &mut Providers) { /// You should not read the result of this query directly, but rather use /// `named_variable_map`, `late_bound_vars_map`, etc. #[instrument(level = "debug", skip(tcx))] -fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars { +fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars<'_> { let mut rbv = ResolveBoundVars::default(); let mut visitor = BoundVarContext { tcx, @@ -287,7 +287,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou rbv } -fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind { +fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind<'tcx> { let def_id = param.def_id.to_def_id(); match param.kind { GenericParamKind::Lifetime { .. } => { @@ -301,7 +301,9 @@ fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableK /// Turn a [`ty::GenericParamDef`] into a bound arg. Generally, this should only /// be used when turning early-bound vars into late-bound vars when lowering /// return type notation. -fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind { +fn generic_param_def_as_bound_arg<'tcx>( + param: &ty::GenericParamDef, +) -> ty::BoundVariableKind<'tcx> { match param.kind { ty::GenericParamDefKind::Lifetime => { ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id)) @@ -329,7 +331,9 @@ fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. - fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { + fn poly_trait_ref_binder_info( + &mut self, + ) -> (Vec>, BinderScopeType) { let mut scope = self.scope; let mut supertrait_bound_vars = vec![]; loop { @@ -364,7 +368,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated - let mut full_binders = + let mut full_binders: Vec> = self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone(); full_binders.extend(supertrait_bound_vars); break (full_binders, BinderScopeType::Concatenating); @@ -659,7 +663,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { LifetimeKind::Param(def_id) => { self.resolve_lifetime_ref(def_id, lt); } - LifetimeKind::Error => {} + LifetimeKind::Error(..) => {} LifetimeKind::ImplicitObjectLifetimeDefault | LifetimeKind::Infer | LifetimeKind::Static => { @@ -800,7 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // If the user wrote an explicit name, use that. self.visit_lifetime(&*lifetime); } - LifetimeKind::Error => {} + LifetimeKind::Error(..) => {} } } hir::TyKind::Ref(lifetime_ref, ref mt) => { @@ -855,7 +859,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } }) } - Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { + Const(_, _, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { intravisit::walk_trait_item(this, trait_item) }), } @@ -887,8 +891,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::LifetimeKind::Param(param_def_id) => { self.resolve_lifetime_ref(param_def_id, lifetime_ref) } - // If we've already reported an error, just ignore `lifetime_ref`. - hir::LifetimeKind::Error => {} + // Keep track of lifetimes about which errors have already been reported + hir::LifetimeKind::Error(guar) => { + self.insert_lifetime(lifetime_ref, ResolvedArg::Error(guar)) + } // Those will be resolved by typechecking. hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {} } @@ -1094,7 +1100,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL } impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { - fn with(&mut self, wrap_scope: Scope<'_>, f: F) + fn with(&mut self, wrap_scope: Scope<'_, 'tcx>, f: F) where F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>), { @@ -1115,7 +1121,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { *self.opaque_capture_errors.borrow_mut() = this.opaque_capture_errors.into_inner(); } - fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec) { + fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec>) { if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) { bug!( "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", @@ -1691,7 +1697,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | DefKind::Union | DefKind::Enum | DefKind::TyAlias - | DefKind::Trait, + | DefKind::Trait + | DefKind::TraitAlias, def_id, ) if depth == 0 => Some(def_id), _ => None, @@ -1861,7 +1868,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { let bound_vars = if let Some(type_def_id) = type_def_id - && self.tcx.def_kind(type_def_id) == DefKind::Trait + && let DefKind::Trait | DefKind::TraitAlias = self.tcx.def_kind(type_def_id) && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars( self.tcx, type_def_id, @@ -1931,7 +1938,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { def_id: DefId, assoc_ident: Ident, assoc_tag: ty::AssocTag, - ) -> Option<(Vec, &'tcx ty::AssocItem)> { + ) -> Option<(Vec>, &'tcx ty::AssocItem)> { let trait_defines_associated_item_named = |trait_def_id: DefId| { tcx.associated_items(trait_def_id).find_by_ident_and_kind( tcx, @@ -1942,7 +1949,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; use smallvec::{SmallVec, smallvec}; - let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> = + let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind<'tcx>; 8]>); 8]> = smallvec![(def_id, smallvec![])]; let mut visited: FxHashSet = FxHashSet::default(); loop { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 910176a0689c..23df419d06a7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -63,7 +63,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_fn_def(tcx, def_id.to_def_id(), args) } - TraitItemKind::Const(ty, rhs) => rhs + TraitItemKind::Const(ty, rhs, _) => rhs .and_then(|rhs| { ty.is_suggestable_infer_ty().then(|| { infer_placeholder_type( @@ -420,9 +420,9 @@ fn infer_placeholder_type<'tcx>( kind: &'static str, ) -> Ty<'tcx> { let tcx = cx.tcx(); - // If the type is omitted on a #[type_const] we can't run + // If the type is omitted on a `type const` we can't run // type check on since that requires the const have a body - // which type_consts don't. + // which `type const`s don't. let ty = if tcx.is_type_const(def_id.to_def_id()) { if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { tcx.type_of(trait_item_def_id).instantiate_identity() @@ -430,7 +430,7 @@ fn infer_placeholder_type<'tcx>( Ty::new_error_with_message( tcx, ty_span, - "constant with #[type_const] requires an explicit type", + "constant with `type const` requires an explicit type", ) } } else { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2..4b0f1016029e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -4,24 +4,22 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, listify, + MultiSpan, listify, msg, }; use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; use rustc_span::{Ident, Span, Symbol}; - -use crate::fluent_generated as fluent; pub(crate) mod wrong_number_of_generic_args; mod precise_captures; pub(crate) use precise_captures::*; #[derive(Diagnostic)] -#[diag(hir_analysis_ambiguous_assoc_item)] +#[diag("ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}`")] pub(crate) struct AmbiguousAssocItem<'a> { #[primary_span] - #[label] + #[label("ambiguous associated {$assoc_kind} `{$assoc_ident}`")] pub span: Span, pub assoc_kind: &'static str, pub assoc_ident: Ident, @@ -29,29 +27,26 @@ pub(crate) struct AmbiguousAssocItem<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_kind_mismatch)] +#[diag("expected {$expected}, found {$got}")] pub(crate) struct AssocKindMismatch { #[primary_span] - #[label] + #[label("unexpected {$got}")] pub span: Span, pub expected: &'static str, pub got: &'static str, - #[label(hir_analysis_expected_because_label)] + #[label("expected a {$expected} because of this associated {$expected}")] pub expected_because_label: Option, pub assoc_kind: &'static str, - #[note] + #[note("the associated {$assoc_kind} is defined here")] pub def_span: Span, - #[label(hir_analysis_bound_on_assoc_const_label)] + #[label("bounds are not allowed on associated constants")] pub bound_on_assoc_const_label: Option, #[subdiagnostic] pub wrap_in_braces_sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, - applicability = "maybe-incorrect" -)] +#[multipart_suggestion("consider adding braces here", applicability = "maybe-incorrect")] pub(crate) struct AssocKindMismatchWrapInBracesSugg { #[suggestion_part(code = "{{ ")] pub lo: Span, @@ -60,19 +55,19 @@ pub(crate) struct AssocKindMismatchWrapInBracesSugg { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_is_private, code = E0624)] +#[diag("{$kind} `{$name}` is private", code = E0624)] pub(crate) struct AssocItemIsPrivate { #[primary_span] - #[label] + #[label("private {$kind}")] pub span: Span, pub kind: &'static str, pub name: Ident, - #[label(hir_analysis_defined_here_label)] + #[label("the {$kind} is defined here")] pub defined_here_label: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_not_found, code = E0220)] +#[diag("associated {$assoc_kind} `{$assoc_ident}` not found for `{$qself}`", code = E0220)] pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, @@ -83,18 +78,23 @@ pub(crate) struct AssocItemNotFound<'a> { pub label: Option>, #[subdiagnostic] pub sugg: Option>, - #[label(hir_analysis_within_macro)] + #[label("due to this macro variable")] pub within_macro_span: Option, } #[derive(Subdiagnostic)] pub(crate) enum AssocItemNotFoundLabel<'a> { - #[label(hir_analysis_assoc_item_not_found_label)] + #[label("associated {$assoc_kind} `{$assoc_ident}` not found")] NotFound { #[primary_span] span: Span, }, - #[label(hir_analysis_assoc_item_not_found_found_in_other_trait_label)] + #[label( + "there is {$identically_named -> + [true] an + *[false] a similarly named + } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`" + )] FoundInOtherTrait { #[primary_span] span: Span, @@ -109,7 +109,7 @@ pub(crate) enum AssocItemNotFoundLabel<'a> { pub(crate) enum AssocItemNotFoundSugg<'a> { #[suggestion( - hir_analysis_assoc_item_not_found_similar_sugg, + "there is an associated {$assoc_kind} with a similar name", code = "{suggested_name}", applicability = "maybe-incorrect" )] @@ -120,7 +120,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { suggested_name: Symbol, }, #[suggestion( - hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg, + "change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`", code = "{suggested_name}", style = "verbose", applicability = "maybe-incorrect" @@ -133,7 +133,10 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { suggested_name: Symbol, }, #[multipart_suggestion( - hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg, + "consider fully qualifying{$identically_named -> + [true] {\"\"} + *[false] {\" \"}and renaming + } the associated {$assoc_kind}", style = "verbose" )] SimilarInOtherTraitQPath { @@ -150,7 +153,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { applicability: Applicability, }, #[suggestion( - hir_analysis_assoc_item_not_found_other_sugg, + "`{$qself}` has the following associated {$assoc_kind}", code = "{suggested_name}", applicability = "maybe-incorrect" )] @@ -164,10 +167,15 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)] +#[diag("intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}", code = E0094)] pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] - #[label] + #[label( + "expected {$expected} {$descr} {$expected -> + [one] parameter + *[other] parameters + }" + )] pub span: Span, pub found: usize, pub expected: usize, @@ -175,90 +183,90 @@ pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)] -#[help] +#[diag("unrecognized intrinsic function: `{$name}`", code = E0093)] +#[help("if you're adding an intrinsic, be sure to update `check_intrinsic_type`")] pub(crate) struct UnrecognizedIntrinsicFunction { #[primary_span] - #[label] + #[label("unrecognized intrinsic")] pub span: Span, pub name: Symbol, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)] +#[diag("lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration", code = E0195)] pub(crate) struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] - #[label] + #[label("lifetimes do not match {$item_kind} in trait")] pub span: Span, - #[label(hir_analysis_generics_label)] + #[label("lifetimes in impl do not match this {$item_kind} in trait")] pub generics_span: Span, - #[label(hir_analysis_where_label)] + #[label("this `where` clause might not match the one in the trait")] pub where_span: Option, - #[label(hir_analysis_bounds_label)] + #[label("this bound might be missing in the impl")] pub bounds_span: Vec, pub item_kind: &'static str, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] +#[diag("the `{$trait_}` trait may only be implemented for local structs, enums, and unions", code = E0120)] pub(crate) struct DropImplOnWrongItem { #[primary_span] - #[label] + #[label("must be a struct, enum, or union in the current crate")] pub span: Span, pub trait_: Symbol, } #[derive(Diagnostic)] pub(crate) enum FieldAlreadyDeclared { - #[diag(hir_analysis_field_already_declared, code = E0124)] + #[diag("field `{$field_name}` is already declared", code = E0124)] NotNested { field_name: Ident, #[primary_span] - #[label] + #[label("field already declared")] span: Span, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here")] prev_span: Span, }, - #[diag(hir_analysis_field_already_declared_current_nested)] + #[diag("field `{$field_name}` is already declared")] CurrentNested { field_name: Ident, #[primary_span] - #[label] + #[label("field `{$field_name}` declared in this unnamed field")] span: Span, - #[note(hir_analysis_nested_field_decl_note)] + #[note("field `{$field_name}` declared here")] nested_field_span: Span, #[subdiagnostic] help: FieldAlreadyDeclaredNestedHelp, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here")] prev_span: Span, }, - #[diag(hir_analysis_field_already_declared_previous_nested)] + #[diag("field `{$field_name}` is already declared")] PreviousNested { field_name: Ident, #[primary_span] - #[label] + #[label("field already declared")] span: Span, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here in this unnamed field")] prev_span: Span, - #[note(hir_analysis_previous_nested_field_decl_note)] + #[note("field `{$field_name}` first declared here")] prev_nested_field_span: Span, #[subdiagnostic] prev_help: FieldAlreadyDeclaredNestedHelp, }, - #[diag(hir_analysis_field_already_declared_both_nested)] + #[diag("field `{$field_name}` is already declared")] BothNested { field_name: Ident, #[primary_span] - #[label] + #[label("field `{$field_name}` declared in this unnamed field")] span: Span, - #[note(hir_analysis_nested_field_decl_note)] + #[note("field `{$field_name}` declared here")] nested_field_span: Span, #[subdiagnostic] help: FieldAlreadyDeclaredNestedHelp, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here in this unnamed field")] prev_span: Span, - #[note(hir_analysis_previous_nested_field_decl_note)] + #[note("field `{$field_name}` first declared here")] prev_nested_field_span: Span, #[subdiagnostic] prev_help: FieldAlreadyDeclaredNestedHelp, @@ -266,65 +274,67 @@ pub(crate) enum FieldAlreadyDeclared { } #[derive(Subdiagnostic)] -#[help(hir_analysis_field_already_declared_nested_help)] +#[help("fields from the type of this unnamed field are considered fields of the outer type")] pub(crate) struct FieldAlreadyDeclaredNestedHelp { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] +#[diag("the trait `Copy` cannot be implemented for this type; the type has a destructor", code = E0184)] pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] - #[label] + #[label("`Copy` not allowed on types with destructors")] pub span: Span, + #[note("destructor declared here")] + pub impl_: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] +#[diag("the trait `Copy` cannot be implemented for this type", code = E0206)] pub(crate) struct CopyImplOnNonAdt { #[primary_span] - #[label] + #[label("type is not a structure or enumeration")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_param_ty_impl_on_unsized)] +#[diag("the trait `ConstParamTy` may not be implemented for this type")] pub(crate) struct ConstParamTyImplOnUnsized { #[primary_span] - #[label] + #[label("type is not `Sized`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_param_ty_impl_on_non_adt)] +#[diag("the trait `ConstParamTy` may not be implemented for this type")] pub(crate) struct ConstParamTyImplOnNonAdt { #[primary_span] - #[label] + #[label("type is not a structure or enumeration")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)] +#[diag("at least one trait is required for an object type", code = E0224)] pub(crate) struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, - #[label(hir_analysis_alias_span)] + #[label("this alias does not contain a trait")] pub trait_alias_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] +#[diag("ambiguous lifetime bound, explicit lifetime bound required", code = E0227)] pub(crate) struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)] +#[diag("associated item constraints are not allowed here", code = E0229)] pub(crate) struct AssocItemConstraintsNotAllowedHere { #[primary_span] - #[label] + #[label("associated item constraint not allowed here")] pub span: Span, #[subdiagnostic] @@ -332,45 +342,64 @@ pub(crate) struct AssocItemConstraintsNotAllowedHere { } #[derive(Diagnostic)] -#[diag(hir_analysis_param_in_ty_of_assoc_const_binding)] +#[diag( + "the type of the associated constant `{$assoc_const}` must not depend on {$param_category -> + [self] `Self` + [synthetic] `impl Trait` + *[normal] generic parameters + }" +)] pub(crate) struct ParamInTyOfAssocConstBinding<'tcx> { #[primary_span] - #[label] + #[label( + "its type must not depend on {$param_category -> + [self] `Self` + [synthetic] `impl Trait` + *[normal] the {$param_def_kind} `{$param_name}` + }" + )] pub span: Span, pub assoc_const: Ident, pub param_name: Symbol, pub param_def_kind: &'static str, pub param_category: &'static str, - #[label(hir_analysis_param_defined_here_label)] + #[label( + "{$param_category -> + [synthetic] the `impl Trait` is specified here + *[normal] the {$param_def_kind} `{$param_name}` is defined here + }" + )] pub param_defined_here_label: Option, #[subdiagnostic] pub ty_note: Option>, } #[derive(Subdiagnostic, Clone, Copy)] -#[note(hir_analysis_ty_of_assoc_const_binding_note)] +#[note("`{$assoc_const}` has type `{$ty}`")] pub(crate) struct TyOfAssocConstBindingNote<'tcx> { pub assoc_const: Ident, pub ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding)] +#[diag( + "the type of the associated constant `{$assoc_const}` cannot capture late-bound generic parameters" +)] pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> { #[primary_span] - #[label] + #[label("its type cannot capture the late-bound {$var_def_kind} `{$var_name}`")] pub span: Span, pub assoc_const: Ident, pub var_name: Symbol, pub var_def_kind: &'static str, - #[label(hir_analysis_var_defined_here_label)] + #[label("the late-bound {$var_def_kind} `{$var_name}` is defined here")] pub var_defined_here_label: Span, #[subdiagnostic] pub ty_note: Option>, } #[derive(Subdiagnostic)] -#[help(hir_analysis_parenthesized_fn_trait_expansion)] +#[help("parenthesized trait syntax expands to `{$expanded_type}`")] pub(crate) struct ParenthesizedFnTraitExpansion { #[primary_span] pub span: Span, @@ -379,20 +408,20 @@ pub(crate) struct ParenthesizedFnTraitExpansion { } #[derive(Diagnostic)] -#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)] +#[diag("the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified", code = E0719)] pub(crate) struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] - #[label] + #[label("re-bound here")] pub span: Span, - #[label(hir_analysis_previous_bound_label)] + #[label("`{$item_name}` bound here first")] pub prev_span: Span, pub item_name: Ident, pub def_path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_unconstrained_opaque_type)] -#[note] +#[diag("unconstrained opaque type")] +#[note("`{$name}` must be used in combination with a concrete type within the same {$what}")] pub(crate) struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, @@ -412,10 +441,27 @@ pub(crate) struct MissingGenericParams { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut err = Diag::new(dcx, level, fluent::hir_analysis_missing_generic_params); + let mut err = Diag::new( + dcx, + level, + msg!( + "the {$descr} {$parameterCount -> + [one] parameter + *[other] parameters + } {$parameters} must be explicitly specified" + ), + ); err.span(self.span); err.code(E0393); - err.span_label(self.def_span, fluent::hir_analysis_label); + err.span_label( + self.def_span, + msg!( + "{$descr} {$parameterCount -> + [one] parameter + *[other] parameters + } {$parameters} must be specified for this" + ), + ); enum Descr { Generic, @@ -465,7 +511,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { // least we can clue them to the correct syntax `Trait`. err.span_suggestion_verbose( self.span.shrink_to_hi(), - fluent::hir_analysis_suggestion, + msg!( + "explicitly specify the {$descr} {$parameterCount -> + [one] parameter + *[other] parameters + }" + ), format!( "<{}>", self.missing_generic_params @@ -480,84 +531,112 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { } } if !suggested { - err.span_label(self.span, fluent::hir_analysis_no_suggestion_label); + err.span_label( + self.span, + msg!( + "missing {$parameterCount -> + [one] reference + *[other] references + } to {$parameters}" + ), + ); } - err.note(fluent::hir_analysis_note); + err.note(msg!( + "because the parameter {$parameterCount -> + [one] default references + *[other] defaults reference + } `Self`, the {$parameterCount -> + [one] parameter + *[other] parameters + } must be specified on the trait object type" + )); err } } #[derive(Diagnostic)] -#[diag(hir_analysis_manual_implementation, code = E0183)] -#[help] +#[diag("manual implementations of `{$trait_name}` are experimental", code = E0183)] +#[help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")] pub(crate) struct ManualImplementation { #[primary_span] - #[label] + #[label("manual implementations of `{$trait_name}` are experimental")] pub span: Span, pub trait_name: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_generic_args_on_overridden_impl)] +#[diag("could not resolve generic parameters on overridden impl")] pub(crate) struct GenericArgsOnOverriddenImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_impl_for_non_const_trait)] +#[diag("const `impl` for trait `{$trait_name}` which is not `const`")] pub(crate) struct ConstImplForNonConstTrait { #[primary_span] - #[label] + #[label("this trait is not `const`")] pub trait_ref_span: Span, pub trait_name: String, - #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] + #[suggestion( + "{$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations", + applicability = "machine-applicable", + code = "const ", + style = "verbose" + )] pub suggestion: Option, pub suggestion_pre: &'static str, - #[note] + #[note("marking a trait with `const` ensures all default method bodies are `const`")] pub marking: (), - #[note(hir_analysis_adding)] + #[note("adding a non-const method body in the future would be a breaking change")] pub adding: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_const_bound_for_non_const_trait)] +#[diag("`{$modifier}` can only be applied to `const` traits")] pub(crate) struct ConstBoundForNonConstTrait { #[primary_span] - #[label] + #[label("can't be applied to `{$trait_name}`")] pub span: Span, pub modifier: &'static str, - #[note] + #[note("`{$trait_name}` can't be used with `{$modifier}` because it isn't `const`")] pub def_span: Option, - #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] + #[suggestion( + "{$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations", + applicability = "machine-applicable", + code = "const ", + style = "verbose" + )] pub suggestion: Option, pub suggestion_pre: &'static str, pub trait_name: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_self_in_impl_self)] +#[diag("`Self` is not valid in the self type of an impl block")] pub(crate) struct SelfInImplSelf { #[primary_span] pub span: MultiSpan, - #[note] + #[note("replace `Self` with a different type")] pub note: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_linkage_type, code = E0791)] +#[diag("invalid type for variable with `#[linkage]` attribute", code = E0791)] pub(crate) struct LinkageType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[help] -#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] +#[diag("reached the recursion limit while auto-dereferencing `{$ty}`", code = E0055)] pub(crate) struct AutoDerefReachedRecursionLimit<'a> { #[primary_span] - #[label] + #[label("deref recursion limit reached")] pub span: Span, pub ty: Ty<'a>, pub suggested_limit: Limit, @@ -565,96 +644,96 @@ pub(crate) struct AutoDerefReachedRecursionLimit<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_where_clause_on_main, code = E0646)] +#[diag("`main` function is not allowed to have a `where` clause", code = E0646)] pub(crate) struct WhereClauseOnMain { #[primary_span] pub span: Span, - #[label] + #[label("`main` cannot have a `where` clause")] pub generics_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_track_caller_on_main)] +#[diag("`main` function is not allowed to be `#[track_caller]`")] pub(crate) struct TrackCallerOnMain { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "")] + #[suggestion("remove this annotation", applicability = "maybe-incorrect", code = "")] pub span: Span, - #[label(hir_analysis_track_caller_on_main)] + #[label("`main` function is not allowed to be `#[track_caller]`")] pub annotated: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_target_feature_on_main)] +#[diag("`main` function is not allowed to have `#[target_feature]`")] pub(crate) struct TargetFeatureOnMain { #[primary_span] - #[label(hir_analysis_target_feature_on_main)] + #[label("`main` function is not allowed to have `#[target_feature]`")] pub main: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_return_type_generic, code = E0131)] +#[diag("`main` function return type is not allowed to have generic parameters", code = E0131)] pub(crate) struct MainFunctionReturnTypeGeneric { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_async, code = E0752)] +#[diag("`main` function is not allowed to be `async`", code = E0752)] pub(crate) struct MainFunctionAsync { #[primary_span] pub span: Span, - #[label] + #[label("`main` function is not allowed to be `async`")] pub asyncness: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_generic_parameters, code = E0131)] +#[diag("`main` function is not allowed to have generic parameters", code = E0131)] pub(crate) struct MainFunctionGenericParameters { #[primary_span] pub span: Span, - #[label] + #[label("`main` cannot have generic parameters")] pub label_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] +#[diag("C-variadic functions with the {$convention} calling convention are not supported", code = E0045)] pub(crate) struct VariadicFunctionCompatibleConvention<'a> { #[primary_span] - #[label] + #[label("C-variadic function must have a compatible calling convention")] pub span: Span, pub convention: &'a str, } #[derive(Diagnostic)] pub(crate) enum CannotCaptureLateBound { - #[diag(hir_analysis_cannot_capture_late_bound_ty)] + #[diag("cannot capture late-bound type parameter in {$what}")] Type { #[primary_span] use_span: Span, - #[label] + #[label("parameter defined here")] def_span: Span, what: &'static str, }, - #[diag(hir_analysis_cannot_capture_late_bound_const)] + #[diag("cannot capture late-bound const parameter in {$what}")] Const { #[primary_span] use_span: Span, - #[label] + #[label("parameter defined here")] def_span: Span, what: &'static str, }, - #[diag(hir_analysis_cannot_capture_late_bound_lifetime)] + #[diag("cannot capture late-bound lifetime in {$what}")] Lifetime { #[primary_span] use_span: Span, - #[label] + #[label("lifetime defined here")] def_span: Span, what: &'static str, }, } #[derive(Diagnostic)] -#[diag(hir_analysis_variances_of)] +#[diag("{$variances}")] pub(crate) struct VariancesOf { #[primary_span] pub span: Span, @@ -662,7 +741,7 @@ pub(crate) struct VariancesOf { } #[derive(Diagnostic)] -#[diag(hir_analysis_type_of)] +#[diag("{$ty}")] pub(crate) struct TypeOf<'tcx> { #[primary_span] pub span: Span, @@ -670,30 +749,37 @@ pub(crate) struct TypeOf<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_union_field, code = E0740)] +#[diag("field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union", code = E0740)] pub(crate) struct InvalidUnionField { #[primary_span] pub field_span: Span, #[subdiagnostic] pub sugg: InvalidUnionFieldSuggestion, - #[note] + #[note( + "union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`" + )] pub note: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_on_non_rpitit)] +#[diag( + "return type notation used on function that is not `async` and does not return `impl Trait`" +)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, - #[label] + #[label("this function must be `async` or return `impl Trait`")] pub fn_span: Option, - #[note] + #[note("function returns `{$ty}`, which is not compatible with associated type return bounds")] pub note: (), } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "wrap the field type in `ManuallyDrop<...>`", + applicability = "machine-applicable" +)] pub(crate) struct InvalidUnionFieldSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop<")] pub lo: Span, @@ -702,27 +788,32 @@ pub(crate) struct InvalidUnionFieldSuggestion { } #[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_equality_bound)] +#[diag("return type notation is not allowed to use type equality")] pub(crate) struct ReturnTypeNotationEqualityBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = E0121)] +#[diag("the placeholder `_` is not allowed within types on item signatures for {$kind}", code = E0121)] pub(crate) struct PlaceholderNotAllowedItemSignatures { #[primary_span] - #[label] + #[label("not allowed in type signatures")] pub spans: Vec, pub kind: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)] +#[diag("cannot use the {$what} of a trait with uninferred generic parameters", code = E0212)] pub(crate) struct AssociatedItemTraitUninferredGenericParams { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")] + #[suggestion( + "use a fully qualified path with inferred lifetimes", + style = "verbose", + applicability = "maybe-incorrect", + code = "{bound}" + )] pub inferred_sugg: Option, pub bound: String, #[subdiagnostic] @@ -732,7 +823,7 @@ pub(crate) struct AssociatedItemTraitUninferredGenericParams { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion, + "use a fully qualified path with explicit lifetimes", applicability = "maybe-incorrect" )] pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion { @@ -745,11 +836,11 @@ pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion } #[derive(Diagnostic)] -#[diag(hir_analysis_enum_discriminant_overflowed, code = E0370)] -#[note] +#[diag("enum discriminant overflowed", code = E0370)] +#[note("explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome")] pub(crate) struct EnumDiscriminantOverflowed { #[primary_span] - #[label] + #[label("overflowed on value after {$discr}")] pub span: Span, pub discr: String, pub item_name: Ident, @@ -757,16 +848,18 @@ pub(crate) struct EnumDiscriminantOverflowed { } #[derive(Diagnostic)] -#[diag(hir_analysis_paren_sugar_attribute)] -#[help] +#[diag( + "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation" +)] +#[help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")] pub(crate) struct ParenSugarAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_simd_ffi_highly_experimental)] -#[help] +#[diag("use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code")] +#[help("add `#![feature(simd_ffi)]` to the crate attributes to enable")] pub(crate) struct SIMDFFIHighlyExperimental { #[primary_span] pub span: Span, @@ -775,18 +868,18 @@ pub(crate) struct SIMDFFIHighlyExperimental { #[derive(Diagnostic)] pub(crate) enum ImplNotMarkedDefault { - #[diag(hir_analysis_impl_not_marked_default, code = E0520)] - #[note] + #[diag("`{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`", code = E0520)] + #[note("to specialize, `{$ident}` in the parent `impl` must be marked `default`")] Ok { #[primary_span] - #[label] + #[label("cannot specialize default item `{$ident}`")] span: Span, - #[label(hir_analysis_ok_label)] + #[label("parent `impl` is here")] ok_label: Span, ident: Ident, }, - #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)] - #[note] + #[diag("`{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`", code = E0520)] + #[note("parent implementation is in crate `{$cname}`")] Err { #[primary_span] span: Span, @@ -796,14 +889,14 @@ pub(crate) enum ImplNotMarkedDefault { } #[derive(LintDiagnostic)] -#[diag(hir_analysis_useless_impl_item)] +#[diag("this item cannot be used as its where bounds are not satisfied for the `Self` type")] pub(crate) struct UselessImplItem; #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item, code = E0046)] +#[diag("not all trait items implemented, missing: `{$missing_items_msg}`", code = E0046)] pub(crate) struct MissingTraitItem { #[primary_span] - #[label] + #[label("missing `{$missing_items_msg}` in implementation")] pub span: Span, #[subdiagnostic] pub missing_trait_item_label: Vec, @@ -815,7 +908,7 @@ pub(crate) struct MissingTraitItem { } #[derive(Subdiagnostic)] -#[label(hir_analysis_missing_trait_item_label)] +#[label("`{$item}` from trait")] pub(crate) struct MissingTraitItemLabel { #[primary_span] pub span: Span, @@ -824,7 +917,7 @@ pub(crate) struct MissingTraitItemLabel { #[derive(Subdiagnostic)] #[suggestion( - hir_analysis_missing_trait_item_suggestion, + "implement the missing item: `{$snippet}`", style = "tool-only", applicability = "has-placeholders", code = "{code}" @@ -838,7 +931,7 @@ pub(crate) struct MissingTraitItemSuggestion { #[derive(Subdiagnostic)] #[suggestion( - hir_analysis_missing_trait_item_suggestion, + "implement the missing item: `{$snippet}`", style = "hidden", applicability = "has-placeholders", code = "{code}" @@ -851,25 +944,25 @@ pub(crate) struct MissingTraitItemSuggestionNone { } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_one_of_trait_item, code = E0046)] +#[diag("not all trait items implemented, missing one of: `{$missing_items_msg}`", code = E0046)] pub(crate) struct MissingOneOfTraitItem { #[primary_span] - #[label] + #[label("missing one of `{$missing_items_msg}` in implementation")] pub span: Span, - #[note] + #[note("required because of this annotation")] pub note: Option, pub missing_items_msg: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item_unstable, code = E0046)] -#[note] +#[diag("not all trait items implemented, missing: `{$missing_item_name}`", code = E0046)] +#[note("default implementation of `{$missing_item_name}` is unstable")] pub(crate) struct MissingTraitItemUnstable { #[primary_span] pub span: Span, - #[note(hir_analysis_some_note)] + #[note("use of unstable library feature `{$feature}`: {$reason}")] pub some_note: bool, - #[note(hir_analysis_none_note)] + #[note("use of unstable library feature `{$feature}`")] pub none_note: bool, pub missing_item_name: Ident, pub feature: Symbol, @@ -877,78 +970,78 @@ pub(crate) struct MissingTraitItemUnstable { } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_enum_variant, code = E0731)] +#[diag("transparent enum needs exactly one variant, but has {$number}", code = E0731)] pub(crate) struct TransparentEnumVariant { #[primary_span] - #[label] + #[label("needs exactly one variant, but has {$number}")] pub span: Span, - #[label(hir_analysis_multi_label)] + #[label("variant here")] pub spans: Vec, - #[label(hir_analysis_many_label)] + #[label("too many variants in `{$path}`")] pub many: Option, pub number: usize, pub path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized_enum, code = E0690)] +#[diag("the variant of a transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count}", code = E0690)] pub(crate) struct TransparentNonZeroSizedEnum<'a> { #[primary_span] - #[label] + #[label("needs at most one field with non-trivial size or alignment, but has {$field_count}")] pub span: Span, - #[label(hir_analysis_labels)] + #[label("this field has non-zero size or requires alignment")] pub spans: Vec, pub field_count: usize, pub desc: &'a str, } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized, code = E0690)] +#[diag("transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count}", code = E0690)] pub(crate) struct TransparentNonZeroSized<'a> { #[primary_span] - #[label] + #[label("needs at most one field with non-trivial size or alignment, but has {$field_count}")] pub span: Span, - #[label(hir_analysis_labels)] + #[label("this field has non-zero size or requires alignment")] pub spans: Vec, pub field_count: usize, pub desc: &'a str, } #[derive(Diagnostic)] -#[diag(hir_analysis_too_large_static)] +#[diag("extern static is too large for the target architecture")] pub(crate) struct TooLargeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_specialization_trait)] -#[help] +#[diag("implementing `rustc_specialization_trait` traits is unstable")] +#[help("add `#![feature(min_specialization)]` to the crate attributes to enable")] pub(crate) struct SpecializationTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_closure_implicit_hrtb)] +#[diag("implicit types in closure signatures are forbidden when `for<...>` is present")] pub(crate) struct ClosureImplicitHrtb { #[primary_span] pub spans: Vec, - #[label] + #[label("`for<...>` is here")] pub for_sp: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_empty_specialization)] +#[diag("specialization impl does not specialize any associated items")] pub(crate) struct EmptySpecialization { #[primary_span] pub span: Span, - #[note] + #[note("impl is a specialization of this impl")] pub base_impl_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_static_specialize)] +#[diag("cannot specialize on `'static` lifetime")] pub(crate) struct StaticSpecialize { #[primary_span] pub span: Span, @@ -956,12 +1049,12 @@ pub(crate) struct StaticSpecialize { #[derive(Diagnostic)] pub(crate) enum DropImplPolarity { - #[diag(hir_analysis_drop_impl_negative)] + #[diag("negative `Drop` impls are not supported")] Negative { #[primary_span] span: Span, }, - #[diag(hir_analysis_drop_impl_reservation)] + #[diag("reservation `Drop` impls are not supported")] Reservation { #[primary_span] span: Span, @@ -970,65 +1063,75 @@ pub(crate) enum DropImplPolarity { #[derive(Diagnostic)] pub(crate) enum ReturnTypeNotationIllegalParam { - #[diag(hir_analysis_return_type_notation_illegal_param_type)] + #[diag("return type notation is not allowed for functions that have type parameters")] Type { #[primary_span] span: Span, - #[label] + #[label("type parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_return_type_notation_illegal_param_const)] + #[diag("return type notation is not allowed for functions that have const parameters")] Const { #[primary_span] span: Span, - #[label] + #[label("const parameter declared here")] param_span: Span, }, } #[derive(Diagnostic)] pub(crate) enum LateBoundInApit { - #[diag(hir_analysis_late_bound_type_in_apit)] + #[diag("`impl Trait` can only mention type parameters from an fn or impl")] Type { #[primary_span] span: Span, - #[label] + #[label("type parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_late_bound_const_in_apit)] + #[diag("`impl Trait` can only mention const parameters from an fn or impl")] Const { #[primary_span] span: Span, - #[label] + #[label("const parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_late_bound_lifetime_in_apit)] + #[diag("`impl Trait` can only mention lifetimes from an fn or impl")] Lifetime { #[primary_span] span: Span, - #[label] + #[label("lifetime declared here")] param_span: Span, }, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_unused_associated_type_bounds)] -#[note] +#[diag("unnecessary associated type bound for dyn-incompatible associated type")] +#[note( + "this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`" +)] pub(crate) struct UnusedAssociatedTypeBounds { - #[suggestion(code = "")] + #[suggestion("remove this bound", code = "")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_rpitit_refined)] -#[note] -#[note(hir_analysis_feedback_note)] +#[diag("impl trait in impl method signature does not match trait method signature")] +#[note( + "add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate" +)] +#[note( + "we are soliciting feedback, see issue #121718 for more information" +)] pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { - #[suggestion(applicability = "maybe-incorrect", code = "{pre}{return_ty}{post}")] + #[suggestion( + "replace the return type so that it matches the trait", + applicability = "maybe-incorrect", + code = "{pre}{return_ty}{post}" + )] pub impl_return_span: Span, - #[label] + #[label("return type from trait method defined here")] pub trait_return_span: Option, - #[label(hir_analysis_unmatched_bound_label)] + #[label("this bound is stronger than that defined on the trait")] pub unmatched_bound: Option, pub pre: &'static str, @@ -1037,33 +1140,43 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { } #[derive(LintDiagnostic)] -#[diag(hir_analysis_rpitit_refined_lifetimes)] -#[note] -#[note(hir_analysis_feedback_note)] +#[diag("impl trait in impl method captures fewer lifetimes than in trait")] +#[note( + "add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate" +)] +#[note( + "we are soliciting feedback, see issue #121718 for more information" +)] pub(crate) struct ReturnPositionImplTraitInTraitRefinedLifetimes { - #[suggestion(applicability = "maybe-incorrect", code = "{suggestion}")] + #[suggestion( + "modify the `use<..>` bound to capture the same lifetimes that the trait does", + applicability = "maybe-incorrect", + code = "{suggestion}" + )] pub suggestion_span: Span, pub suggestion: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0390)] +#[help("consider moving this inherent impl into the crate defining the type if possible")] pub(crate) struct InherentTyOutside { #[primary_span] - #[help(hir_analysis_span_help)] + #[help( + "alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] +#[diag("structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`", code = E0378)] pub(crate) struct DispatchFromDynRepr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}`", code = E0802)] pub(crate) struct CoercePointeeNotStruct { #[primary_span] pub span: Span, @@ -1071,65 +1184,81 @@ pub(crate) struct CoercePointeeNotStruct { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct`", code = E0802)] pub(crate) struct CoercePointeeNotConcreteType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)] +#[diag("asserting applicability of `derive(CoercePointee)` on a target data is forbidden", code = E0802)] pub(crate) struct CoercePointeeNoUserValidityAssertion { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout", code = E0802)] pub(crate) struct CoercePointeeNotTransparent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with at least one field", code = E0802)] pub(crate) struct CoercePointeeNoField { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0390)] +#[help("consider moving this inherent impl into the crate defining the type if possible")] pub(crate) struct InherentTyOutsideRelevant { #[primary_span] pub span: Span, - #[help(hir_analysis_span_help)] + #[help("alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items")] pub help_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)] -#[note] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0116)] +#[help( + "consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it" +)] +#[note( + "for more details about the orphan rules, see " +)] pub(crate) struct InherentTyOutsideNew { #[primary_span] - #[label] + #[label("impl for type defined outside of crate")] pub span: Span, + #[subdiagnostic] + pub note: Option, +} + +#[derive(Subdiagnostic)] +#[note("`{$ty_name}` does not define a new type, only an alias of `{$alias_ty_name}` defined here")] +pub(crate) struct InherentTyOutsideNewAliasNote { + #[primary_span] + pub span: Span, + pub ty_name: String, + pub alias_ty_name: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for primitive types outside of `core`", code = E0390)] +#[help("consider moving this inherent impl into `core` if possible")] pub(crate) struct InherentTyOutsidePrimitive { #[primary_span] pub span: Span, - #[help(hir_analysis_span_help)] + #[help("alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items")] pub help_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_primitive_ty, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for primitive types", code = E0390)] +#[help("consider using an extension trait instead")] pub(crate) struct InherentPrimitiveTy<'a> { #[primary_span] pub span: Span, @@ -1138,32 +1267,34 @@ pub(crate) struct InherentPrimitiveTy<'a> { } #[derive(Subdiagnostic)] -#[note(hir_analysis_inherent_primitive_ty_note)] +#[note( + "you could also try moving the reference to uses of `{$subty}` (such as `self`) within the implementation" +)] pub(crate) struct InherentPrimitiveTyNote<'a> { pub subty: Ty<'a>, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_dyn, code = E0785)] -#[note] +#[diag("cannot define inherent `impl` for a dyn auto trait", code = E0785)] +#[note("define and implement a new trait or type instead")] pub(crate) struct InherentDyn { #[primary_span] - #[label] + #[label("impl requires at least one non-auto trait")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_nominal, code = E0118)] -#[note] +#[diag("no nominal type found for inherent implementation", code = E0118)] +#[note("either implement a trait on it or create a newtype to wrap it instead")] pub(crate) struct InherentNominal { #[primary_span] - #[label] + #[label("impl requires a nominal type")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)] -#[note] +#[diag("the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else", code = E0378)] +#[note("extra field `{$name}` of type `{$ty}` is not allowed")] pub(crate) struct DispatchFromDynZST<'a> { #[primary_span] pub span: Span, @@ -1172,28 +1303,30 @@ pub(crate) struct DispatchFromDynZST<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_zero, code = E0374)] +#[diag("implementing `{$trait_name}` requires a field to be coerced", code = E0374)] pub(crate) struct CoerceNoField { #[primary_span] pub span: Span, pub trait_name: &'static str, - #[note(hir_analysis_coercion_between_struct_single_note)] + #[note("expected a single field to be coerced, none found")] pub note: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_multi, code = E0375)] +#[diag("implementing `{$trait_name}` does not allow multiple fields to be coerced", code = E0375)] pub(crate) struct CoerceMulti { pub trait_name: &'static str, #[primary_span] pub span: Span, pub number: usize, - #[note] + #[note( + "the trait `{$trait_name}` may only be implemented when a single field is being coerced" + )] pub fields: MultiSpan, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0377)] +#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)] pub(crate) struct CoerceUnsizedNonStruct { #[primary_span] pub span: Span, @@ -1201,7 +1334,7 @@ pub(crate) struct CoerceUnsizedNonStruct { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_same_pat_kind)] +#[diag("only pattern types with the same pattern can be coerced between each other")] pub(crate) struct CoerceSamePatKind { #[primary_span] pub span: Span, @@ -1211,43 +1344,49 @@ pub(crate) struct CoerceSamePatKind { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0377)] +#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)] pub(crate) struct CoerceSameStruct { #[primary_span] pub span: Span, pub trait_name: &'static str, - #[note(hir_analysis_coercion_between_struct_same_note)] + #[note( + "expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}`" + )] pub note: bool, pub source_path: String, pub target_path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_field_validity)] +#[diag( + "for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}`" +)] pub(crate) struct CoerceFieldValidity<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub trait_name: &'static str, - #[label] + #[label( + "`{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized" + )] pub field_span: Span, pub field_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] +#[diag("the trait `{$trait_name}` cannot be implemented for this type", code = E0204)] pub(crate) struct TraitCannotImplForTy { #[primary_span] pub span: Span, pub trait_name: String, - #[label] + #[label("this field does not implement `{$trait_name}`")] pub label_spans: Vec, #[subdiagnostic] pub notes: Vec, } #[derive(Subdiagnostic)] -#[note(hir_analysis_requires_note)] +#[note("the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`")] pub(crate) struct ImplForTyRequires { #[primary_span] pub span: MultiSpan, @@ -1257,8 +1396,10 @@ pub(crate) struct ImplForTyRequires { } #[derive(Diagnostic)] -#[diag(hir_analysis_traits_with_default_impl, code = E0321)] -#[note] +#[diag("traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`", code = E0321)] +#[note( + "a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds" +)] pub(crate) struct TraitsWithDefaultImpl<'a> { #[primary_span] pub span: Span, @@ -1268,26 +1409,26 @@ pub(crate) struct TraitsWithDefaultImpl<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits, code = E0321)] +#[diag("cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`", code = E0321)] pub(crate) struct CrossCrateTraits<'a> { #[primary_span] - #[label] + #[label("can't implement cross-crate trait with a default impl for non-struct/enum type")] pub span: Span, pub traits: String, pub self_ty: Ty<'a>, } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits_defined, code = E0321)] +#[diag("cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate", code = E0321)] pub(crate) struct CrossCrateTraitsDefined { #[primary_span] - #[label] + #[label("can't implement cross-crate trait for type in another crate")] pub span: Span, pub traits: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_no_variant_named, code = E0599)] +#[diag("no variant named `{$ident}` found for enum `{$ty}`", code = E0599)] pub struct NoVariantNamed<'tcx> { #[primary_span] pub span: Span, @@ -1298,99 +1439,123 @@ pub struct NoVariantNamed<'tcx> { // FIXME(fmease): Deduplicate: #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_first_local, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type" +)] pub(crate) struct TyParamFirstLocal<'tcx> { #[primary_span] - #[label] + #[label( + "type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)" + )] pub span: Span, - #[note(hir_analysis_case_note)] + #[note( + "in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last" + )] pub note: (), pub param: Ident, pub local_type: Ty<'tcx>, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_ty_param_first_local, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type" +)] pub(crate) struct TyParamFirstLocalLint<'tcx> { - #[label] + #[label( + "type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)" + )] pub span: Span, - #[note(hir_analysis_case_note)] + #[note( + "in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last" + )] pub note: (), pub param: Ident, pub local_type: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_some, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local" +)] pub(crate) struct TyParamSome { #[primary_span] - #[label] + #[label("type parameter `{$param}` must be used as the type parameter for some local type")] pub span: Span, - #[note(hir_analysis_only_note)] + #[note("only traits defined in the current crate can be implemented for a type parameter")] pub note: (), pub param: Ident, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_ty_param_some, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local" +)] pub(crate) struct TyParamSomeLint { - #[label] + #[label("type parameter `{$param}` must be used as the type parameter for some local type")] pub span: Span, - #[note(hir_analysis_only_note)] + #[note("only traits defined in the current crate can be implemented for a type parameter")] pub note: (), pub param: Ident, } #[derive(Diagnostic)] pub(crate) enum OnlyCurrentTraits { - #[diag(hir_analysis_only_current_traits_outside, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for types defined outside of the crate", code = E0117)] Outside { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, - #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for primitive types", code = E0117)] Primitive { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, - #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for arbitrary types", code = E0117)] Arbitrary { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_opaque)] +#[label( + "type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate" +)] pub(crate) struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_foreign)] +#[label("this is not defined in the current crate because this is a foreign trait")] pub(crate) struct OnlyCurrentTraitsForeign { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_name)] +#[label("this is not defined in the current crate because {$name} are always foreign")] pub(crate) struct OnlyCurrentTraitsName<'a> { #[primary_span] pub span: Span, @@ -1398,7 +1563,7 @@ pub(crate) struct OnlyCurrentTraitsName<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_pointer)] +#[label("`{$pointer}` is not defined in the current crate because raw pointers are always foreign")] pub(crate) struct OnlyCurrentTraitsPointer<'a> { #[primary_span] pub span: Span, @@ -1406,7 +1571,7 @@ pub(crate) struct OnlyCurrentTraitsPointer<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_ty)] +#[label("`{$ty}` is not defined in the current crate")] pub(crate) struct OnlyCurrentTraitsTy<'a> { #[primary_span] pub span: Span, @@ -1414,7 +1579,7 @@ pub(crate) struct OnlyCurrentTraitsTy<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_adt)] +#[label("`{$name}` is not defined in the current crate")] pub(crate) struct OnlyCurrentTraitsAdt { #[primary_span] pub span: Span, @@ -1423,7 +1588,7 @@ pub(crate) struct OnlyCurrentTraitsAdt { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_analysis_only_current_traits_pointer_sugg, + "consider introducing a new wrapper type", applicability = "maybe-incorrect" )] pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { @@ -1436,104 +1601,120 @@ pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_not_supported_delegation)] +#[diag("{$descr}")] pub(crate) struct UnsupportedDelegation<'a> { #[primary_span] pub span: Span, pub descr: &'a str, - #[label] + #[label("callee defined here")] pub callee_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_method_should_return_future)] +#[diag("method should be `async` or return a future, but it is synchronous")] pub(crate) struct MethodShouldReturnFuture { #[primary_span] pub span: Span, pub method_name: Ident, - #[note] + #[note("this method is `async` so it expects a future to be returned")] pub trait_item_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_unused_generic_parameter)] +#[diag("{$param_def_kind} `{$param_name}` is never used")] pub(crate) struct UnusedGenericParameter { #[primary_span] - #[label] + #[label("unused {$param_def_kind}")] pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[label(hir_analysis_usage_spans)] + #[label("`{$param_name}` is named here, but is likely unused in the containing type")] pub usage_spans: Vec, #[subdiagnostic] pub help: UnusedGenericParameterHelp, - #[help(hir_analysis_const_param_help)] + #[help( + "if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead" + )] pub const_param_help: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_recursive_generic_parameter)] +#[diag("{$param_def_kind} `{$param_name}` is only used recursively")] pub(crate) struct RecursiveGenericParameter { #[primary_span] pub spans: Vec, - #[label] + #[label("{$param_def_kind} must be used non-recursively in the definition")] pub param_span: Span, pub param_name: Ident, pub param_def_kind: &'static str, #[subdiagnostic] pub help: UnusedGenericParameterHelp, - #[note] + #[note( + "all type parameters must be used in a non-recursive way in order to constrain their variance" + )] pub note: (), } #[derive(Subdiagnostic)] pub(crate) enum UnusedGenericParameterHelp { - #[help(hir_analysis_unused_generic_parameter_adt_help)] + #[help( + "consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`" + )] Adt { param_name: Ident, phantom_data: String }, - #[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)] + #[help("consider removing `{$param_name}` or referring to it in a field")] AdtNoPhantomData { param_name: Ident }, - #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] + #[help("consider removing `{$param_name}` or referring to it in the body of the type alias")] TyAlias { param_name: Ident }, } #[derive(Diagnostic)] -#[diag(hir_analysis_unconstrained_generic_parameter)] +#[diag( + "the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates" +)] pub(crate) struct UnconstrainedGenericParameter { #[primary_span] - #[label] + #[label("unconstrained {$param_def_kind}")] pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[note(hir_analysis_const_param_note)] + #[note("expressions using a const parameter must map each value to a distinct output value")] pub const_param_note: bool, - #[note(hir_analysis_const_param_note2)] + #[note( + "proving the result of expressions other than the parameter are unique is not supported" + )] pub const_param_note2: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] +#[diag("`impl Trait` cannot capture {$bad_place}", code = E0657)] pub(crate) struct OpaqueCapturesHigherRankedLifetime { #[primary_span] pub span: MultiSpan, - #[label] + #[label("`impl Trait` implicitly captures all lifetimes in scope")] pub label: Option, - #[note] + #[note("lifetime declared here")] pub decl_span: MultiSpan, pub bad_place: &'static str, } #[derive(Subdiagnostic)] pub(crate) enum InvalidReceiverTyHint { - #[note(hir_analysis_invalid_receiver_ty_help_weak_note)] + #[note( + "`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`" + )] Weak, - #[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)] + #[note( + "`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`" + )] NonNull, } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)] -#[note] -#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)] +#[diag("invalid `self` parameter type: `{$receiver_ty}`", code = E0307)] +#[note("type of `self` must be `Self` or a type that dereferences to it")] +#[help( + "consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`)" +)] pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { #[primary_span] pub span: Span, @@ -1541,9 +1722,11 @@ pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_receiver_ty, code = E0307)] -#[note] -#[help(hir_analysis_invalid_receiver_ty_help)] +#[diag("invalid `self` parameter type: `{$receiver_ty}`", code = E0307)] +#[note("type of `self` must be `Self` or some type implementing `Receiver`")] +#[help( + "consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`" +)] pub(crate) struct InvalidReceiverTy<'tcx> { #[primary_span] pub span: Span, @@ -1553,9 +1736,11 @@ pub(crate) struct InvalidReceiverTy<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)] -#[note] -#[help(hir_analysis_invalid_generic_receiver_ty_help)] +#[diag("invalid generic `self` parameter type: `{$receiver_ty}`", code = E0801)] +#[note("type of `self` must not be a method generic parameter type")] +#[help( + "use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`)" +)] pub(crate) struct InvalidGenericReceiverTy<'tcx> { #[primary_span] pub span: Span, @@ -1563,28 +1748,32 @@ pub(crate) struct InvalidGenericReceiverTy<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)] -#[note] +#[diag("arguments for `{$abi}` function too large to pass via registers", code = E0798)] +#[note( + "functions with the `{$abi}` ABI must pass all their arguments via the 4 32-bit argument registers" +)] pub(crate) struct CmseInputsStackSpill { #[primary_span] - #[label] + #[label("does not fit in the available registers")] pub spans: Vec, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)] -#[note(hir_analysis_note1)] -#[note(hir_analysis_note2)] +#[diag("return value of `{$abi}` function too large to pass via registers", code = E0798)] +#[note("functions with the `{$abi}` ABI must pass their result via the available return registers")] +#[note( + "the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size" +)] pub(crate) struct CmseOutputStackSpill { #[primary_span] - #[label] + #[label("this type doesn't fit in the available registers")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_generic, code = E0798)] +#[diag("generics are not allowed in `extern {$abi}` signatures", code = E0798)] pub(crate) struct CmseGeneric { #[primary_span] pub span: Span, @@ -1592,7 +1781,7 @@ pub(crate) struct CmseGeneric { } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_impl_trait, code = E0798)] +#[diag("`impl Trait` is not allowed in `extern {$abi}` signatures", code = E0798)] pub(crate) struct CmseImplTrait { #[primary_span] pub span: Span, @@ -1600,14 +1789,14 @@ pub(crate) struct CmseImplTrait { } #[derive(Diagnostic)] -#[diag(hir_analysis_bad_return_type_notation_position)] +#[diag("return type notation not allowed in this position yet")] pub(crate) struct BadReturnTypeNotation { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_supertrait_item_shadowing)] +#[diag("trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait")] pub(crate) struct SupertraitItemShadowing { pub item: Symbol, pub subtrait: Symbol, @@ -1617,13 +1806,13 @@ pub(crate) struct SupertraitItemShadowing { #[derive(Subdiagnostic)] pub(crate) enum SupertraitItemShadowee { - #[note(hir_analysis_supertrait_item_shadowee)] + #[note("item from `{$supertrait}` is shadowed by a subtrait item")] Labeled { #[primary_span] span: Span, supertrait: Symbol, }, - #[note(hir_analysis_supertrait_item_multiple_shadowee)] + #[note("items from several supertraits are shadowed: {$traits}")] Several { #[primary_span] spans: MultiSpan, @@ -1632,23 +1821,25 @@ pub(crate) enum SupertraitItemShadowee { } #[derive(Diagnostic)] -#[diag(hir_analysis_dyn_trait_assoc_item_binding_mentions_self)] +#[diag("{$kind} binding in trait object type mentions `Self`")] pub(crate) struct DynTraitAssocItemBindingMentionsSelf { #[primary_span] - #[label] + #[label("contains a mention of `Self`")] pub span: Span, pub kind: &'static str, - #[label(hir_analysis_binding_label)] + #[label("this binding mentions `Self`")] pub binding: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_abi_custom_clothed_function)] +#[diag( + "items with the \"custom\" ABI can only be declared externally or defined via naked functions" +)] pub(crate) struct AbiCustomClothedFunction { #[primary_span] pub span: Span, #[suggestion( - hir_analysis_suggestion, + "convert this to an `#[unsafe(naked)]` function", applicability = "maybe-incorrect", code = "#[unsafe(naked)]\n", style = "short" @@ -1657,36 +1848,49 @@ pub(crate) struct AbiCustomClothedFunction { } #[derive(Diagnostic)] -#[diag(hir_analysis_async_drop_without_sync_drop)] -#[help] +#[diag("`AsyncDrop` impl without `Drop` impl")] +#[help( + "type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds" +)] pub(crate) struct AsyncDropWithoutSyncDrop { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_eii)] +#[diag("lifetime parameters or bounds of `{$ident}` do not match the declaration")] pub(crate) struct LifetimesOrBoundsMismatchOnEii { #[primary_span] - #[label] + #[label("lifetimes do not match")] pub span: Span, - #[label(hir_analysis_generics_label)] + #[label("lifetimes in impl do not match this signature")] pub generics_span: Span, - #[label(hir_analysis_where_label)] + #[label("this `where` clause might not match the one in the trait")] pub where_span: Option, - #[label(hir_analysis_bounds_label)] + #[label("this bound might be missing in the impl")] pub bounds_span: Vec, pub ident: Symbol, } #[derive(Diagnostic)] -#[diag(hir_analysis_eii_with_generics)] -#[help] +#[diag("`{$impl_name}` cannot have generic parameters other than lifetimes")] +#[help("`#[{$eii_name}]` marks the implementation of an \"externally implementable item\"")] pub(crate) struct EiiWithGenerics { #[primary_span] pub span: Span, - #[label] + #[label("required by this attribute")] pub attr: Span, pub eii_name: Symbol, pub impl_name: Symbol, } + +#[derive(Diagnostic)] +#[diag("explicit impls for the `Unpin` trait are not permitted for structurally pinned types")] +pub(crate) struct ImplUnpinForPinProjectedType { + #[primary_span] + #[label("impl of `Unpin` not allowed")] + pub span: Span, + #[help("`{$adt_name}` is structurally pinned because it is marked as `#[pin_v2]`")] + pub adt_span: Span, + pub adt_name: Symbol, +} diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index 8a83866b7fa4..f9e62b8ebcf8 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -3,48 +3,54 @@ use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(hir_analysis_param_not_captured)] -#[note] +#[diag("`impl Trait` must mention all {$kind} parameters in scope in `use<...>`")] +#[note( + "currently, all {$kind} parameters are required to be mentioned in the precise captures list" +)] pub(crate) struct ParamNotCaptured { #[primary_span] pub opaque_span: Span, - #[label] + #[label("{$kind} parameter is implicitly captured by this `impl Trait`")] pub param_span: Span, pub kind: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_self_ty_not_captured)] -#[note] +#[diag("`impl Trait` must mention the `Self` type of the trait in `use<...>`")] +#[note("currently, all type parameters are required to be mentioned in the precise captures list")] pub(crate) struct SelfTyNotCaptured { #[primary_span] pub opaque_span: Span, - #[label] + #[label("`Self` type parameter is implicitly captured by this `impl Trait`")] pub trait_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_not_captured)] +#[diag( + "`impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list" +)] pub(crate) struct LifetimeNotCaptured { #[primary_span] pub use_span: Span, - #[label(hir_analysis_param_label)] + #[label("this lifetime parameter is captured")] pub param_span: Span, - #[label] + #[label("lifetime captured due to being mentioned in the bounds of the `impl Trait`")] pub opaque_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_implicitly_captured)] +#[diag( + "`impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list" +)] pub(crate) struct LifetimeImplicitlyCaptured { #[primary_span] pub opaque_span: Span, - #[label(hir_analysis_param_label)] + #[label("all lifetime parameters originating from a trait are captured implicitly")] pub param_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_bad_precise_capture)] +#[diag("expected {$kind} parameter in `use<...>` precise captures list, found {$found}")] pub(crate) struct BadPreciseCapture { #[primary_span] pub span: Span, @@ -53,31 +59,31 @@ pub(crate) struct BadPreciseCapture { } #[derive(Diagnostic)] -#[diag(hir_analysis_precise_capture_self_alias, code = E0799)] +#[diag("`Self` can't be captured in `use<...>` precise captures list, since it is an alias", code = E0799)] pub(crate) struct PreciseCaptureSelfAlias { #[primary_span] pub span: Span, - #[label] + #[label("`Self` is not a generic argument, but an alias to the type of the {$what}")] pub self_span: Span, pub what: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_duplicate_precise_capture)] +#[diag("cannot capture parameter `{$name}` twice")] pub(crate) struct DuplicatePreciseCapture { #[primary_span] pub first_span: Span, pub name: Symbol, - #[label] + #[label("parameter captured again here")] pub second_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_must_be_first)] +#[diag("lifetime parameter `{$name}` must be listed before non-lifetime parameters")] pub(crate) struct LifetimesMustBeFirst { #[primary_span] pub lifetime_span: Span, pub name: Symbol, - #[label] + #[label("move the lifetime before this parameter")] pub other_span: Span, } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index d6441702b268..670312ff1ba1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, kw}; use rustc_trait_selection::traits; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -171,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` - if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) { + if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) { return; } @@ -285,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { context: ImpliedBoundsContext<'tcx>, ) -> bool { let collected = collect_bounds(hir_bounds, context, trait_def_id); - !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any() + !find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) + && !collected.any() } fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) { @@ -362,7 +363,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { param_ty: Ty<'tcx>, hir_bounds: I, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, - bound_vars: &'tcx ty::List, + bound_vars: &'tcx ty::List>, predicate_filter: PredicateFilter, overlapping_assoc_constraints: OverlappingAsssocItemConstraints, ) where @@ -603,22 +604,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !find_attr!( - self.tcx().get_all_attrs(assoc_item.def_id), - AttributeKind::TypeConst(_) - ) + && !self.tcx().is_type_const(assoc_item.def_id) { if tcx.features().min_generic_const_args() { let mut err = self.dcx().struct_span_err( constraint.span, - "use of trait associated const without `#[type_const]`", + "use of trait associated const not defined as `type const`", ); - err.note("the declaration in the trait must be marked with `#[type_const]`"); + err.note("the declaration in the trait must begin with `type const` not just `const` alone"); return Err(err.emit()); } else { let err = self.dcx().span_delayed_bug( constraint.span, - "use of trait associated const without `#[type_const]`", + "use of trait associated const defined as `type const`", ); return Err(err); } @@ -1000,7 +998,9 @@ impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 't .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind)); return ControlFlow::Break(guar); } - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }); } _ => {} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 81bdfc1705a1..58c296d92c24 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,8 +1,8 @@ -use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar}; +use rustc_abi::ExternAbi; use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutCx, LayoutError, TyAndLayout}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::Span; @@ -150,8 +150,9 @@ fn is_valid_cmse_output<'tcx>( let typing_env = ty::TypingEnv::fully_monomorphized(); let layout = tcx.layout_of(typing_env.as_query_input(return_type))?; + let layout_cx = LayoutCx::new(tcx, typing_env); - if !is_valid_cmse_output_layout(layout) { + if !is_valid_cmse_output_layout(layout_cx, layout) { dcx.emit_err(errors::CmseOutputStackSpill { span: fn_decl.output.span(), abi }); } @@ -159,25 +160,20 @@ fn is_valid_cmse_output<'tcx>( } /// Returns whether the output will fit into the available registers -fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool { +fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) -> bool { let size = layout.layout.size().bytes(); if size <= 4 { return true; - } else if size > 8 { + } else if size != 8 { return false; } - // Accept scalar 64-bit types. - let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else { - return false; - }; - - let Scalar::Initialized { value, .. } = scalar else { - return false; - }; - - matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64)) + // Accept (transparently wrapped) scalar 64-bit primitives. + matches!( + layout.peel_transparent_wrappers(&cx).ty.kind(), + ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64) + ) } fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b605..00765498b061 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -451,17 +451,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { let reason = if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind { - if let hir::Node::Ty(hir::Ty { - kind: hir::TyKind::Ref(parent_lifetime, _), - .. - }) = tcx.parent_hir_node(hir_id) - && tcx.named_bound_var(parent_lifetime.hir_id).is_none() - { - // Parent lifetime must have failed to resolve. Don't emit a redundant error. - RegionInferReason::ExplicitObjectLifetime - } else { - RegionInferReason::ObjectLifetimeDefault - } + RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi()) } else { RegionInferReason::ExplicitObjectLifetime }; @@ -592,7 +582,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if span.can_be_used_for_suggestions() && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) - && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag) { self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); } @@ -750,10 +740,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_dyn_trait( &self, hir_id: hir::HirId, + span: Span, sugg: Vec<(Span, String)>, diag: &mut Diag<'_>, ) -> bool { let tcx = self.tcx(); + if span.in_derive_expansion() { + return false; + } // Look at the direct HIR parent, since we care about the relationship between // the type and the thing that directly encloses it. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d114691b25e8..975f8ab4e42f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordMap; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, pluralize, + Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, msg, pluralize, struct_span_code_err, }; use rustc_hir::def::{CtorOf, DefKind, Res}; @@ -31,7 +31,6 @@ use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, }; -use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { @@ -305,7 +304,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( assoc_ident.span, - fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, + msg!("...and changing the associated {$assoc_kind} name"), suggested_name, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index cbd0bec38d57..ff0a5a8df0fa 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -393,8 +393,7 @@ pub fn check_generic_arg_count_for_call( IsMethodCall::Yes => GenericArgPosition::MethodCall, IsMethodCall::No => GenericArgPosition::Value, }; - let has_self = generics.parent.is_none() && generics.has_self; - check_generic_arg_count(cx, def_id, seg, generics, gen_pos, has_self) + check_generic_arg_count(cx, def_id, seg, generics, gen_pos, generics.has_own_self()) } /// Checks that the correct number of generic arguments have been provided. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 867c588e302d..3f8237530892 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -28,19 +28,17 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err, }; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::DynCompatibilityViolation; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; -use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, - TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, fold_regions, + self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, Ty, TyCtxt, + TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, const_lit_matches_ty, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; @@ -105,7 +103,7 @@ pub enum RegionInferReason<'a> { /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`. ExplicitObjectLifetime, /// A trait object's lifetime when it is elided, e.g. `dyn Any`. - ObjectLifetimeDefault, + ObjectLifetimeDefault(Span), /// Generic lifetime parameter Param(&'a ty::GenericParamDef), RegionPredicate, @@ -405,6 +403,11 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { diag.span_note(impl_.self_ty.span, "not a concrete type"); } } + if self.tcx.features().min_generic_const_args() + && !self.tcx.features().opaque_generic_const_args() + { + diag.help("add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items"); + } diag.emit() } } @@ -1423,14 +1426,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(def_id, args) => { - if !find_attr!(self.tcx().get_all_attrs(def_id), AttributeKind::TypeConst(_)) { - let mut err = self.dcx().struct_span_err( - span, - "use of trait associated const without `#[type_const]`", - ); - err.note("the declaration in the trait must be marked with `#[type_const]`"); - return Err(err.emit()); - } + self.require_type_const_attribute(def_id, span)?; let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) @@ -1886,30 +1882,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_def_id: DefId, trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, - ) -> Const<'tcx> { - match self.lower_resolved_assoc_item_path( + ) -> Result, ErrorGuaranteed> { + let (item_def_id, item_args) = self.lower_resolved_assoc_item_path( span, opt_self_ty, item_def_id, trait_segment, item_segment, ty::AssocTag::Const, - ) { - Ok((item_def_id, item_args)) => { - if !find_attr!(self.tcx().get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) { - let mut err = self.dcx().struct_span_err( - span, - "use of `const` in the type system without `#[type_const]`", - ); - err.note("the declaration must be marked with `#[type_const]`"); - return Const::new_error(self.tcx(), err.emit()); - } - - let uv = ty::UnevaluatedConst::new(item_def_id, item_args); - Const::new_unevaluated(self.tcx(), uv) - } - Err(guar) => Const::new_error(self.tcx(), guar), - } + )?; + self.require_type_const_attribute(item_def_id, span)?; + let uv = ty::UnevaluatedConst::new(item_def_id, item_args); + Ok(Const::new_unevaluated(self.tcx(), uv)) } /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path. @@ -2310,7 +2294,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => ty::Const::new_bound( tcx, debruijn, - ty::BoundConst { var: ty::BoundVar::from_u32(index) }, + ty::BoundConst::new(ty::BoundVar::from_u32(index)), ), Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id), @@ -2397,8 +2381,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon), hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span), hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e), - hir::ConstArgKind::Literal(kind) => { - self.lower_const_arg_literal(&kind, ty, const_arg.span) + hir::ConstArgKind::Literal { lit, negated } => { + self.lower_const_arg_literal(&lit, negated, ty, const_arg.span) } } } @@ -2480,7 +2464,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let parent_did = tcx.parent(*def_id); (tcx.adt_def(parent_did), fn_args, parent_did) } - _ => return non_adt_or_variant_res(), + _ => { + let e = self.dcx().span_err( + span, + "complex const arguments must be placed inside of a `const` block", + ); + return Const::new_error(tcx, e); + } }; let variant_def = adt_def.variant_with_id(variant_did); @@ -2669,6 +2659,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_param(def_id, hir_id) } Res::Def(DefKind::Const, did) => { + if let Err(guar) = self.require_type_const_attribute(did, span) { + return Const::new_error(self.tcx(), guar); + } + assert_eq!(opt_self_ty, None); let [leading_segments @ .., segment] = path.segments else { bug!() }; let _ = self @@ -2719,6 +2713,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_segment, path.segments.last().unwrap(), ) + .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } Res::Def(DefKind::Static { .. }, _) => { span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") @@ -2805,10 +2800,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } #[instrument(skip(self), level = "debug")] - fn lower_const_arg_literal(&self, kind: &LitKind, ty: Ty<'tcx>, span: Span) -> Const<'tcx> { + fn lower_const_arg_literal( + &self, + kind: &LitKind, + neg: bool, + ty: Ty<'tcx>, + span: Span, + ) -> Const<'tcx> { let tcx = self.tcx(); - let input = LitToConstInput { lit: *kind, ty, neg: false }; - tcx.at(span).lit_to_const(input) + if let LitKind::Err(guar) = *kind { + return ty::Const::new_error(tcx, guar); + } + let input = LitToConstInput { lit: *kind, ty, neg }; + match tcx.at(span).lit_to_const(input) { + Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty), + None => { + let e = tcx.dcx().span_err(span, "type annotations needed for the literal"); + ty::Const::new_error(tcx, e) + } + } } #[instrument(skip(self), level = "debug")] @@ -2837,11 +2847,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { _ => None, }; - lit_input - // Allow the `ty` to be an alias type, though we cannot handle it here, we just go through - // the more expensive anon const code path. - .filter(|l| !l.ty.has_aliases()) - .map(|l| tcx.at(expr.span).lit_to_const(l)) + lit_input.and_then(|l| { + if const_lit_matches_ty(tcx, &l.lit, l.ty, l.neg) { + tcx.at(expr.span) + .lit_to_const(l) + .map(|value| ty::Const::new_value(tcx, value.valtree, value.ty)) + } else { + None + } + }) + } + + fn require_type_const_attribute( + &self, + def_id: DefId, + span: Span, + ) -> Result<(), ErrorGuaranteed> { + let tcx = self.tcx(); + if tcx.is_type_const(def_id) { + Ok(()) + } else { + let mut err = self.dcx().struct_span_err( + span, + "use of `const` in the type system not defined as `type const`", + ); + if def_id.is_local() { + let name = tcx.def_path_str(def_id); + err.span_suggestion( + tcx.def_span(def_id).shrink_to_lo(), + format!("add `type` before `const` for `{name}`"), + format!("type "), + Applicability::MaybeIncorrect, + ); + } else { + err.note("only consts marked defined as `type const` may be used in types"); + } + Err(err.emit()) + } } fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { @@ -3196,8 +3238,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { #[instrument(level = "trace", skip(self, generate_err))] fn validate_late_bound_regions<'cx>( &'cx self, - constrained_regions: FxIndexSet, - referenced_regions: FxIndexSet, + constrained_regions: FxIndexSet>, + referenced_regions: FxIndexSet>, generate_err: impl Fn(&str) -> Diag<'cx>, ) { for br in referenced_regions.difference(&constrained_regions) { diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index f879153c5765..08da8d19344d 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -51,12 +51,12 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( struct HirWfCheck<'tcx> { tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, - cause: Option>, - cause_depth: usize, + cause: Option> = None, + cause_depth: usize = 0, icx: ItemCtxt<'tcx>, def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, - depth: usize, + depth: usize = 0, } impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { @@ -124,16 +124,8 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( } } - let mut visitor = HirWfCheck { - tcx, - predicate, - cause: None, - cause_depth: 0, - icx, - def_id, - param_env: tcx.param_env(def_id.to_def_id()), - depth: 0, - }; + let param_env = tcx.param_env(def_id.to_def_id()); + let mut visitor = HirWfCheck { tcx, predicate, icx, def_id, param_env, .. }; // Get the starting `hir::Ty` using our `WellFormedLoc`. // We will walk 'into' this type to try to find @@ -147,7 +139,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( }, hir::Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(), - hir::TraitItemKind::Const(ty, _) => vec![ty], + hir::TraitItemKind::Const(ty, _, _) => vec![ty], ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 3a4d894239fc..70209993a510 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -56,7 +56,8 @@ This API is completely unstable and subject to change. */ // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] +#![feature(default_field_values)] #![feature(gen_blocks)] #![feature(if_let_guard)] #![feature(iter_intersperse)] @@ -84,12 +85,9 @@ mod variance; pub use errors::NoVariantNamed; use rustc_abi::{CVariadicStatus, ExternAbi}; -use rustc_hir::attrs::AttributeKind; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; -use rustc_hir::{ - find_attr, {self as hir}, -}; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; @@ -101,8 +99,6 @@ use rustc_trait_selection::traits; pub use crate::collect::suggest_impl_trait; use crate::hir_ty_lowering::HirTyLowerer; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) { if !decl.c_variadic { // Not even a variadic function. @@ -237,7 +233,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !find_attr!(tcx.get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) => + && !tcx.is_type_const(item_def_id) => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs index 4233896c3720..cf770a2561db 100644 --- a/compiler/rustc_hir_analysis/src/outlives/dump.rs +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -1,10 +1,12 @@ +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::sym; pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { for id in tcx.hir_free_items() { - if !tcx.has_attr(id.owner_id, sym::rustc_outlives) { + if !find_attr!(tcx.get_all_attrs(id.owner_id), AttributeKind::RustcOutlives) { continue; } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e0e9fe775853..fc6cc4e67251 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -937,7 +937,7 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo()); self.print_attrs(self.attrs(ti.hir_id())); match ti.kind { - hir::TraitItemKind::Const(ty, default) => { + hir::TraitItemKind::Const(ty, default, _) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { @@ -1158,9 +1158,12 @@ impl<'a> State<'a> { ConstArgKind::Anon(anon) => self.print_anon_const(anon), ConstArgKind::Error(_) => self.word("/*ERROR*/"), ConstArgKind::Infer(..) => self.word("_"), - ConstArgKind::Literal(node) => { + ConstArgKind::Literal { lit, negated } => { + if *negated { + self.word("-"); + } let span = const_arg.span; - self.print_literal(&Spanned { span, node: *node }) + self.print_literal(&Spanned { span, node: *lit }) } } } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 246134665174..43db09b0eab8 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl deleted file mode 100644 index 0c4b1f891ead..000000000000 --- a/compiler/rustc_hir_typeck/messages.ftl +++ /dev/null @@ -1,315 +0,0 @@ -hir_typeck_abi_cannot_be_called = - functions with the {$abi} ABI cannot be called - .note = an `extern {$abi}` function can only be called using inline assembly - -hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function - -hir_typeck_add_return_type_add = try adding a return type - -hir_typeck_add_return_type_missing_here = a return type might be missing here - -hir_typeck_address_of_temporary_taken = cannot take address of a temporary - .label = temporary value - -hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where - .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new - -hir_typeck_as_deref_suggestion = consider using `as_deref` here -hir_typeck_base_expression_double_dot = base expression required after `..` -hir_typeck_base_expression_double_dot_add_expr = add a base expression here -hir_typeck_base_expression_double_dot_enable_default_field_values = - add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields -hir_typeck_base_expression_double_dot_remove = remove the `..` as all the fields are already present - -hir_typeck_break_inside_closure = - `{$name}` inside of a closure - .label = cannot `{$name}` inside of a closure - .closure_label = enclosing closure - -hir_typeck_break_inside_coroutine = - `{$name}` inside `{$kind}` {$source} - .label = cannot `{$name}` inside `{$kind}` {$source} - .coroutine_label = enclosing `{$kind}` {$source} - -hir_typeck_break_non_loop = - `break` with value from a `{$kind}` loop - .label = can only break with a value inside `loop` or breakable block - .label2 = you can't `break` with a value in a `{$kind}` loop - .suggestion = use `break` on its own without a value inside this `{$kind}` loop - .break_expr_suggestion = alternatively, you might have meant to use the available loop label - - -hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty -> - [NONE] {""} - [implement] , perhaps you need to implement it - *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it -} - -hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool` - .suggestion = compare with zero instead - .help = compare with zero instead - .label = unsupported cast - -hir_typeck_cant_dereference = type `{$ty}` cannot be dereferenced -hir_typeck_cant_dereference_label = can't be dereferenced - -hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop` - -hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}` - .teach_help = Thin pointers are "simple" pointers: they are purely a reference to a - memory address. - - Wide pointers are pointers referencing "Dynamically Sized Types" (also - called DST). DST don't have a statically known size, therefore they can - only exist behind some kind of pointers that contain additional - information. Slices and trait objects are DSTs. In the case of slices, - the additional information the wide pointer holds is their size. - - To fix this error, don't try to cast directly between thin and wide - pointers. - - For more information about casts, take a look at The Book: - https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions", - -hir_typeck_cast_unknown_pointer = cannot cast {$to -> - [true] to - *[false] from - } a pointer of an unknown kind - .label_to = needs more type information - .note = the type information given here is insufficient to check whether the pointer cast is valid - .label_from = the type information given here is insufficient to check whether the pointer cast is valid - -hir_typeck_const_continue_bad_label = - `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` - -hir_typeck_continue_labeled_block = - `continue` pointing to a labeled block - .label = labeled blocks cannot be `continue`'d - .block_label = labeled block the `continue` points to - - -hir_typeck_convert_to_str = try converting the passed type into a `&str` - -hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `{$expected}` - -hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private - -hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()` - .note = in edition 2024, the requirement `{$obligation}` will fail - .help = specify the types explicitly - -hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty` - -hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}` -hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}` - -hir_typeck_expected_default_return_type = expected `()` because of default return type - -hir_typeck_expected_return_type = expected `{$expected}` because of return type - -hir_typeck_explicit_destructor = explicit use of destructor method - .label = explicit destructor calls not allowed - .suggestion = consider using `drop` function - -hir_typeck_field_multiply_specified_in_initializer = - field `{$ident}` specified more than once - .label = used more than once - .previous_use_label = first use of `{$ident}` - -hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function - .suggestion = use a function pointer instead - .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI - .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html - -hir_typeck_fru_expr = this expression does not end in a comma... -hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax -hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression -hir_typeck_fru_suggestion = - to set the remaining fields{$expr -> - [NONE]{""} - *[other] {" "}from `{$expr}` - }, separate the last named field with a comma - -hir_typeck_functional_record_update_on_non_struct = - functional record update syntax requires a struct - -hir_typeck_gpu_kernel_abi_cannot_be_called = - functions with the "gpu-kernel" ABI cannot be called - .note = an `extern "gpu-kernel"` function must be launched on the GPU by the runtime - -hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` -hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` - -hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide -> - [true] is - *[false] may be - } wide -hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata} -hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` - -hir_typeck_invalid_callee = expected function, found {$found} -hir_typeck_invalid_defined = `{$path}` defined here -hir_typeck_invalid_defined_kind = {$kind} `{$path}` defined here -hir_typeck_invalid_fn_defined = `{$func}` defined here returns `{$ty}` -hir_typeck_invalid_local = `{$local_name}` has type `{$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 - .help = if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead - -hir_typeck_lossy_provenance_ptr2int = - under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}` - .suggestion = use `.addr()` to obtain the address of a pointer - .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead - -hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty}` - -hir_typeck_naked_asm_outside_naked_fn = - the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]` - -hir_typeck_naked_functions_asm_block = - naked functions must contain a single `naked_asm!` invocation - .label_multiple_asm = multiple `naked_asm!` invocations are not allowed in naked functions - .label_non_asm = not allowed in naked functions - -hir_typeck_naked_functions_must_naked_asm = - the `asm!` macro is not allowed in naked functions - .label = consider using the `naked_asm!` macro instead - -hir_typeck_never_type_fallback_flowing_into_unsafe_call = never type fallback affects this call to an `unsafe` function - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_deref = never type fallback affects this raw pointer dereference - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_method = never type fallback affects this call to an `unsafe` method - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback affects this `unsafe` function - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access - .help = specify the type explicitly - -hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method -> - [true] {""} - *[other] {" "}in the current scope -} - -hir_typeck_no_field_on_type = no field `{$field}` on type `{$ty}` - -hir_typeck_no_field_on_variant = no field named `{$field}` on enum variant `{$container}::{$ident}` -hir_typeck_no_field_on_variant_enum = this enum variant... -hir_typeck_no_field_on_variant_field = ...does not have this field - -hir_typeck_no_patterns = - patterns not allowed in naked function parameters - -hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}` - -hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide - -hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}` -hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}` -hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}` - -hir_typeck_outside_loop = - `{$name}` outside of a loop{$is_break -> - [true] {" or labeled block"} - *[false] {""} - } - .label = cannot `{$name}` outside of a loop{$is_break -> - [true] {" or labeled block"} - *[false] {""} - } - -hir_typeck_outside_loop_suggestion = consider labeling this block to be able to break within it - - -hir_typeck_params_not_allowed = - referencing function parameters is not allowed in naked functions - .help = follow the calling convention in asm block to use parameters - -hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function - .suggestion = cast the value to `{$cast_ty}` - .teach_help = certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's numeric promotion rules - -hir_typeck_project_on_non_pin_project_type = cannot project on type that is not `#[pin_v2]` - .note = type defined here - .suggestion = add `#[pin_v2]` here - -hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len -> - [1] auto trait {$traits} - *[other] auto traits {$traits} -} to dyn bound via pointer cast - .note = this could allow UB elsewhere - .help = use `transmute` if you're sure this is sound - .label = unsupported cast - -hir_typeck_register_type_unstable = - type `{$ty}` cannot be used with this register class in stable - -hir_typeck_remove_semi_for_coerce = you might have meant to return the `match` expression -hir_typeck_remove_semi_for_coerce_expr = this could be implicitly returned but it is a statement, not a tail expression -hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this return type -hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it -hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon - -hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr} - -hir_typeck_return_stmt_outside_of_fn_body = - {$statement_kind} statement outside of function body - .encl_body_label = the {$statement_kind} is part of this body... - .encl_fn_label = ...not the enclosing function body - -hir_typeck_rpit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions - -hir_typeck_rpit_change_return_type = you could change the return type to be a boxed trait object - -hir_typeck_rustcall_incorrect_args = - functions with the "rust-call" ABI must take a single non-self tuple argument - -hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from outer item - .label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference - .suggestion = replace `Self` with the actual type - -hir_typeck_self_ctor_from_outer_item_inner_item = `Self` used in this inner item - -hir_typeck_slicing_suggestion = consider slicing here - -hir_typeck_struct_expr_non_exhaustive = - cannot create non-exhaustive {$what} using struct expression - -hir_typeck_suggest_boxing_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 - -hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new` - -hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead - -hir_typeck_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits} - -hir_typeck_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item - -hir_typeck_supertrait_item_shadower = item from `{$subtrait}` shadows a supertrait item - -hir_typeck_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait - -hir_typeck_trivial_cast = trivial {$numeric -> - [true] numeric cast - *[false] cast - }: `{$expr_ty}` as `{$cast_ty}` - .help = cast can be replaced by coercion; this might require a temporary variable - -hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns - -hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field - -hir_typeck_unlabeled_cf_in_while_condition = - `break` or `continue` with no label in the condition of a `while` loop - .label = unlabeled `{$cf_type}` in the condition of a `while` loop - -hir_typeck_unlabeled_in_labeled_block = - unlabeled `{$cf_type}` inside of a labeled block - .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label -hir_typeck_use_is_empty = - consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything - -hir_typeck_yield_expr_outside_of_coroutine = - yield expression outside of coroutine literal diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 4fe77278706e..f7700179d2a3 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; use rustc_infer::traits::PredicateObligations; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref}; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -45,22 +45,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty())); let steps: Vec<_> = steps .iter() - .map(|&(source, kind)| { - if let AutoderefKind::Overloaded = kind { - self.try_overloaded_deref(autoderef.span(), source).and_then( - |InferOk { value: method, obligations: o }| { + .map(|&(source, kind)| match kind { + AutoderefKind::Overloaded => { + self.try_overloaded_deref(autoderef.span(), source) + .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); // FIXME: we should assert the sig is &T here... there's no reason for this to be fallible. if let ty::Ref(_, _, mutbl) = *method.sig.output().kind() { - Some(OverloadedDeref { mutbl, span: autoderef.span() }) + Some(DerefAdjustKind::Overloaded(OverloadedDeref { + mutbl, + span: autoderef.span(), + })) } else { None } - }, - ) - } else { - None + }) + .unwrap_or(DerefAdjustKind::Builtin) } + AutoderefKind::Builtin => DerefAdjustKind::Builtin, }) .zip_eq(targets) .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a26b44e79dc7..7ad0b85ee53f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -2,10 +2,11 @@ use std::iter; use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey, msg}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, LangItem}; +use rustc_hir::{self as hir, HirId, LangItem, find_attr}; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; @@ -25,8 +26,8 @@ use tracing::{debug, instrument}; use super::method::MethodCallee; use super::method::probe::ProbeScope; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; +use crate::errors; use crate::method::TreatNotYetDefinedOpaques; -use crate::{errors, fluent_generated}; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -526,7 +527,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `#[rustc_evaluate_where_clauses]` trigger special output // to let us test the trait evaluation system. if self.has_rustc_attrs - && self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) + && find_attr!( + self.tcx.get_all_attrs(def_id), + AttributeKind::RustcEvaluateWhereClauses + ) { let predicates = self.tcx.predicates_of(def_id); let predicates = predicates.instantiate(self.tcx, args); @@ -832,12 +836,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (Some((_, kind, path)), _) => { err.arg("kind", kind); err.arg("path", path); - Some(fluent_generated::hir_typeck_invalid_defined_kind) + Some(msg!("{$kind} `{$path}` defined here")) } (_, Some(hir::QPath::Resolved(_, path))) => { self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| { err.arg("func", p); - fluent_generated::hir_typeck_invalid_fn_defined + msg!("`{$func}` defined here returns `{$ty}`") }) } _ => { @@ -846,15 +850,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type definitions themselves, but rather variables *of* that type. Res::Local(hir_id) => { err.arg("local_name", self.tcx.hir_name(hir_id)); - Some(fluent_generated::hir_typeck_invalid_local) + Some(msg!("`{$local_name}` has type `{$ty}`")) } Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { err.arg("path", self.tcx.def_path_str(def_id)); - Some(fluent_generated::hir_typeck_invalid_defined) + Some(msg!("`{$path}` defined here")) } _ => { err.arg("path", callee_ty); - Some(fluent_generated::hir_typeck_invalid_defined) + Some(msg!("`{$path}` defined here")) } } } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 3f13a102684e..b5094d736dd5 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -572,6 +572,17 @@ impl<'a, 'tcx> CastCheck<'tcx> { let metadata = known_metadata.unwrap_or("type-specific metadata"); let known_wide = known_metadata.is_some(); let span = self.cast_span; + let param_note = (!known_wide) + .then(|| match cast_ty.kind() { + ty::RawPtr(pointee, _) => match pointee.kind() { + ty::Param(param) => { + Some(errors::IntToWideParamNote { param: param.name }) + } + _ => None, + }, + _ => None, + }) + .flatten(); fcx.dcx().emit_err(errors::IntToWide { span, metadata, @@ -579,6 +590,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { cast_ty, expr_if_nightly, known_wide, + param_note, }); } CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => { diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 52ea6cdeaa0e..88d2e80f1521 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -50,7 +50,8 @@ use rustc_infer::traits::{ }; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, + Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, + PointerCoercion, }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; @@ -595,7 +596,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No); Some(( - Adjustment { kind: Adjust::Deref(None), target: ty_a }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b), @@ -606,7 +607,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { coerce_mutbls(mt_a, mt_b)?; Some(( - Adjustment { kind: Adjust::Deref(None), target: ty_a }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)), target: Ty::new_ptr(self.tcx, ty_a, mt_b), @@ -643,7 +644,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { .infcx .visit_proof_tree( Goal::new(self.tcx, self.param_env, pred), - &mut CoerceVisitor { fcx: self.fcx, span: self.cause.span }, + &mut CoerceVisitor { fcx: self.fcx, span: self.cause.span, errored: false }, ) .is_break() { @@ -936,7 +937,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( a_raw, b, - [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + [Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: mt_a.ty }], Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), ForceLeakCheck::No, ) @@ -1365,6 +1366,7 @@ pub fn can_coerce<'tcx>( /// - WARNING: I don't believe this final type is guaranteed to be /// related to your initial `expected_ty` in any particular way, /// although it will typically be a subtype, so you should check it. +/// Check the note below for more details. /// - Invoking `complete()` may cause us to go and adjust the "adjustments" on /// previously coerced expressions. /// @@ -1378,6 +1380,28 @@ pub fn can_coerce<'tcx>( /// } /// let final_ty = coerce.complete(fcx); /// ``` +/// +/// NOTE: Why does the `expected_ty` participate in the LUB? +/// When coercing, each branch should use the following expectations for type inference: +/// - The branch can be coerced to the expected type of the match/if/whatever. +/// - The branch can be coercion lub'd with the types of the previous branches. +/// Ideally we'd have some sort of `Expectation::ParticipatesInCoerceLub(ongoing_lub_ty, final_ty)`, +/// but adding and using this feels very challenging. +/// What we instead do is to use the expected type of the match/if/whatever as +/// the initial coercion lub. This allows us to use the lub of "expected type of match" with +/// "types from previous branches" as the coercion target, which can contains both expectations. +/// +/// Two concerns with this approach: +/// - We may have incompatible `final_ty` if that lub is different from the expected +/// type of the match. However, in this case coercing the final type of the +/// `CoerceMany` to its expected type would have error'd anyways, so we don't care. +/// - We may constrain the `expected_ty` too early. For some branches with +/// type `a` and `b`, we end up with `(a lub expected_ty) lub b` instead of +/// `(a lub b) lub expected_ty`. They should be the same type. However, +/// `a lub expected_ty` may constrain inference variables in `expected_ty`. +/// In this case the difference does matter and we get actually incorrect results. +/// FIXME: Ideally we'd compute the final type without unnecessarily constraining +/// the expected type of the match when computing the types of its branches. pub(crate) struct CoerceMany<'tcx> { expected_ty: Ty<'tcx>, final_ty: Option>, @@ -1937,6 +1961,10 @@ impl<'tcx> CoerceMany<'tcx> { struct CoerceVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, + /// Whether the coercion is impossible. If so we sometimes still try to + /// coerce in these cases to emit better errors. This changes the behavior + /// when hitting the recursion limit. + errored: bool, } impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> { @@ -1963,6 +1991,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> { // If we prove the `Unsize` or `CoerceUnsized` goal, continue recursing. Ok(Certainty::Yes) => ControlFlow::Continue(()), Err(NoSolution) => { + self.errored = true; // Even if we find no solution, continue recursing if we find a single candidate // for which we're shallowly certain it holds to get the right error source. if let [only_candidate] = &goal.candidates()[..] @@ -1995,4 +2024,15 @@ impl<'tcx> ProofTreeVisitor<'tcx> for CoerceVisitor<'_, 'tcx> { } } } + + fn on_recursion_limit(&mut self) -> Self::Result { + if self.errored { + // This prevents accidentally committing unfulfilled unsized coercions while trying to + // find the error source for diagnostics. + // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/266. + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 3f214b4d2fcc..68cbfa728058 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,7 +1,8 @@ use rustc_errors::{Applicability, Diag, MultiSpan, listify}; -use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::Res; use rustc_hir::intravisit::Visitor; +use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::bug; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -605,6 +606,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { parent_id = self.tcx.parent_hir_id(*hir_id); parent } + hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => { + parent_id = self.tcx.parent_hir_id(*hir_id); + parent + } + hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => { + parent_id = self.tcx.parent_hir_id(*hir_id); + parent + } hir::Node::Block(_) => { parent_id = self.tcx.parent_hir_id(parent_id); parent @@ -1073,19 +1082,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id, |m| { self.has_only_self_parameter(m) - && self - .tcx - // This special internal attribute is used to permit - // "identity-like" conversion methods to be suggested here. - // - // FIXME (#46459 and #46460): ideally - // `std::convert::Into::into` and `std::borrow:ToOwned` would - // also be `#[rustc_conversion_suggestion]`, if not for - // method-probing false-positives and -negatives (respectively). - // - // FIXME? Other potential candidate methods: `as_ref` and - // `as_mut`? - .has_attr(m.def_id, sym::rustc_conversion_suggestion) + // This special internal attribute is used to permit + // "identity-like" conversion methods to be suggested here. + // + // FIXME (#46459 and #46460): ideally + // `std::convert::Into::into` and `std::borrow:ToOwned` would + // also be `#[rustc_conversion_suggestion]`, if not for + // method-probing false-positives and -negatives (respectively). + // + // FIXME? Other potential candidate methods: `as_ref` and + // `as_mut`? + && find_attr!(self.tcx.get_all_attrs(m.def_id), AttributeKind::RustcConversionSuggestion) }, ); diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 0cf7f09e9376..e0467f4dc6ed 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -7,7 +7,7 @@ use rustc_ast::{AssignOpKind, Label}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir as hir; use rustc_hir::ExprKind; @@ -17,15 +17,15 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; -use crate::{FnCtxt, fluent_generated as fluent}; +use crate::FnCtxt; #[derive(Diagnostic)] -#[diag(hir_typeck_base_expression_double_dot, code = E0797)] +#[diag("base expression required after `..`", code = E0797)] pub(crate) struct BaseExpressionDoubleDot { #[primary_span] pub span: Span, #[suggestion( - hir_typeck_base_expression_double_dot_enable_default_field_values, + "add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields", code = "#![feature(default_field_values)]\n", applicability = "machine-applicable", style = "verbose" @@ -39,7 +39,7 @@ pub(crate) struct BaseExpressionDoubleDot { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_base_expression_double_dot_remove, + "remove the `..` as all the fields are already present", code = "", applicability = "machine-applicable", style = "verbose" @@ -51,7 +51,7 @@ pub(crate) struct BaseExpressionDoubleDotRemove { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_base_expression_double_dot_add_expr, + "add a base expression here", code = "/* expr */", applicability = "has-placeholders", style = "verbose" @@ -62,24 +62,24 @@ pub(crate) struct BaseExpressionDoubleDotAddExpr { } #[derive(Diagnostic)] -#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] +#[diag("field `{$ident}` specified more than once", code = E0062)] pub(crate) struct FieldMultiplySpecifiedInInitializer { #[primary_span] - #[label] + #[label("used more than once")] pub span: Span, - #[label(hir_typeck_previous_use_label)] + #[label("first use of `{$ident}`")] pub prev_span: Span, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)] +#[diag("{$statement_kind} statement outside of function body", code = E0572)] pub(crate) struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, - #[label(hir_typeck_encl_body_label)] + #[label("the {$statement_kind} is part of this body...")] pub encl_body_span: Option, - #[label(hir_typeck_encl_fn_label)] + #[label("...not the enclosing function body")] pub encl_fn_span: Option, pub statement_kind: ReturnLikeStatementKind, } @@ -102,21 +102,21 @@ impl IntoDiagArg for ReturnLikeStatementKind { } #[derive(Diagnostic)] -#[diag(hir_typeck_rustcall_incorrect_args)] +#[diag("functions with the \"rust-call\" ABI must take a single non-self tuple argument")] pub(crate) struct RustCallIncorrectArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)] +#[diag("yield expression outside of coroutine literal", code = E0627)] pub(crate) struct YieldExprOutsideOfCoroutine { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)] +#[diag("cannot create non-exhaustive {$what} using struct expression", code = E0639)] pub(crate) struct StructExprNonExhaustive { #[primary_span] pub span: Span, @@ -124,24 +124,24 @@ pub(crate) struct StructExprNonExhaustive { } #[derive(Diagnostic)] -#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] +#[diag("functional record update syntax requires a struct", code = E0436)] pub(crate) struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_address_of_temporary_taken, code = E0745)] +#[diag("cannot take address of a temporary", code = E0745)] pub(crate) struct AddressOfTemporaryTaken { #[primary_span] - #[label] + #[label("temporary value")] pub span: Span, } #[derive(Subdiagnostic)] pub(crate) enum AddReturnTypeSuggestion { #[suggestion( - hir_typeck_add_return_type_add, + "try adding a return type", code = " -> {found}", applicability = "machine-applicable" )] @@ -151,7 +151,7 @@ pub(crate) enum AddReturnTypeSuggestion { found: String, }, #[suggestion( - hir_typeck_add_return_type_missing_here, + "a return type might be missing here", code = " -> _", applicability = "has-placeholders" )] @@ -163,12 +163,12 @@ pub(crate) enum AddReturnTypeSuggestion { #[derive(Subdiagnostic)] pub(crate) enum ExpectedReturnTypeLabel<'tcx> { - #[label(hir_typeck_expected_default_return_type)] + #[label("expected `()` because of default return type")] Unit { #[primary_span] span: Span, }, - #[label(hir_typeck_expected_return_type)] + #[label("expected `{$expected}` because of return type")] Other { #[primary_span] span: Span, @@ -177,10 +177,10 @@ pub(crate) enum ExpectedReturnTypeLabel<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_explicit_destructor, code = E0040)] +#[diag("explicit use of destructor method", code = E0040)] pub(crate) struct ExplicitDestructorCall { #[primary_span] - #[label] + #[label("explicit destructor calls not allowed")] pub span: Span, #[subdiagnostic] pub sugg: ExplicitDestructorCallSugg, @@ -188,9 +188,13 @@ pub(crate) struct ExplicitDestructorCall { #[derive(Subdiagnostic)] pub(crate) enum ExplicitDestructorCallSugg { - #[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")] + #[suggestion( + "consider using `drop` function", + code = "drop", + applicability = "maybe-incorrect" + )] Empty(#[primary_span] Span), - #[multipart_suggestion(hir_typeck_suggestion, style = "short")] + #[multipart_suggestion("consider using `drop` function", style = "short")] Snippet { #[suggestion_part(code = "drop(")] lo: Span, @@ -200,10 +204,10 @@ pub(crate) enum ExplicitDestructorCallSugg { } #[derive(Diagnostic)] -#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)] +#[diag("can't call method `{$method_name}` on type `{$ty}`", code = E0689)] pub(crate) struct MissingParenthesesInRange<'tcx> { #[primary_span] - #[label(hir_typeck_missing_parentheses_in_range)] + #[label("can't call method `{$method_name}` on type `{$ty}`")] pub span: Span, pub ty: Ty<'tcx>, pub method_name: String, @@ -213,32 +217,32 @@ pub(crate) struct MissingParenthesesInRange<'tcx> { #[derive(LintDiagnostic)] pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this call to an `unsafe` function")] Call { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_method)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this call to an `unsafe` method")] Method { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_path)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this `unsafe` function")] Path { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_union_field)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this union access")] UnionField { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_deref)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this raw pointer dereference")] Deref { #[subdiagnostic] sugg: SuggestAnnotations, @@ -246,10 +250,10 @@ pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { } #[derive(LintDiagnostic)] -#[help] -#[diag(hir_typeck_dependency_on_unit_never_type_fallback)] +#[help("specify the types explicitly")] +#[diag("this function depends on never type fallback being `()`")] pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> { - #[note] + #[note("in edition 2024, the requirement `{$obligation}` will fail")] pub obligation_span: Span, pub obligation: ty::Predicate<'tcx>, #[subdiagnostic] @@ -310,7 +314,7 @@ impl Subdiagnostic for SuggestAnnotations { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_add_missing_parentheses_in_range, + "you must surround the range in parentheses to call its `{$func_name}` function", style = "verbose", applicability = "maybe-incorrect" )] @@ -337,17 +341,31 @@ impl Subdiagnostic for TypeMismatchFruTypo { // Only explain that `a ..b` is a range if it's split up if self.expr_span.between(self.fru_span).is_empty() { - diag.span_note(self.expr_span.to(self.fru_span), fluent::hir_typeck_fru_note); + diag.span_note( + self.expr_span.to(self.fru_span), + msg!("this expression may have been misinterpreted as a `..` range expression"), + ); } else { let mut multispan: MultiSpan = vec![self.expr_span, self.fru_span].into(); - multispan.push_span_label(self.expr_span, fluent::hir_typeck_fru_expr); - multispan.push_span_label(self.fru_span, fluent::hir_typeck_fru_expr2); - diag.span_note(multispan, fluent::hir_typeck_fru_note); + multispan.push_span_label( + self.expr_span, + msg!("this expression does not end in a comma..."), + ); + multispan.push_span_label(self.fru_span, msg!("... so this is interpreted as a `..` range expression, instead of functional record update syntax")); + diag.span_note( + multispan, + msg!("this expression may have been misinterpreted as a `..` range expression"), + ); } diag.span_suggestion( self.expr_span.shrink_to_hi(), - fluent::hir_typeck_fru_suggestion, + msg!( + "to set the remaining fields{$expr -> + [NONE]{\"\"} + *[other] {\" \"}from `{$expr}` + }, separate the last named field with a comma" + ), ", ", Applicability::MaybeIncorrect, ); @@ -355,8 +373,10 @@ impl Subdiagnostic for TypeMismatchFruTypo { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_lossy_provenance_int2ptr)] -#[help] +#[diag("strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`")] +#[help( + "if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead" +)] pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -365,19 +385,25 @@ pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_ptr_cast_add_auto_to_object, code = E0804)] -#[note] -#[help] +#[diag("cannot add {$traits_len -> + [1] auto trait {$traits} + *[other] auto traits {$traits} +} to dyn bound via pointer cast", code = E0804)] +#[note("this could allow UB elsewhere")] +#[help("use `transmute` if you're sure this is sound")] pub(crate) struct PtrCastAddAutoToObject { #[primary_span] - #[label] + #[label("unsupported cast")] pub span: Span, pub traits_len: usize, pub traits: DiagSymbolList, } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")] +#[multipart_suggestion( + "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address", + applicability = "has-placeholders" +)] pub(crate) struct LossyProvenanceInt2PtrSuggestion { #[suggestion_part(code = "(...).with_addr(")] pub lo: Span, @@ -386,8 +412,12 @@ pub(crate) struct LossyProvenanceInt2PtrSuggestion { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_lossy_provenance_ptr2int)] -#[help] +#[diag( + "under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`" +)] +#[help( + "if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead" +)] pub(crate) struct LossyProvenancePtr2Int<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -397,7 +427,10 @@ pub(crate) struct LossyProvenancePtr2Int<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { - #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] NeedsParensCast { #[suggestion_part(code = "(")] expr_span: Span, @@ -405,7 +438,10 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, cast_ty: Ty<'tcx>, }, - #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] NeedsParens { #[suggestion_part(code = "(")] expr_span: Span, @@ -413,7 +449,7 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, }, #[suggestion( - hir_typeck_suggestion, + "use `.addr()` to obtain the address of a pointer", code = ".addr() as {cast_ty}", applicability = "maybe-incorrect" )] @@ -422,7 +458,11 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, cast_ty: Ty<'tcx>, }, - #[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")] + #[suggestion( + "use `.addr()` to obtain the address of a pointer", + code = ".addr()", + applicability = "maybe-incorrect" + )] Other { #[primary_span] cast_span: Span, @@ -431,11 +471,11 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum HelpUseLatestEdition { - #[help(hir_typeck_help_set_edition_cargo)] - #[note(hir_typeck_note_edition_guide)] + #[help("set `edition = \"{$edition}\"` in `Cargo.toml`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Cargo { edition: Edition }, - #[help(hir_typeck_help_set_edition_standalone)] - #[note(hir_typeck_note_edition_guide)] + #[help("pass `--edition {$edition}` to `rustc`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Standalone { edition: Edition }, } @@ -451,7 +491,7 @@ impl HelpUseLatestEdition { } #[derive(Diagnostic)] -#[diag(hir_typeck_no_field_on_type, code = E0609)] +#[diag("no field `{$field}` on type `{$ty}`", code = E0609)] pub(crate) struct NoFieldOnType<'tcx> { #[primary_span] pub(crate) span: Span, @@ -460,33 +500,33 @@ pub(crate) struct NoFieldOnType<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_no_field_on_variant, code = E0609)] +#[diag("no field named `{$field}` on enum variant `{$container}::{$ident}`", code = E0609)] pub(crate) struct NoFieldOnVariant<'tcx> { #[primary_span] pub(crate) span: Span, pub(crate) container: Ty<'tcx>, pub(crate) ident: Ident, pub(crate) field: Ident, - #[label(hir_typeck_no_field_on_variant_enum)] + #[label("this enum variant...")] pub(crate) enum_span: Span, - #[label(hir_typeck_no_field_on_variant_field)] + #[label("...does not have this field")] pub(crate) field_span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_cant_dereference, code = E0614)] +#[diag("type `{$ty}` cannot be dereferenced", code = E0614)] pub(crate) struct CantDereference<'tcx> { #[primary_span] - #[label(hir_typeck_cant_dereference_label)] + #[label("can't be dereferenced")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_typeck_expected_array_or_slice, code = E0529)] +#[diag("expected an array or slice, found `{$ty}`", code = E0529)] pub(crate) struct ExpectedArrayOrSlice<'tcx> { #[primary_span] - #[label(hir_typeck_expected_array_or_slice_label)] + #[label("pattern cannot match with input type `{$ty}`")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, pub(crate) slice_pat_semantics: bool, @@ -498,7 +538,7 @@ pub(crate) struct ExpectedArrayOrSlice<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_as_deref_suggestion, + "consider using `as_deref` here", code = ".as_deref()", style = "verbose", applicability = "maybe-incorrect" @@ -510,7 +550,7 @@ pub(crate) struct AsDerefSuggestion { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_slicing_suggestion, + "consider slicing here", code = "[..]", style = "verbose", applicability = "maybe-incorrect" @@ -521,7 +561,7 @@ pub(crate) struct SlicingSuggestion { } #[derive(Diagnostic)] -#[diag(hir_typeck_invalid_callee, code = E0618)] +#[diag("expected function, found {$found}", code = E0618)] pub(crate) struct InvalidCallee<'tcx> { #[primary_span] pub span: Span, @@ -530,23 +570,36 @@ pub(crate) struct InvalidCallee<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_int_to_fat, code = E0606)] +#[diag("cannot cast `{$expr_ty}` to a pointer that {$known_wide -> + [true] is + *[false] may be +} wide", code = E0606)] pub(crate) struct IntToWide<'tcx> { #[primary_span] - #[label(hir_typeck_int_to_fat_label)] + #[label("creating a `{$cast_ty}` requires both an address and {$metadata}")] pub span: Span, pub metadata: &'tcx str, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, - #[label(hir_typeck_int_to_fat_label_nightly)] + #[label( + "consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`" + )] pub expr_if_nightly: Option, pub known_wide: bool, + #[subdiagnostic] + pub param_note: Option, +} + +#[derive(Subdiagnostic)] +#[note("the type parameter `{$param}` is not known to be `Sized`, so this pointer may be wide")] +pub(crate) struct IntToWideParamNote { + pub param: Symbol, } #[derive(Subdiagnostic)] pub(crate) enum OptionResultRefMismatch { #[suggestion( - hir_typeck_option_result_copied, + "use `{$def_path}::copied` to copy the value inside the `{$def_path}`", code = ".copied()", style = "verbose", applicability = "machine-applicable" @@ -557,7 +610,7 @@ pub(crate) enum OptionResultRefMismatch { def_path: String, }, #[suggestion( - hir_typeck_option_result_cloned, + "use `{$def_path}::cloned` to clone the value inside the `{$def_path}`", code = ".cloned()", style = "verbose", applicability = "machine-applicable" @@ -569,7 +622,7 @@ pub(crate) enum OptionResultRefMismatch { }, // FIXME: #114050 // #[suggestion( - // hir_typeck_option_result_asref, + // "use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`", // code = ".as_ref()", // style = "verbose", // applicability = "machine-applicable" @@ -592,14 +645,21 @@ pub(crate) struct RemoveSemiForCoerce { impl Subdiagnostic for RemoveSemiForCoerce { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multispan: MultiSpan = self.semi.into(); - multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); - multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); - multispan.push_span_label(self.semi, fluent::hir_typeck_remove_semi_for_coerce_semi); - diag.span_note(multispan, fluent::hir_typeck_remove_semi_for_coerce); + multispan.push_span_label( + self.expr, + msg!("this could be implicitly returned but it is a statement, not a tail expression"), + ); + multispan + .push_span_label(self.ret, msg!("the `match` arms can conform to this return type")); + multispan.push_span_label( + self.semi, + msg!("the `match` is a statement because of this semicolon, consider removing it"), + ); + diag.span_note(multispan, msg!("you might have meant to return the `match` expression")); diag.tool_only_span_suggestion( self.semi, - fluent::hir_typeck_remove_semi_for_coerce_suggestion, + msg!("remove this semicolon"), "", Applicability::MaybeIncorrect, ); @@ -607,14 +667,14 @@ impl Subdiagnostic for RemoveSemiForCoerce { } #[derive(Diagnostic)] -#[diag(hir_typeck_union_pat_multiple_fields)] +#[diag("union patterns should have exactly one field")] pub(crate) struct UnionPatMultipleFields { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_union_pat_dotdot)] +#[diag("`..` cannot be used in union patterns")] pub(crate) struct UnionPatDotDot { #[primary_span] pub span: Span, @@ -622,7 +682,7 @@ pub(crate) struct UnionPatDotDot { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_use_is_empty, + "consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything", applicability = "maybe-incorrect", style = "verbose" )] @@ -635,7 +695,7 @@ pub(crate) struct UseIsEmpty<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_arg_mismatch_indeterminate)] +#[diag("argument type mismatch was detected, but rustc had trouble determining where")] pub(crate) struct ArgMismatchIndeterminate { #[primary_span] pub span: Span, @@ -643,9 +703,11 @@ pub(crate) struct ArgMismatchIndeterminate { #[derive(Subdiagnostic)] pub(crate) enum SuggestBoxing { - #[note(hir_typeck_suggest_boxing_note)] + #[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" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] Unit { @@ -654,11 +716,15 @@ pub(crate) enum SuggestBoxing { #[suggestion_part(code = "")] end: Span, }, - #[note(hir_typeck_suggest_boxing_note)] + #[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" + )] AsyncBody, - #[note(hir_typeck_suggest_boxing_note)] + #[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" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] ExprFieldShorthand { @@ -668,9 +734,11 @@ pub(crate) enum SuggestBoxing { end: Span, ident: Ident, }, - #[note(hir_typeck_suggest_boxing_note)] + #[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" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] Other { @@ -683,7 +751,7 @@ pub(crate) enum SuggestBoxing { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_suggest_ptr_null_mut, + "consider using `core::ptr::null_mut` instead", applicability = "maybe-incorrect", style = "verbose", code = "core::ptr::null_mut()" @@ -694,8 +762,13 @@ pub(crate) struct SuggestPtrNullMut { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_trivial_cast)] -#[help] +#[diag( + "trivial {$numeric -> + [true] numeric cast + *[false] cast + }: `{$expr_ty}` as `{$cast_ty}`" +)] +#[help("cast can be replaced by coercion; this might require a temporary variable")] pub(crate) struct TrivialCast<'tcx> { pub numeric: bool, pub expr_ty: Ty<'tcx>, @@ -716,17 +789,20 @@ pub(crate) struct BreakNonLoop<'a> { impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::hir_typeck_break_non_loop); + let mut diag = Diag::new(dcx, level, msg!("`break` with value from a `{$kind}` loop")); diag.span(self.span); diag.code(E0571); diag.arg("kind", self.kind); - diag.span_label(self.span, fluent::hir_typeck_label); + diag.span_label( + self.span, + msg!("can only break with a value inside `loop` or breakable block"), + ); if let Some(head) = self.head { - diag.span_label(head, fluent::hir_typeck_label2); + diag.span_label(head, msg!("you can't `break` with a value in a `{$kind}` loop")); } diag.span_suggestion( self.span, - fluent::hir_typeck_suggestion, + msg!("use `break` on its own without a value inside this `{$kind}` loop"), self.suggestion, Applicability::MaybeIncorrect, ); @@ -744,7 +820,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { _ => { diag.span_suggestion( self.break_expr_span, - fluent::hir_typeck_break_expr_suggestion, + msg!("alternatively, you might have meant to use the available loop label"), label.ident, Applicability::MaybeIncorrect, ); @@ -756,33 +832,33 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_continue_labeled_block, code = E0696)] +#[diag("`continue` pointing to a labeled block", code = E0696)] pub(crate) struct ContinueLabeledBlock { #[primary_span] - #[label] + #[label("labeled blocks cannot be `continue`'d")] pub span: Span, - #[label(hir_typeck_block_label)] + #[label("labeled block the `continue` points to")] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_break_inside_closure, code = E0267)] +#[diag("`{$name}` inside of a closure", code = E0267)] pub(crate) struct BreakInsideClosure<'a> { #[primary_span] - #[label] + #[label("cannot `{$name}` inside of a closure")] pub span: Span, - #[label(hir_typeck_closure_label)] + #[label("enclosing closure")] pub closure_span: Span, pub name: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_break_inside_coroutine, code = E0267)] +#[diag("`{$name}` inside `{$kind}` {$source}", code = E0267)] pub(crate) struct BreakInsideCoroutine<'a> { #[primary_span] - #[label] + #[label("cannot `{$name}` inside `{$kind}` {$source}")] pub span: Span, - #[label(hir_typeck_coroutine_label)] + #[label("enclosing `{$kind}` {$source}")] pub coroutine_span: Span, pub name: &'a str, pub kind: &'a str, @@ -790,10 +866,18 @@ pub(crate) struct BreakInsideCoroutine<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_outside_loop, code = E0268)] +#[diag("`{$name}` outside of a loop{$is_break -> + [true] {\" or labeled block\"} + *[false] {\"\"} + }", code = E0268)] pub(crate) struct OutsideLoop<'a> { #[primary_span] - #[label] + #[label( + "cannot `{$name}` outside of a loop{$is_break -> + [true] {\" or labeled block\"} + *[false] {\"\"} + }" + )] pub spans: Vec, pub name: &'a str, pub is_break: bool, @@ -801,7 +885,10 @@ pub(crate) struct OutsideLoop<'a> { pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_typeck_outside_loop_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider labeling this block to be able to break within it", + applicability = "maybe-incorrect" +)] pub(crate) struct OutsideLoopSuggestion { #[suggestion_part(code = "'block: ")] pub block_span: Span, @@ -810,25 +897,30 @@ pub(crate) struct OutsideLoopSuggestion { } #[derive(Diagnostic)] -#[diag(hir_typeck_unlabeled_in_labeled_block, code = E0695)] +#[diag("unlabeled `{$cf_type}` inside of a labeled block", code = E0695)] pub(crate) struct UnlabeledInLabeledBlock<'a> { #[primary_span] - #[label] + #[label( + "`{$cf_type}` statements that would diverge to or through a labeled block need to bear a label" + )] pub span: Span, pub cf_type: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_unlabeled_cf_in_while_condition, code = E0590)] +#[diag("`break` or `continue` with no label in the condition of a `while` loop", code = E0590)] pub(crate) struct UnlabeledCfInWhileCondition<'a> { #[primary_span] - #[label] + #[label("unlabeled `{$cf_type}` in the condition of a `while` loop")] pub span: Span, pub cf_type: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_no_associated_item, code = E0599)] +#[diag("no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method -> + [true] {\"\"} + *[other] {\" \"}in the current scope +}", code = E0599)] pub(crate) struct NoAssociatedItem<'tcx> { #[primary_span] pub span: Span, @@ -840,7 +932,13 @@ pub(crate) struct NoAssociatedItem<'tcx> { } #[derive(Subdiagnostic)] -#[note(hir_typeck_candidate_trait_note)] +#[note( + "`{$trait_name}` defines an item `{$item_name}`{$action_or_ty -> + [NONE] {\"\"} + [implement] , perhaps you need to implement it + *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it + }" +)] pub(crate) struct CandidateTraitNote { #[primary_span] pub span: Span, @@ -850,7 +948,7 @@ pub(crate) struct CandidateTraitNote { } #[derive(Diagnostic)] -#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)] +#[diag("cannot cast `{$expr_ty}` as `bool`", code = E0054)] pub(crate) struct CannotCastToBool<'tcx> { #[primary_span] pub span: Span, @@ -860,7 +958,7 @@ pub(crate) struct CannotCastToBool<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_enum_drop)] +#[diag("cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`")] pub(crate) struct CastEnumDrop<'tcx> { #[primary_span] pub span: Span, @@ -869,7 +967,10 @@ pub(crate) struct CastEnumDrop<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_unknown_pointer, code = E0641)] +#[diag("cannot cast {$to -> + [true] to + *[false] from +} a pointer of an unknown kind", code = E0641)] pub(crate) struct CastUnknownPointer { #[primary_span] pub span: Span, @@ -887,13 +988,13 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { CastUnknownPointerSub::To(span) => { - let msg = diag.eagerly_translate(fluent::hir_typeck_label_to); + let msg = diag.eagerly_translate(msg!("needs more type information")); diag.span_label(span, msg); - let msg = diag.eagerly_translate(fluent::hir_typeck_note); + let msg = diag.eagerly_translate(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); diag.note(msg); } CastUnknownPointerSub::From(span) => { - let msg = diag.eagerly_translate(fluent::hir_typeck_label_from); + let msg = diag.eagerly_translate(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); diag.span_label(span, msg); } } @@ -903,18 +1004,18 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { #[derive(Subdiagnostic)] pub(crate) enum CannotCastToBoolHelp { #[suggestion( - hir_typeck_suggestion, + "compare with zero instead", applicability = "machine-applicable", code = " != 0", style = "verbose" )] Numeric(#[primary_span] Span), - #[label(hir_typeck_label)] + #[label("unsupported cast")] Unsupported(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(hir_typeck_ctor_is_private, code = E0603)] +#[diag("tuple struct constructor `{$def}` is private", code = E0603)] pub(crate) struct CtorIsPrivate { #[primary_span] pub span: Span, @@ -922,7 +1023,7 @@ pub(crate) struct CtorIsPrivate { } #[derive(Subdiagnostic)] -#[note(hir_typeck_deref_is_empty)] +#[note("this expression `Deref`s to `{$deref_ty}` which implements `is_empty`")] pub(crate) struct DerefImplsIsEmpty<'tcx> { #[primary_span] pub span: Span, @@ -931,7 +1032,7 @@ pub(crate) struct DerefImplsIsEmpty<'tcx> { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_convert_using_method, + "try using `{$sugg}` to convert `{$found}` to `{$expected}`", applicability = "machine-applicable", style = "verbose" )] @@ -946,7 +1047,9 @@ pub(crate) struct SuggestConvertViaMethod<'tcx> { } #[derive(Subdiagnostic)] -#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)] +#[note( + "the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`" +)] pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { pub ty_param_name: Symbol, pub found_ty: Ty<'tcx>, @@ -954,14 +1057,20 @@ pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum SuggestBoxingForReturnImplTrait { - #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "you could change the return type to be a boxed trait object", + applicability = "maybe-incorrect" + )] ChangeReturnType { #[suggestion_part(code = "Box, @@ -971,11 +1080,13 @@ pub(crate) enum SuggestBoxingForReturnImplTrait { } #[derive(Diagnostic)] -#[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)] +#[diag("can't reference `Self` constructor from outer item", code = E0401)] pub(crate) struct SelfCtorFromOuterItem { #[primary_span] pub span: Span, - #[label] + #[label( + "the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference" + )] pub impl_span: Span, #[subdiagnostic] pub sugg: Option, @@ -984,16 +1095,18 @@ pub(crate) struct SelfCtorFromOuterItem { } #[derive(Subdiagnostic)] -#[label(hir_typeck_self_ctor_from_outer_item_inner_item)] +#[label("`Self` used in this inner item")] pub(crate) struct InnerItem { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_typeck_self_ctor_from_outer_item)] +#[diag("can't reference `Self` constructor from outer item")] pub(crate) struct SelfCtorFromOuterItemLint { - #[label] + #[label( + "the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference" + )] pub impl_span: Span, #[subdiagnostic] pub sugg: Option, @@ -1002,7 +1115,11 @@ pub(crate) struct SelfCtorFromOuterItemLint { } #[derive(Subdiagnostic)] -#[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")] +#[suggestion( + "replace `Self` with the actual type", + code = "{name}", + applicability = "machine-applicable" +)] pub(crate) struct ReplaceWithName { #[primary_span] pub span: Span, @@ -1010,44 +1127,75 @@ pub(crate) struct ReplaceWithName { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)] +#[diag("cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}`", code = E0607)] pub(crate) struct CastThinPointerToWidePointer<'tcx> { #[primary_span] pub span: Span, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, - #[note(hir_typeck_teach_help)] + #[note( + "thin pointers are \"simple\" pointers: they are purely a reference to a + memory address. + + Wide pointers are pointers referencing \"Dynamically Sized Types\" (also + called DST). DST don't have a statically known size, therefore they can + only exist behind some kind of pointers that contain additional + information. Slices and trait objects are DSTs. In the case of slices, + the additional information the wide pointer holds is their size. + + To fix this error, don't try to cast directly between thin and wide + pointers. + + For more information about casts, take a look at The Book: + https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions" + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(hir_typeck_pass_to_variadic_function, code = E0617)] +#[diag("can't pass `{$ty}` to variadic function", code = E0617)] pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub cast_ty: &'a str, - #[suggestion(code = " as {cast_ty}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "cast the value to `{$cast_ty}`", + code = " as {cast_ty}", + applicability = "machine-applicable", + style = "verbose" + )] pub sugg_span: Span, - #[note(hir_typeck_teach_help)] + #[note( + "certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's numeric promotion rules" + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] -#[help] -#[note] +#[diag("can't pass a function item to a variadic function", code = E0617)] +#[help( + "a function item is zero-sized and needs to be cast into a function pointer to be used in FFI" +)] +#[note( + "for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html" +)] pub(crate) struct PassFnItemToVariadicFunction { #[primary_span] pub span: Span, - #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use a function pointer instead", + code = " as {replace}", + applicability = "machine-applicable", + style = "verbose" + )] pub sugg_span: Span, pub replace: String, } #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_replace_comma_with_semicolon, + "replace the comma with a semicolon to create {$descr}", applicability = "machine-applicable", style = "verbose", code = "; " @@ -1059,7 +1207,7 @@ pub(crate) struct ReplaceCommaWithSemicolon { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_supertrait_item_shadowing)] +#[diag("trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait")] pub(crate) struct SupertraitItemShadowing { pub item: Symbol, pub subtrait: Symbol, @@ -1070,7 +1218,7 @@ pub(crate) struct SupertraitItemShadowing { } #[derive(Subdiagnostic)] -#[note(hir_typeck_supertrait_item_shadower)] +#[note("item from `{$subtrait}` shadows a supertrait item")] pub(crate) struct SupertraitItemShadower { pub subtrait: Symbol, #[primary_span] @@ -1079,13 +1227,13 @@ pub(crate) struct SupertraitItemShadower { #[derive(Subdiagnostic)] pub(crate) enum SupertraitItemShadowee { - #[note(hir_typeck_supertrait_item_shadowee)] + #[note("item from `{$supertrait}` is shadowed by a subtrait item")] Labeled { #[primary_span] span: Span, supertrait: Symbol, }, - #[note(hir_typeck_supertrait_item_multiple_shadowee)] + #[note("items from several supertraits are shadowed: {$traits}")] Several { #[primary_span] spans: MultiSpan, @@ -1094,7 +1242,7 @@ pub(crate) enum SupertraitItemShadowee { } #[derive(Diagnostic)] -#[diag(hir_typeck_register_type_unstable)] +#[diag("type `{$ty}` cannot be used with this register class in stable")] pub(crate) struct RegisterTypeUnstable<'a> { #[primary_span] pub span: Span, @@ -1102,22 +1250,22 @@ pub(crate) struct RegisterTypeUnstable<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_naked_asm_outside_naked_fn)] +#[diag("the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]`")] pub(crate) struct NakedAsmOutsideNakedFn { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_no_patterns)] +#[diag("patterns not allowed in naked function parameters")] pub(crate) struct NoPatterns { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_params_not_allowed)] -#[help] +#[diag("referencing function parameters is not allowed in naked functions")] +#[help("follow the calling convention in asm block to use parameters")] pub(crate) struct ParamsNotAllowed { #[primary_span] pub span: Span, @@ -1132,14 +1280,21 @@ pub(crate) struct NakedFunctionsAsmBlock { impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::hir_typeck_naked_functions_asm_block); + let mut diag = Diag::new( + dcx, + level, + msg!("naked functions must contain a single `naked_asm!` invocation"), + ); diag.span(self.span); diag.code(E0787); for span in self.multiple_asms.iter() { - diag.span_label(*span, fluent::hir_typeck_label_multiple_asm); + diag.span_label( + *span, + msg!("multiple `naked_asm!` invocations are not allowed in naked functions"), + ); } for span in self.non_asms.iter() { - diag.span_label(*span, fluent::hir_typeck_label_non_asm); + diag.span_label(*span, msg!("not allowed in naked functions")); } diag } @@ -1182,44 +1337,48 @@ pub(crate) fn maybe_emit_plus_equals_diagnostic<'a>( } #[derive(Diagnostic)] -#[diag(hir_typeck_naked_functions_must_naked_asm, code = E0787)] +#[diag("the `asm!` macro is not allowed in naked functions", code = E0787)] pub(crate) struct NakedFunctionsMustNakedAsm { #[primary_span] - #[label] + #[label("consider using the `naked_asm!` macro instead")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_abi_cannot_be_called)] +#[diag("functions with the {$abi} ABI cannot be called")] pub(crate) struct AbiCannotBeCalled { #[primary_span] - #[note] + #[note("an `extern {$abi}` function can only be called using inline assembly")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_typeck_gpu_kernel_abi_cannot_be_called)] +#[diag("functions with the \"gpu-kernel\" ABI cannot be called")] pub(crate) struct GpuKernelAbiCannotBeCalled { #[primary_span] - #[note] + #[note("an `extern \"gpu-kernel\"` function must be launched on the GPU by the runtime")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_const_continue_bad_label)] +#[diag("`#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`")] pub(crate) struct ConstContinueBadLabel { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_project_on_non_pin_project_type)] +#[diag("cannot project on type that is not `#[pin_v2]`")] pub(crate) struct ProjectOnNonPinProjectType { #[primary_span] pub span: Span, - #[note] + #[note("type defined here")] pub def_span: Option, - #[suggestion(code = "#[pin_v2]\n", applicability = "machine-applicable")] + #[suggestion( + "add `#[pin_v2]` here", + code = "#[pin_v2]\n", + applicability = "machine-applicable" + )] pub sugg_span: Option, } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 885af3b909b8..5b40531f9462 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1670,11 +1670,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce_to = expected .to_option(self) - .and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index()) + .and_then(|uty| { + self.try_structurally_resolve_type(expr.span, uty) + .builtin_index() + // Avoid using the original type variable as the coerce_to type, as it may resolve + // during the first coercion instead of being the LUB type. + .filter(|t| !self.try_structurally_resolve_type(expr.span, *t).is_ty_var()) + }) .unwrap_or_else(|| self.next_ty_var(expr.span)); let mut coerce = CoerceMany::with_capacity(coerce_to, args.len()); for e in args { + // FIXME: the element expectation should use + // `try_structurally_resolve_and_adjust_for_branches` just like in `if` and `match`. + // While that fixes nested coercion, it will break [some + // code like this](https://github.com/rust-lang/rust/pull/140283#issuecomment-2958776528). + // If we find a way to support recursive tuple coercion, this break can be avoided. let e_ty = self.check_expr_with_hint(e, coerce_to); let cause = self.misc(e.span); coerce.coerce(self, &cause, e, e_ty); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ad34994526ed..77ecfc2fb0be 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -22,6 +22,7 @@ use rustc_middle::hir::place::ProjectionKind; pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; use rustc_middle::thir::DerefPatBorrowMode; +use rustc_middle::ty::adjustment::DerefAdjustKind; use rustc_middle::ty::{ self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; @@ -733,14 +734,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.consume_or_copy(&place_with_id, place_with_id.hir_id); } - adjustment::Adjust::Deref(None) => {} + adjustment::Adjust::Deref(DerefAdjustKind::Builtin) => {} // Autoderefs for overloaded Deref calls in fact reference // their receiver. That is, if we have `(*x)` where `x` // is of type `Rc`, then this in fact is equivalent to // `x.deref()`. Since `deref()` is declared with `&self`, // this is an autoref of `x`. - adjustment::Adjust::Deref(Some(ref deref)) => { + adjustment::Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk); } @@ -818,14 +819,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// The core driver for walking a pattern /// /// This should mirror how pattern-matching gets lowered to MIR, as - /// otherwise lowering will ICE when trying to resolve the upvars. + /// otherwise said lowering will ICE when trying to resolve the upvars. /// /// However, it is okay to approximate it here by doing *more* accesses than /// the actual MIR builder will, which is useful when some checks are too - /// cumbersome to perform here. For example, if after typeck it becomes - /// clear that only one variant of an enum is inhabited, and therefore a - /// read of the discriminant is not necessary, `walk_pat` will have - /// over-approximated the necessary upvar capture granularity. + /// cumbersome to perform here, because e.g. they require more typeck results + /// than available. /// /// Do note that discrepancies like these do still create obscure corners /// in the semantics of the language, and should be avoided if possible. @@ -1272,9 +1271,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx { let target = self.cx.resolve_vars_if_possible(adjustment.target); match adjustment.kind { - adjustment::Adjust::Deref(overloaded) => { + adjustment::Adjust::Deref(deref_kind) => { // Equivalent to *expr or something similar. - let base = if let Some(deref) = overloaded { + let base = if let DerefAdjustKind::Overloaded(deref) = deref_kind { let ref_ty = Ty::new_ref( self.cx.tcx(), self.cx.tcx().lifetimes.re_erased, @@ -1852,26 +1851,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// Checks whether a type has multiple variants, and therefore, whether a - /// read of the discriminant might be necessary. Note that the actual MIR - /// builder code does a more specific check, filtering out variants that - /// happen to be uninhabited. - /// - /// Here, it is not practical to perform such a check, because inhabitedness - /// queries require typeck results, and typeck requires closure capture analysis. - /// - /// Moreover, the language is moving towards uninhabited variants still semantically - /// causing a discriminant read, so we *shouldn't* perform any such check. - /// - /// FIXME(never_patterns): update this comment once the aforementioned MIR builder - /// code is changed to be insensitive to inhhabitedness. + /// read of the discriminant might be necessary. #[instrument(skip(self, span), level = "debug")] fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { - // Note that if a non-exhaustive SingleVariant is defined in another crate, we need - // to assume that more cases will be added to the variant in the future. This mean - // that we should handle non-exhaustive SingleVariant the same way we would handle - // a MultiVariant. - def.variants().len() > 1 || def.variant_list_has_applicable_non_exhaustive() + // We treat non-exhaustive enums the same independent of the crate they are + // defined in, to avoid differences in the operational semantics between crates. + def.variants().len() > 1 || def.is_variant_list_non_exhaustive() } else { false } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 727666de3c47..c10e7f3bfb8b 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -7,6 +7,7 @@ use rustc_data_structures::graph::{self}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::HirId; +use rustc_hir::attrs::DivergingFallbackBehavior; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{InferKind, Visitor}; @@ -19,17 +20,6 @@ use tracing::debug; use crate::{FnCtxt, errors}; -#[derive(Copy, Clone)] -pub(crate) enum DivergingFallbackBehavior { - /// Always fallback to `()` (aka "always spontaneous decay") - ToUnit, - /// Always fallback to `!` (which should be equivalent to never falling back + not making - /// never-to-any coercions unless necessary) - ToNever, - /// Don't fallback at all - NoFallback, -} - impl<'tcx> FnCtxt<'_, 'tcx> { /// Performs type inference fallback, setting [`FnCtxt::diverging_fallback_has_occurred`] /// if the never type fallback has occurred. @@ -367,11 +357,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { VecGraph::new(num_ty_vars, coercion_edges) } - /// If `ty` is an unresolved type variable, returns its root vid. - fn root_vid(&self, ty: Ty<'tcx>) -> Option { - Some(self.root_var(self.shallow_resolve(ty).ty_vid()?)) - } - /// Given a set of diverging vids and coercions, walk the HIR to gather a /// set of suggestions which can be applied to preserve fallback to unit. fn try_to_suggest_annotations( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 91f91d911444..e8d5ff017cf8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -20,7 +20,9 @@ use rustc_hir_analysis::hir_ty_lowering::{ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::adjustment::{ + Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, +}; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, @@ -43,6 +45,38 @@ use crate::method::{self, MethodCallee}; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + /// Transform generic args for inherent associated type constants (IACs). + /// + /// IACs have a different generic parameter structure than regular associated constants: + /// - Regular assoc const: parent (impl) generic params + own generic params + /// - IAC (type_const): Self type + own generic params + pub(crate) fn transform_args_for_inherent_type_const( + &self, + def_id: DefId, + args: GenericArgsRef<'tcx>, + ) -> GenericArgsRef<'tcx> { + let tcx = self.tcx; + if !tcx.is_type_const(def_id) { + return args; + } + let Some(assoc_item) = tcx.opt_associated_item(def_id) else { + return args; + }; + if !matches!(assoc_item.container, ty::AssocContainer::InherentImpl) { + return args; + } + + let impl_def_id = assoc_item.container_id(tcx); + let generics = tcx.generics_of(def_id); + let impl_args = &args[..generics.parent_count]; + let self_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args); + // Build new args: [Self, own_args...] + let own_args = &args[generics.parent_count..]; + tcx.mk_args_from_iter( + std::iter::once(ty::GenericArg::from(self_ty)).chain(own_args.iter().copied()), + ) + } + /// Produces warning on the given node, if the current point in the /// function is unreachable, and there hasn't been another warning. pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) { @@ -266,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); } } - Adjust::Deref(Some(overloaded_deref)) => { + Adjust::Deref(DerefAdjustKind::Overloaded(overloaded_deref)) => { self.enforce_context_effects( None, expr.span, @@ -274,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.mk_args(&[expr_ty.into()]), ); } - Adjust::Deref(None) => { + Adjust::Deref(DerefAdjustKind::Builtin) => { // FIXME(const_trait_impl): We *could* enforce `&T: [const] Deref` here. } Adjust::Pointer(_pointer_coercion) => { @@ -547,7 +581,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { where T: TypeVisitable>, { - t.has_free_regions() || t.has_aliases() || t.has_infer_types() + // FIXME(mgca): should this also count stuff with infer consts + t.has_free_regions() || t.has_aliases() || t.has_infer_types() || t.has_param() } pub(crate) fn node_ty(&self, id: HirId) -> Ty<'tcx> { @@ -1279,8 +1314,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }); + let args_for_user_type = if let Res::Def(DefKind::AssocConst, def_id) = res { + self.transform_args_for_inherent_type_const(def_id, args_raw) + } else { + args_raw + }; + // First, store the "user args" for later. - self.write_user_type_annotation_from_args(hir_id, def_id, args_raw, user_self_ty); + self.write_user_type_annotation_from_args(hir_id, def_id, args_for_user_type, user_self_ty); // Normalize only after registering type annotations. let args = self.normalize(span, args_raw); @@ -1320,6 +1361,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } debug!("instantiate_value_path: type of {:?} is {:?}", hir_id, ty_instantiated); + + let args = if let Res::Def(DefKind::AssocConst, def_id) = res { + self.transform_args_for_inherent_type_const(def_id, args) + } else { + args + }; + self.write_args(hir_id, args); (ty_instantiated, res) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c07cbfae256d..54d8306936dd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize}; +use rustc_hir::attrs::DivergingBlockBehavior; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -47,29 +48,6 @@ rustc_index::newtype_index! { pub(crate) struct GenericIdx {} } -#[derive(Clone, Copy, Default)] -pub(crate) enum DivergingBlockBehavior { - /// This is the current stable behavior: - /// - /// ```rust - /// { - /// return; - /// } // block has type = !, even though we are supposedly dropping it with `;` - /// ``` - #[default] - Never, - - /// Alternative behavior: - /// - /// ```ignore (very-unstable-new-attribute) - /// #![rustc_never_type_options(diverging_block_default = "unit")] - /// { - /// return; - /// } // block has type = (), since we are dropping `!` from `return` with `;` - /// ``` - Unit, -} - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn check_casts(&mut self) { let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut(); @@ -2647,7 +2625,15 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { // To suggest a multipart suggestion when encountering `foo(1, "")` where the def // was `fn foo(())`. let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx]; - suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx))); + // Check if the new suggestion would overlap with any existing suggestion. + // This can happen when we have both removal suggestions (which may include + // adjacent commas) and type replacement suggestions for the same span. + let dominated = suggestions + .iter() + .any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span)); + if !dominated { + suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx))); + } } } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c875e2e50d70..412df9162e9f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -10,8 +10,9 @@ use std::ops::Deref; use hir::def_id::CRATE_DEF_ID; use rustc_errors::DiagCtxtHandle; +use rustc_hir::attrs::{AttributeKind, DivergingBlockBehavior, DivergingFallbackBehavior}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, HirId, ItemLocalMap}; +use rustc_hir::{self as hir, HirId, ItemLocalMap, find_attr}; use rustc_hir_analysis::hir_ty_lowering::{ HirTyLowerer, InherentAssocCandidate, RegionInferReason, }; @@ -19,15 +20,13 @@ use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_infer::traits::{DynCompatibilityViolation, Obligation}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; -use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym}; +use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span}; use rustc_trait_selection::error_reporting::TypeErrCtxt; use rustc_trait_selection::traits::{ self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, }; use crate::coercion::CoerceMany; -use crate::fallback::DivergingFallbackBehavior; -use crate::fn_ctxt::checks::DivergingBlockBehavior; use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt}; /// The `FnCtxt` stores type-checking context needed to type-check bodies of @@ -517,51 +516,5 @@ fn parse_never_type_options_attr( // Error handling is dubious here (unwraps), but that's probably fine for an internal attribute. // Just don't write incorrect attributes <3 - let mut fallback = None; - let mut block = None; - - let items = if tcx.features().rustc_attrs() { - tcx.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options) - .map(|attr| attr.meta_item_list().unwrap()) - } else { - None - }; - let items = items.unwrap_or_default(); - - for item in items { - if item.has_name(sym::fallback) && fallback.is_none() { - let mode = item.value_str().unwrap(); - match mode { - sym::unit => fallback = Some(DivergingFallbackBehavior::ToUnit), - sym::never => fallback = Some(DivergingFallbackBehavior::ToNever), - sym::no => fallback = Some(DivergingFallbackBehavior::NoFallback), - _ => { - tcx.dcx().span_err(item.span(), format!("unknown never type fallback mode: `{mode}` (supported: `unit`, `niko`, `never` and `no`)")); - } - }; - continue; - } - - if item.has_name(sym::diverging_block_default) && block.is_none() { - let default = item.value_str().unwrap(); - match default { - sym::unit => block = Some(DivergingBlockBehavior::Unit), - sym::never => block = Some(DivergingBlockBehavior::Never), - _ => { - tcx.dcx().span_err(item.span(), format!("unknown diverging block default: `{default}` (supported: `unit` and `never`)")); - } - }; - continue; - } - - tcx.dcx().span_err( - item.span(), - format!( - "unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)", - item.name().unwrap() - ), - ); - } - - (fallback, block) + find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNeverTypeOptions {fallback, diverging_block_default} => (*fallback, *diverging_block_default)).unwrap_or_default() } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e4c194147f9..735e684500fe 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -5,7 +5,7 @@ use core::iter; use hir::def_id::LocalDefId; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; -use rustc_errors::{Applicability, Diag, MultiSpan, listify}; +use rustc_errors::{Applicability, Diag, MultiSpan, listify, msg}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -33,10 +33,10 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _ use tracing::{debug, instrument}; use super::FnCtxt; +use crate::errors; use crate::fn_ctxt::rustc_span::BytePos; use crate::method::probe; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; -use crate::{errors, fluent_generated as fluent}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn body_fn_sig(&self) -> Option> { @@ -482,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sugg = prefix_wrap(".map(|x| x.as_str())"); err.span_suggestion_verbose( expr.span.shrink_to_hi(), - fluent::hir_typeck_convert_to_str, + msg!("try converting the passed type into a `&str`"), sugg, Applicability::MachineApplicable, ); @@ -1932,25 +1932,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + let mut suggest_derive = true; if let Some(errors) = self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { + let manually_impl = "consider manually implementing `Clone` to avoid the \ + implicit type parameter bounds"; match &errors[..] { [] => {} [error] => { - diag.help(format!( - "`Clone` is not implemented because the trait bound `{}` is \ - not satisfied", - error.obligation.predicate, - )); + let msg = "`Clone` is not implemented because a trait bound is not \ + satisfied"; + if let traits::ObligationCauseCode::ImplDerived(data) = + error.obligation.cause.code() + { + let mut span: MultiSpan = data.span.into(); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) { + span.push_span_label( + data.span, + format!( + "derive introduces an implicit `{}` bound", + error.obligation.predicate + ), + ); + } + diag.span_help(span, msg); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(msg); + } } _ => { - diag.help(format!( - "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {}", - listify(&errors, |e| format!("`{}`", e.obligation.predicate)) - .unwrap(), - )); + let unsatisfied_bounds: Vec<_> = errors + .iter() + .filter_map(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + let pre = if self + .tcx + .is_automatically_derived(data.impl_or_alias_def_id) + { + "derive introduces an implicit " + } else { + "" + }; + Some(( + data.span, + format!( + "{pre}unsatisfied trait bound `{}`", + error.obligation.predicate + ), + )) + } + _ => None, + }) + .collect(); + let msg = "`Clone` is not implemented because the some trait bounds \ + could not be satisfied"; + if errors.len() == unsatisfied_bounds.len() { + let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds + .iter() + .map(|(span, _)| *span) + .collect::>() + .into(); + for (span, label) in unsatisfied_bounds { + unsatisfied_bounds_spans.push_span_label(span, label); + } + diag.span_help(unsatisfied_bounds_spans, msg); + if errors.iter().all(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + } + _ => false, + }) { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(format!( + "{msg}: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), + )); + } } } for error in errors { @@ -1968,7 +2037,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + if suggest_derive { + self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + } } } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 39c28c4f4e99..8692720529d5 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] @@ -67,8 +67,6 @@ use crate::expectation::Expectation; use crate::fn_ctxt::LoweredTy; use crate::gather_locals::GatherLocalsVisitor; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - #[macro_export] macro_rules! type_error_struct { ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({ @@ -200,6 +198,14 @@ fn typeck_with_inspect<'tcx>( let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id))); fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code); + if let hir::Node::AnonConst(_) = node { + fcx.require_type_is_sized( + expected_type, + body.value.span, + ObligationCauseCode::SizedConstOrStatic, + ); + } + fcx.check_expr_coercible_to_type(body.value, expected_type, None); fcx.write_ty(id, expected_type); diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index bf829c2d645d..746678e2865f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -7,7 +7,7 @@ mod prelude_edition_lints; pub(crate) mod probe; mod suggest; -use rustc_errors::{Applicability, Diag, SubdiagMessage}; +use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; @@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_method_call( &self, err: &mut Diag<'_>, - msg: impl Into + std::fmt::Debug, + msg: impl Into + std::fmt::Debug, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5673d044ad2c..517d73f51783 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,7 +13,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err}; +use rustc_errors::{ + Applicability, Diag, MultiSpan, StashKey, listify, pluralize, struct_span_code_err, +}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -50,6 +52,51 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem}; use crate::method::probe::UnsatisfiedPredicates; use crate::{Expectation, FnCtxt}; +/// Tracks trait bounds and detects duplicates between ref and non-ref versions of self types. +/// This is used to condense error messages when the same trait bound appears for both +/// `T` and `&T` (or `&mut T`). +struct TraitBoundDuplicateTracker { + trait_def_ids: FxIndexSet, + seen_ref: FxIndexSet, + seen_non_ref: FxIndexSet, + has_ref_dupes: bool, +} + +impl TraitBoundDuplicateTracker { + fn new() -> Self { + Self { + trait_def_ids: FxIndexSet::default(), + seen_ref: FxIndexSet::default(), + seen_non_ref: FxIndexSet::default(), + has_ref_dupes: false, + } + } + + /// Track a trait bound. `is_ref` indicates whether the self type is a reference. + fn track(&mut self, def_id: DefId, is_ref: bool) { + self.trait_def_ids.insert(def_id); + if is_ref { + if self.seen_non_ref.contains(&def_id) { + self.has_ref_dupes = true; + } + self.seen_ref.insert(def_id); + } else { + if self.seen_ref.contains(&def_id) { + self.has_ref_dupes = true; + } + self.seen_non_ref.insert(def_id); + } + } + + fn has_ref_dupes(&self) -> bool { + self.has_ref_dupes + } + + fn into_trait_def_ids(self) -> FxIndexSet { + self.trait_def_ids + } +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { self.autoderef(span, ty) @@ -1004,6 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_ident: Ident, item_kind: &str, bound_spans: SortedMap>, + unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>, ) { let mut ty_span = match rcvr_ty.kind() { ty::Param(param_type) => { @@ -1012,13 +1060,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) if def.did().is_local() => Some(self.tcx.def_span(def.did())), _ => None, }; + let rcvr_ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path()); + let mut tracker = TraitBoundDuplicateTracker::new(); + for (predicate, _parent_pred, _cause) in unsatisfied_predicates { + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = + predicate.kind().skip_binder() + && let self_ty = pred.trait_ref.self_ty() + && self_ty.peel_refs() == rcvr_ty + { + let is_ref = matches!(self_ty.kind(), ty::Ref(..)); + tracker.track(pred.trait_ref.def_id, is_ref); + } + } + let has_ref_dupes = tracker.has_ref_dupes(); + let mut missing_trait_names = tracker + .into_trait_def_ids() + .into_iter() + .map(|def_id| format!("`{}`", self.tcx.def_path_str(def_id))) + .collect::>(); + missing_trait_names.sort(); + let should_condense = + has_ref_dupes && missing_trait_names.len() > 1 && matches!(rcvr_ty.kind(), ty::Adt(..)); + let missing_trait_list = if should_condense { + Some(match missing_trait_names.as_slice() { + [only] => only.clone(), + [first, second] => format!("{first} or {second}"), + [rest @ .., last] => format!("{} or {last}", rest.join(", ")), + [] => String::new(), + }) + } else { + None + }; for (span, mut bounds) in bound_spans { if !self.tcx.sess.source_map().is_span_accessible(span) { continue; } bounds.sort(); bounds.dedup(); - let pre = if Some(span) == ty_span { + let is_ty_span = Some(span) == ty_span; + if is_ty_span && should_condense { + ty_span.take(); + let label = if let Some(missing_trait_list) = &missing_trait_list { + format!( + "{item_kind} `{item_ident}` not found for this {} because `{rcvr_ty_str}` doesn't implement {missing_trait_list}", + rcvr_ty.prefix_string(self.tcx) + ) + } else { + format!( + "{item_kind} `{item_ident}` not found for this {}", + rcvr_ty.prefix_string(self.tcx) + ) + }; + err.span_label(span, label); + continue; + } + let pre = if is_ty_span { ty_span.take(); format!( "{item_kind} `{item_ident}` not found for this {} because it ", @@ -1248,6 +1344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_ident, item_kind, bound_spans, + unsatisfied_predicates, ); self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected); @@ -1507,6 +1604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_spans: &mut SortedMap>, ) { let tcx = self.tcx; + let rcvr_ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path()); let mut type_params = FxIndexMap::default(); // Pick out the list of unimplemented traits on the receiver. @@ -1650,19 +1748,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: UnordSet<_> = Default::default(); let mut spanned_predicates = FxIndexMap::default(); + let mut manually_impl = false; for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. - let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) { - Some(ObligationCauseCode::ImplDerived(data)) => { - (data.impl_or_alias_def_id, data.span) - } - Some( - ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) - | ObligationCauseCode::WhereClause(def_id, span), - ) if !span.is_dummy() => (*def_id, *span), - _ => continue, - }; + let (item_def_id, cause_span, cause_msg) = + match cause.as_ref().map(|cause| cause.code()) { + Some(ObligationCauseCode::ImplDerived(data)) => { + let msg = if let DefKind::Impl { of_trait: true } = + self.tcx.def_kind(data.impl_or_alias_def_id) + { + format!( + "type parameter would need to implement `{}`", + self.tcx + .item_name(self.tcx.impl_trait_id(data.impl_or_alias_def_id)) + ) + } else { + format!("unsatisfied bound `{p}` introduced here") + }; + (data.impl_or_alias_def_id, data.span, msg) + } + Some( + ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) + | ObligationCauseCode::WhereClause(def_id, span), + ) if !span.is_dummy() => { + (*def_id, *span, format!("unsatisfied bound `{p}` introduced here")) + } + _ => continue, + }; // Don't point out the span of `WellFormed` predicates. if !matches!( @@ -1693,13 +1806,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = entry.or_insert_with(|| { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); - entry.0.insert(span); + entry.0.insert(cause_span); entry.1.insert(( - span, - "unsatisfied trait bound introduced in this `derive` macro", + cause_span, + cause_msg, )); entry.2.push(p); skip_list.insert(p); + manually_impl = true; } // Unmet obligation coming from an `impl`. @@ -1744,7 +1858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1752,9 +1866,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(self_ty.span); }; if let Some(of_trait) = of_trait { - entry.1.insert((of_trait.trait_ref.path.span, "")); + entry.1.insert((of_trait.trait_ref.path.span, String::new())); } - entry.1.insert((self_ty.span, "")); + entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), @@ -1783,8 +1897,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert((ident.span, "")); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((ident.span, String::new())); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); entry.2.push(p); } _ => { @@ -1798,6 +1912,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); spanned_predicates.sort_by_key(|(span, _)| *span); for (_, (primary_spans, span_labels, predicates)) in spanned_predicates { + let mut tracker = TraitBoundDuplicateTracker::new(); + let mut all_trait_bounds_for_rcvr = true; + for pred in &predicates { + match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + let self_ty = pred.trait_ref.self_ty(); + if self_ty.peel_refs() != rcvr_ty { + all_trait_bounds_for_rcvr = false; + break; + } + let is_ref = matches!(self_ty.kind(), ty::Ref(..)); + tracker.track(pred.trait_ref.def_id, is_ref); + } + _ => { + all_trait_bounds_for_rcvr = false; + break; + } + } + } + let has_ref_dupes = tracker.has_ref_dupes(); + let trait_def_ids = tracker.into_trait_def_ids(); let mut preds: Vec<_> = predicates .iter() .filter_map(|pred| format_pred(**pred)) @@ -1805,7 +1940,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); preds.sort(); preds.dedup(); - let msg = if let [pred] = &preds[..] { + let availability_note = if all_trait_bounds_for_rcvr + && has_ref_dupes + && trait_def_ids.len() > 1 + && matches!(rcvr_ty.kind(), ty::Adt(..)) + { + let mut trait_names = trait_def_ids + .into_iter() + .map(|def_id| format!("`{}`", tcx.def_path_str(def_id))) + .collect::>(); + trait_names.sort(); + listify(&trait_names, |name| name.to_string()).map(|traits| { + format!( + "for `{item_ident}` to be available, `{rcvr_ty_str}` must implement {traits}" + ) + }) + } else { + None + }; + let msg = if let Some(availability_note) = availability_note { + availability_note + } else if let [pred] = &preds[..] { format!("trait bound {pred} was not satisfied") } else { format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),) @@ -1944,6 +2099,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *suggested_derive = self.suggest_derive(err, unsatisfied_predicates); *unsatisfied_bounds = true; } + if manually_impl { + err.help("consider manually implementing the trait to avoid undesired bounds"); + } } /// If an appropriate error source is not found, check method chain for possible candidates @@ -2103,7 +2261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for inherent_method in self.tcx.associated_items(inherent_impl_did).in_definition_order() { - if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols) + if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::RustcConfusables{symbols, ..} => symbols) && candidates.contains(&item_name.name) && inherent_method.is_fn() { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b56ab6dcb4ab..13f87c092352 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -3,6 +3,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use rustc_abi::FieldIdx; use rustc_ast as ast; +use rustc_data_structures::assert_matches; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ @@ -24,7 +25,6 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::source_map::Spanned; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; @@ -611,7 +611,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(*hir_id, ty); ty } - PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info), + PatKind::Expr(expr @ PatExpr { kind: PatExprKind::Lit { lit, .. }, .. }) => { + self.check_pat_lit(pat.span, expr, &lit.node, expected, &pat_info.top_info) + } PatKind::Range(lhs, rhs, _) => { self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info) } @@ -938,23 +940,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_lit( &self, span: Span, - lt: &hir::PatExpr<'tcx>, + expr: &hir::PatExpr<'tcx>, + lit_kind: &ast::LitKind, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx> { + assert_matches!(expr.kind, hir::PatExprKind::Lit { .. }); + // We've already computed the type above (when checking for a non-ref pat), // so avoid computing it again. - let ty = self.node_ty(lt.hir_id); + let ty = self.node_ty(expr.hir_id); // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. // Additionally, when `deref_patterns` is enabled, byte string literal patterns may have // types `[u8]` or `[u8; N]`, in order to type, e.g., `deref!(b"..."): Vec`. let mut pat_ty = ty; - if let hir::PatExprKind::Lit { - lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, .. - } = lt.kind - { + if matches!(lit_kind, ast::LitKind::ByteStr(..)) { let tcx = self.tcx; let expected = self.structurally_resolve_type(span, expected); match *expected.kind() { @@ -962,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Ref(_, inner_ty, _) if self.try_structurally_resolve_type(span, inner_ty).is_slice() => { - trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); + trace!(?expr.hir_id.local_id, "polymorphic byte string lit"); pat_ty = Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, @@ -988,9 +990,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // When `deref_patterns` is enabled, in order to allow `deref!("..."): String`, we allow // string literal patterns to have type `str`. This is accounted for when lowering to MIR. if self.tcx.features().deref_patterns() - && let hir::PatExprKind::Lit { - lit: Spanned { node: ast::LitKind::Str(..), .. }, .. - } = lt.kind + && matches!(lit_kind, ast::LitKind::Str(..)) && self.try_structurally_resolve_type(span, expected).is_str() { pat_ty = self.tcx.types.str_; @@ -2841,7 +2841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match expected.maybe_pinned_ref() { - Some((r_ty, r_pinned, r_mutbl)) + Some((r_ty, r_pinned, r_mutbl, _)) if ((ref_pat_matches_mut_ref && r_mutbl >= pat_mutbl) || r_mutbl == pat_mutbl) && pat_pinned == r_pinned => diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index a48db2cc855c..c33f8bdaffe2 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -4,8 +4,8 @@ use rustc_infer::infer::InferOk; use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref, - PointerCoercion, + Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, + OverloadedDeref, PointerCoercion, }; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, sym}; @@ -298,7 +298,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { for adjustment in &mut adjustments { - if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind + if let Adjust::Deref(DerefAdjustKind::Overloaded(ref mut deref)) = + adjustment.kind && let Some(ok) = self.try_mutable_overloaded_place_op( expr.span, source, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 1a2b76485f35..767913ba5261 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -36,10 +36,10 @@ use rustc_abi::FIRST_VARIANT; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir as hir; -use rustc_hir::HirId; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{self as hir, HirId, find_attr}; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; @@ -1743,7 +1743,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool { - self.has_rustc_attrs && self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis) + self.has_rustc_attrs + && find_attr!( + self.tcx.get_all_attrs(closure_def_id), + AttributeKind::RustcCaptureAnalysis + ) } fn log_capture_analysis_first_pass( diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index db0a58418875..ac4d7d8e1cbc 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -6,10 +6,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rand = "0.9.0" -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hashes = { path = "../rustc_hashes" } @@ -19,6 +17,5 @@ rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl deleted file mode 100644 index bbc1fab05dfe..000000000000 --- a/compiler/rustc_incremental/messages.ftl +++ /dev/null @@ -1,102 +0,0 @@ -incremental_assert_loaded = - we asserted that an existing incremental cache directory should be successfully loaded, but it was not - -incremental_assert_not_loaded = - we asserted that the incremental cache should not be loaded, but it was loaded - -incremental_assertion_auto = - `except` specified DepNodes that can not be affected for "{$name}": "{$e}" - -incremental_associated_value_expected = expected an associated value - -incremental_associated_value_expected_for = associated value expected for `{$ident}` - -incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err} - -incremental_cargo_help_1 = - incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental) -incremental_cargo_help_2 = - the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir) - -incremental_copy_workproduct_to_cache = - error copying object file `{$from}` to incremental directory as `{$to}`: {$err} - -incremental_corrupt_file = corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant. - -incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err} - -incremental_create_incr_comp_dir = - could not create incremental compilation {$tag} directory `{$path}`: {$err} - -incremental_create_lock = - incremental compilation: could not create session directory lock file: {$lock_err} -incremental_create_new = failed to create {$name} at `{$path}`: {$err} - -incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} - -incremental_delete_incompatible = - failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err} - -incremental_delete_lock = - error deleting lock file for incremental compilation session directory `{$path}`: {$err} - -incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err} - -incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err} - -incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err} - -incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err} - -incremental_finalized_gc_failed = - failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err} - -incremental_hard_link_failed = - hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}` - -incremental_invalid_gc_failed = - failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err} - -incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err} - -incremental_lock_unsupported = - the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation - -incremental_missing_depnode = missing `DepNode` variant - -incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected - -incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err} - -incremental_no_cfg = no cfg attribute - -incremental_no_path = no path from `{$source}` to `{$target}` - -incremental_not_clean = `{$dep_node_str}` should be clean but is not - -incremental_not_dirty = `{$dep_node_str}` should be dirty but is not - -incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not - -incremental_ok = OK - -incremental_repeated_depnode_label = dep-node label `{$label}` is repeated - -incremental_session_gc_failed = - failed to garbage collect incremental compilation session directory `{$path}`: {$err} - -incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute - -incremental_undefined_clean_dirty_assertions = - clean/dirty auto-assertions not yet defined for {$kind} - -incremental_undefined_clean_dirty_assertions_item = - clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} - -incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument - -incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} - -incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized - -incremental_write_new = failed to write {$name} to `{$path}`: {$err} diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 0e04a2a784ec..3447836598bf 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -5,7 +5,7 @@ //! annotations. These annotations can be used to test whether paths //! exist in the graph. These checks run after codegen, so they view the //! the final state of the dependency graph. Note that there are -//! similar assertions found in `persist::dirty_clean` which check the +//! similar assertions found in `persist::clean` which check the //! **initial** state of the dependency graph, just after it has been //! loaded from disk. //! @@ -39,14 +39,16 @@ use std::io::Write; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING}; +use rustc_hir::Attribute; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; +use rustc_middle::bug; use rustc_middle::dep_graph::{ DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, dep_kinds, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; -use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use tracing::debug; use {rustc_graphviz as dot, rustc_hir as hir}; @@ -105,29 +107,13 @@ struct IfThisChanged<'tcx> { } impl<'tcx> IfThisChanged<'tcx> { - fn argument(&self, attr: &hir::Attribute) -> Option { - let mut value = None; - for list_item in attr.meta_item_list().unwrap_or_default() { - match list_item.ident() { - Some(ident) if list_item.is_word() && value.is_none() => value = Some(ident.name), - _ => - // FIXME better-encapsulate meta_item (don't directly access `node`) - { - span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item) - } - } - } - value - } - fn process_attrs(&mut self, def_id: LocalDefId) { let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id()); let hir_id = self.tcx.local_def_id_to_hir_id(def_id); let attrs = self.tcx.hir_attrs(hir_id); for attr in attrs { - if attr.has_name(sym::rustc_if_this_changed) { - let dep_node_interned = self.argument(attr); - let dep_node = match dep_node_interned { + if let Attribute::Parsed(AttributeKind::RustcIfThisChanged(span, dep_node)) = *attr { + let dep_node = match dep_node { None => DepNode::from_def_path_hash( self.tcx, def_path_hash, @@ -136,36 +122,29 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => self.tcx.dcx().emit_fatal(errors::UnrecognizedDepNode { - span: attr.span(), - name: n, - }), + Err(()) => self + .tcx + .dcx() + .emit_fatal(errors::UnrecognizedDepNode { span, name: n }), } } }; - self.if_this_changed.push((attr.span(), def_id.to_def_id(), dep_node)); - } else if attr.has_name(sym::rustc_then_this_would_need) { - let dep_node_interned = self.argument(attr); - let dep_node = match dep_node_interned { - Some(n) => { - match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { - Ok(n) => n, - Err(()) => self.tcx.dcx().emit_fatal(errors::UnrecognizedDepNode { - span: attr.span(), - name: n, - }), - } - } - None => { - self.tcx.dcx().emit_fatal(errors::MissingDepNode { span: attr.span() }); - } - }; - self.then_this_would_need.push(( - attr.span(), - dep_node_interned.unwrap(), - hir_id, - dep_node, - )); + self.if_this_changed.push((span, def_id.to_def_id(), dep_node)); + } else if let Attribute::Parsed(AttributeKind::RustcThenThisWouldNeed( + _, + ref dep_nodes, + )) = *attr + { + for &n in dep_nodes { + let Ok(dep_node) = + DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) + else { + self.tcx + .dcx() + .emit_fatal(errors::UnrecognizedDepNode { span: n.span, name: n.name }); + }; + self.then_this_would_need.push((n.span, n.name, hir_id, dep_node)); + } } } } diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index dbc72d085be9..3354689d0ca3 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -1,10 +1,10 @@ use std::path::{Path, PathBuf}; use rustc_macros::Diagnostic; -use rustc_span::{Ident, Span, Symbol}; +use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(incremental_unrecognized_depnode)] +#[diag("unrecognized `DepNode` variant: {$name}")] pub(crate) struct UnrecognizedDepNode { #[primary_span] pub span: Span, @@ -12,28 +12,21 @@ pub(crate) struct UnrecognizedDepNode { } #[derive(Diagnostic)] -#[diag(incremental_missing_depnode)] -pub(crate) struct MissingDepNode { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(incremental_missing_if_this_changed)] +#[diag("no `#[rustc_if_this_changed]` annotation detected")] pub(crate) struct MissingIfThisChanged { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_ok)] +#[diag("OK")] pub(crate) struct Ok { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_no_path)] +#[diag("no path from `{$source}` to `{$target}`")] pub(crate) struct NoPath { #[primary_span] pub span: Span, @@ -42,7 +35,7 @@ pub(crate) struct NoPath { } #[derive(Diagnostic)] -#[diag(incremental_assertion_auto)] +#[diag("`except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"")] pub(crate) struct AssertionAuto<'a> { #[primary_span] pub span: Span, @@ -51,7 +44,7 @@ pub(crate) struct AssertionAuto<'a> { } #[derive(Diagnostic)] -#[diag(incremental_undefined_clean_dirty_assertions_item)] +#[diag("clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}")] pub(crate) struct UndefinedCleanDirtyItem { #[primary_span] pub span: Span, @@ -59,7 +52,7 @@ pub(crate) struct UndefinedCleanDirtyItem { } #[derive(Diagnostic)] -#[diag(incremental_undefined_clean_dirty_assertions)] +#[diag("clean/dirty auto-assertions not yet defined for {$kind}")] pub(crate) struct UndefinedCleanDirty { #[primary_span] pub span: Span, @@ -67,7 +60,7 @@ pub(crate) struct UndefinedCleanDirty { } #[derive(Diagnostic)] -#[diag(incremental_repeated_depnode_label)] +#[diag("dep-node label `{$label}` is repeated")] pub(crate) struct RepeatedDepNodeLabel<'a> { #[primary_span] pub span: Span, @@ -75,7 +68,7 @@ pub(crate) struct RepeatedDepNodeLabel<'a> { } #[derive(Diagnostic)] -#[diag(incremental_unrecognized_depnode_label)] +#[diag("dep-node label `{$label}` not recognized")] pub(crate) struct UnrecognizedDepNodeLabel<'a> { #[primary_span] pub span: Span, @@ -83,7 +76,7 @@ pub(crate) struct UnrecognizedDepNodeLabel<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_dirty)] +#[diag("`{$dep_node_str}` should be dirty but is not")] pub(crate) struct NotDirty<'a> { #[primary_span] pub span: Span, @@ -91,7 +84,7 @@ pub(crate) struct NotDirty<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_clean)] +#[diag("`{$dep_node_str}` should be clean but is not")] pub(crate) struct NotClean<'a> { #[primary_span] pub span: Span, @@ -99,7 +92,7 @@ pub(crate) struct NotClean<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_loaded)] +#[diag("`{$dep_node_str}` should have been loaded from disk but it was not")] pub(crate) struct NotLoaded<'a> { #[primary_span] pub span: Span, @@ -107,43 +100,13 @@ pub(crate) struct NotLoaded<'a> { } #[derive(Diagnostic)] -#[diag(incremental_unknown_rustc_clean_argument)] -pub(crate) struct UnknownRustcCleanArgument { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(incremental_no_cfg)] -pub(crate) struct NoCfg { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(incremental_associated_value_expected_for)] -pub(crate) struct AssociatedValueExpectedFor { - #[primary_span] - pub span: Span, - pub ident: Ident, -} - -#[derive(Diagnostic)] -#[diag(incremental_associated_value_expected)] -pub(crate) struct AssociatedValueExpected { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(incremental_unchecked_clean)] +#[diag("found unchecked `#[rustc_clean]` attribute")] pub(crate) struct UncheckedClean { #[primary_span] pub span: Span, } - #[derive(Diagnostic)] -#[diag(incremental_delete_old)] +#[diag("unable to delete old {$name} at `{$path}`: {$err}")] pub(crate) struct DeleteOld<'a> { pub name: &'a str, pub path: PathBuf, @@ -151,7 +114,7 @@ pub(crate) struct DeleteOld<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_new)] +#[diag("failed to create {$name} at `{$path}`: {$err}")] pub(crate) struct CreateNew<'a> { pub name: &'a str, pub path: PathBuf, @@ -159,7 +122,7 @@ pub(crate) struct CreateNew<'a> { } #[derive(Diagnostic)] -#[diag(incremental_write_new)] +#[diag("failed to write {$name} to `{$path}`: {$err}")] pub(crate) struct WriteNew<'a> { pub name: &'a str, pub path: PathBuf, @@ -167,14 +130,14 @@ pub(crate) struct WriteNew<'a> { } #[derive(Diagnostic)] -#[diag(incremental_canonicalize_path)] +#[diag("incremental compilation: error canonicalizing path `{$path}`: {$err}")] pub(crate) struct CanonicalizePath { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_create_incr_comp_dir)] +#[diag("could not create incremental compilation {$tag} directory `{$path}`: {$err}")] pub(crate) struct CreateIncrCompDir<'a> { pub tag: &'a str, pub path: &'a Path, @@ -182,96 +145,112 @@ pub(crate) struct CreateIncrCompDir<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_lock)] +#[diag("incremental compilation: could not create session directory lock file: {$lock_err}")] pub(crate) struct CreateLock<'a> { pub lock_err: std::io::Error, pub session_dir: &'a Path, - #[note(incremental_lock_unsupported)] + #[note( + "the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation" + )] pub is_unsupported_lock: bool, - #[help(incremental_cargo_help_1)] - #[help(incremental_cargo_help_2)] + #[help( + "incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)" + )] + #[help( + "the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)" + )] pub is_cargo: bool, } #[derive(Diagnostic)] -#[diag(incremental_delete_lock)] +#[diag("error deleting lock file for incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct DeleteLock<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_hard_link_failed)] +#[diag( + "hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`" +)] pub(crate) struct HardLinkFailed<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(incremental_delete_partial)] +#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")] pub(crate) struct DeletePartial<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_delete_full)] +#[diag("error deleting incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct DeleteFull<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_finalize)] +#[diag("error finalizing incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct Finalize<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_invalid_gc_failed)] +#[diag( + "failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}" +)] pub(crate) struct InvalidGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_finalized_gc_failed)] +#[diag( + "failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}" +)] pub(crate) struct FinalizedGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_session_gc_failed)] +#[diag("failed to garbage collect incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct SessionGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_assert_not_loaded)] +#[diag("we asserted that the incremental cache should not be loaded, but it was loaded")] pub(crate) struct AssertNotLoaded; #[derive(Diagnostic)] -#[diag(incremental_assert_loaded)] +#[diag( + "we asserted that an existing incremental cache directory should be successfully loaded, but it was not" +)] pub(crate) struct AssertLoaded; #[derive(Diagnostic)] -#[diag(incremental_delete_incompatible)] +#[diag( + "failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}" +)] pub(crate) struct DeleteIncompatible { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_load_dep_graph)] +#[diag("could not load dep-graph from `{$path}`: {$err}")] pub(crate) struct LoadDepGraph { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_move_dep_graph)] +#[diag("failed to move dependency graph from `{$from}` to `{$to}`: {$err}")] pub(crate) struct MoveDepGraph<'a> { pub from: &'a Path, pub to: &'a Path, @@ -279,14 +258,14 @@ pub(crate) struct MoveDepGraph<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_dep_graph)] +#[diag("failed to create dependency graph at `{$path}`: {$err}")] pub(crate) struct CreateDepGraph<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_copy_workproduct_to_cache)] +#[diag("error copying object file `{$from}` to incremental directory as `{$to}`: {$err}")] pub(crate) struct CopyWorkProductToCache<'a> { pub from: &'a Path, pub to: &'a Path, @@ -294,14 +273,16 @@ pub(crate) struct CopyWorkProductToCache<'a> { } #[derive(Diagnostic)] -#[diag(incremental_delete_workproduct)] +#[diag("file-system error deleting outdated file `{$path}`: {$err}")] pub(crate) struct DeleteWorkProduct<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_corrupt_file)] +#[diag( + "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant" +)] pub(crate) struct CorruptFile<'a> { pub path: &'a Path, } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index e750810c0119..591ade379e6a 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -21,5 +21,3 @@ pub fn provide(providers: &mut Providers) { providers.hooks.save_dep_graph = |tcx| tcx.sess.time("serialize_dep_graph", || persist::save_dep_graph(tcx)); } - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/clean.rs similarity index 73% rename from compiler/rustc_incremental/src/persist/dirty_clean.rs rename to compiler/rustc_incremental/src/persist/clean.rs index 71fb18895246..d83ba5a78bed 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -19,26 +19,22 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. -use rustc_ast::{self as ast, MetaItemInner}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; +use rustc_hir::attrs::{AttributeKind, RustcCleanAttribute}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{ - Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit, + Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, + intravisit, }; use rustc_middle::dep_graph::{DepNode, DepNodeExt, dep_kind_from_label, label_strs}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; -use rustc_span::{Span, Symbol, sym}; -use thin_vec::ThinVec; +use rustc_span::{Span, Symbol}; use tracing::debug; use crate::errors; -const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; -const EXCEPT: Symbol = sym::except; -const CFG: Symbol = sym::cfg; - // Base and Extra labels to build up the labels /// For typedef, constants, and statics @@ -127,14 +123,14 @@ const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; type Labels = UnordSet; -/// Represents the requested configuration by rustc_clean/dirty +/// Represents the requested configuration by rustc_clean struct Assertion { clean: Labels, dirty: Labels, loaded_from_disk: Labels, } -pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { +pub(crate) fn check_clean_annotations(tcx: TyCtxt<'_>) { if !tcx.sess.opts.unstable_opts.query_dep_graph { return; } @@ -145,24 +141,24 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { } tcx.dep_graph.with_ignore(|| { - let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() }; + let mut clean_visitor = CleanVisitor { tcx, checked_attrs: Default::default() }; let crate_items = tcx.hir_crate_items(()); for id in crate_items.free_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; @@ -171,67 +167,62 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { // Note that we cannot use the existing "unused attribute"-infrastructure // here, since that is running before codegen. This is also the reason why // all codegen-specific attributes are `AssumedUsed` in rustc_ast::feature_gate. - all_attrs.report_unchecked_attrs(dirty_clean_visitor.checked_attrs); + all_attrs.report_unchecked_attrs(clean_visitor.checked_attrs); }) } -struct DirtyCleanVisitor<'tcx> { +struct CleanVisitor<'tcx> { tcx: TyCtxt<'tcx>, - checked_attrs: FxHashSet, + checked_attrs: FxHashSet, } -impl<'tcx> DirtyCleanVisitor<'tcx> { - /// Possibly "deserialize" the attribute into a clean/dirty assertion - fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { - assert!(attr.has_name(sym::rustc_clean)); - if !check_config(self.tcx, attr) { - // skip: not the correct `cfg=` - return None; - } - let assertion = self.assertion_auto(item_id, attr); - Some(assertion) +impl<'tcx> CleanVisitor<'tcx> { + /// Convert the attribute to an [`Assertion`] if the relevant cfg is active + fn assertion_maybe( + &mut self, + item_id: LocalDefId, + attr: &RustcCleanAttribute, + ) -> Option { + self.tcx + .sess + .psess + .config + .contains(&(attr.cfg, None)) + .then(|| self.assertion_auto(item_id, attr)) } /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels. - fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion { - let (name, mut auto) = self.auto_labels(item_id, attr); + fn assertion_auto(&mut self, item_id: LocalDefId, attr: &RustcCleanAttribute) -> Assertion { + let (name, mut auto) = self.auto_labels(item_id, attr.span); let except = self.except(attr); let loaded_from_disk = self.loaded_from_disk(attr); for e in except.items().into_sorted_stable_ord() { if !auto.remove(e) { - self.tcx.dcx().emit_fatal(errors::AssertionAuto { span: attr.span(), name, e }); + self.tcx.dcx().emit_fatal(errors::AssertionAuto { span: attr.span, name, e }); } } Assertion { clean: auto, dirty: except, loaded_from_disk } } /// `loaded_from_disk=` attribute value - fn loaded_from_disk(&self, attr: &Attribute) -> Labels { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(LOADED_FROM_DISK) { - let value = expect_associated_value(self.tcx, &item); - return self.resolve_labels(&item, value); - } - } - // If `loaded_from_disk=` is not specified, don't assert anything - Labels::default() + fn loaded_from_disk(&self, attr: &RustcCleanAttribute) -> Labels { + attr.loaded_from_disk + .as_ref() + .map(|queries| self.resolve_labels(&queries.entries, queries.span)) + .unwrap_or_default() } /// `except=` attribute value - fn except(&self, attr: &Attribute) -> Labels { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(EXCEPT) { - let value = expect_associated_value(self.tcx, &item); - return self.resolve_labels(&item, value); - } - } - // if no `label` or `except` is given, only the node's group are asserted - Labels::default() + fn except(&self, attr: &RustcCleanAttribute) -> Labels { + attr.except + .as_ref() + .map(|queries| self.resolve_labels(&queries.entries, queries.span)) + .unwrap_or_default() } /// Return all DepNode labels that should be asserted for this item. /// index=0 is the "name" used for error messages - fn auto_labels(&mut self, item_id: LocalDefId, attr: &Attribute) -> (&'static str, Labels) { + fn auto_labels(&mut self, item_id: LocalDefId, span: Span) -> (&'static str, Labels) { let node = self.tcx.hir_node_by_def_id(item_id); let (name, labels) = match node { HirNode::Item(item) => { @@ -282,7 +273,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL), _ => self.tcx.dcx().emit_fatal(errors::UndefinedCleanDirtyItem { - span: attr.span(), + span, kind: format!("{:?}", item.kind), }), } @@ -297,31 +288,31 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), }, - _ => self.tcx.dcx().emit_fatal(errors::UndefinedCleanDirty { - span: attr.span(), - kind: format!("{node:?}"), - }), + _ => self + .tcx + .dcx() + .emit_fatal(errors::UndefinedCleanDirty { span, kind: format!("{node:?}") }), }; let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); (name, labels) } - fn resolve_labels(&self, item: &MetaItemInner, value: Symbol) -> Labels { + fn resolve_labels(&self, values: &[Symbol], span: Span) -> Labels { let mut out = Labels::default(); - for label in value.as_str().split(',') { - let label = label.trim(); - if DepNode::has_label_string(label) { - if out.contains(label) { + for label in values { + let label_str = label.as_str(); + if DepNode::has_label_string(label_str) { + if out.contains(label_str) { self.tcx .dcx() - .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label }); + .emit_fatal(errors::RepeatedDepNodeLabel { span, label: label_str }); } - out.insert(label.to_string()); + out.insert(label_str.to_string()); } else { self.tcx .dcx() - .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label }); + .emit_fatal(errors::UnrecognizedDepNodeLabel { span, label: label_str }); } } out @@ -360,11 +351,18 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { fn check_item(&mut self, item_id: LocalDefId) { let item_span = self.tcx.def_span(item_id.to_def_id()); let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); - for attr in self.tcx.get_attrs(item_id, sym::rustc_clean) { + + let Some(attr) = + find_attr!(self.tcx.get_all_attrs(item_id), AttributeKind::RustcClean(attr) => attr) + else { + return; + }; + + for attr in attr { let Some(assertion) = self.assertion_maybe(item_id, attr) else { continue; }; - self.checked_attrs.insert(attr.id()); + self.checked_attrs.insert(attr.span); for label in assertion.clean.items().into_sorted_stable_ord() { let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_clean(item_span, dep_node); @@ -400,61 +398,24 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { } } -/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have -/// a cfg flag called `foo`. -fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { - debug!("check_config(attr={:?})", attr); - let config = &tcx.sess.psess.config; - debug!("check_config: config={:?}", config); - let mut cfg = None; - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(CFG) { - let value = expect_associated_value(tcx, &item); - debug!("check_config: searching for cfg {:?}", value); - cfg = Some(config.contains(&(value, None))); - } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { - tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() }); - } - } - - match cfg { - None => tcx.dcx().emit_fatal(errors::NoCfg { span: attr.span() }), - Some(c) => c, - } -} - -fn expect_associated_value(tcx: TyCtxt<'_>, item: &MetaItemInner) -> Symbol { - if let Some(value) = item.value_str() { - value - } else if let Some(ident) = item.ident() { - tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); - } else { - tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() }); - } -} - /// A visitor that collects all `#[rustc_clean]` attributes from /// the HIR. It is used to verify that we really ran checks for all annotated /// nodes. struct FindAllAttrs<'tcx> { tcx: TyCtxt<'tcx>, - found_attrs: Vec<&'tcx Attribute>, + found_attrs: Vec<&'tcx RustcCleanAttribute>, } impl<'tcx> FindAllAttrs<'tcx> { - fn is_active_attr(&mut self, attr: &Attribute) -> bool { - if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { - return true; - } - - false + fn is_active_attr(&self, attr: &RustcCleanAttribute) -> bool { + self.tcx.sess.psess.config.contains(&(attr.cfg, None)) } - fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { + fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { for attr in &self.found_attrs { - if !checked_attrs.contains(&attr.id()) { - self.tcx.dcx().emit_err(errors::UncheckedClean { span: attr.span() }); - checked_attrs.insert(attr.id()); + if !checked_attrs.contains(&attr.span) { + self.tcx.dcx().emit_err(errors::UncheckedClean { span: attr.span }); + checked_attrs.insert(attr.span); } } } @@ -468,8 +429,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { } fn visit_attribute(&mut self, attr: &'tcx Attribute) { - if self.is_active_attr(attr) { - self.found_attrs.push(attr); + if let Attribute::Parsed(AttributeKind::RustcClean(attrs)) = attr { + for attr in attrs { + if self.is_active_attr(attr) { + self.found_attrs.push(attr); + } + } } } } diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index f5d5167e0e2c..a3857967ab08 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -2,8 +2,8 @@ //! into the given directory. At the same time, it also hashes the //! various HIR nodes. +mod clean; mod data; -mod dirty_clean; mod file_format; mod fs; mod load; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 58fea3278a83..996ae162607d 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -2,7 +2,7 @@ use std::fs; use std::sync::Arc; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::sync::join; +use rustc_data_structures::sync::par_join; use rustc_middle::dep_graph::{ DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap, }; @@ -14,7 +14,7 @@ use tracing::debug; use super::data::*; use super::fs::*; -use super::{dirty_clean, file_format, work_product}; +use super::{clean, file_format, work_product}; use crate::assert_dep_graph::assert_dep_graph; use crate::errors; @@ -42,9 +42,9 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { let staging_dep_graph_path = staging_dep_graph_path(sess); sess.time("assert_dep_graph", || assert_dep_graph(tcx)); - sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)); + sess.time("check_clean", || clean::check_clean_annotations(tcx)); - join( + par_join( move || { sess.time("incr_comp_persist_dep_graph", || { if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) { diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 7fb9deaa1697..dc7fe03dcf3c 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] -#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))] +#![cfg_attr(all(feature = "nightly", test), feature(test))] +#![cfg_attr(feature = "nightly", feature(extend_one, step_trait))] #![cfg_attr(feature = "nightly", feature(new_range_api))] // tidy-alphabetical-end diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 08c036148849..c4fbe89315db 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -10,7 +10,6 @@ doctest = false # tidy-alphabetical-start rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl deleted file mode 100644 index e51734ff7a77..000000000000 --- a/compiler/rustc_infer/messages.ftl +++ /dev/null @@ -1,5 +0,0 @@ -infer_opaque_hidden_type = - opaque type's hidden type cannot be another opaque type from the same scope - .label = one of the two opaque types used here has to be outside its defining scope - .opaque_type = opaque type whose hidden type is being assigned - .hidden_type = opaque type being used as hidden type diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs index 76ea9c3433d3..7c6e3b4ef314 100644 --- a/compiler/rustc_infer/src/errors.rs +++ b/compiler/rustc_infer/src/errors.rs @@ -2,13 +2,13 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(infer_opaque_hidden_type)] +#[diag("opaque type's hidden type cannot be another opaque type from the same scope")] pub(crate) struct OpaqueHiddenTypeDiag { #[primary_span] - #[label] + #[label("one of the two opaque types used here has to be outside its defining scope")] pub span: Span, - #[note(infer_opaque_type)] + #[note("opaque type whose hidden type is being assigned")] pub opaque_type: Span, - #[note(infer_hidden_type)] + #[note("opaque type being used as hidden type")] pub hidden_type: Span, } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 23f6fee406a5..89ea6324d854 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -684,19 +684,19 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]), CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), CanonicalVarKind::PlaceholderTy(placeholder) => { - CanonicalVarKind::PlaceholderTy(ty::Placeholder::new( + CanonicalVarKind::PlaceholderTy(ty::PlaceholderType::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) } CanonicalVarKind::PlaceholderRegion(placeholder) => { - CanonicalVarKind::PlaceholderRegion(ty::Placeholder::new( + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) } CanonicalVarKind::PlaceholderConst(placeholder) => { - CanonicalVarKind::PlaceholderConst(ty::Placeholder::new( + CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c9ea420944e2..b57306536260 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -447,7 +447,7 @@ pub enum RegionVariableOrigin<'tcx> { /// Region variables created when instantiating a binder with /// existential variables, e.g. when calling a function or method. - BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime), + BoundRegion(Span, ty::BoundRegionKind<'tcx>, BoundRegionConversionTime), UpvarRegion(ty::UpvarId, Span), @@ -1099,22 +1099,45 @@ impl<'tcx> InferCtxt<'tcx> { // // Note: if these two lines are combined into one we get // dynamic borrow errors on `self.inner`. - let known = self.inner.borrow_mut().type_variables().probe(v).known(); - known.map_or(ty, |t| self.shallow_resolve(t)) + let (root_vid, value) = + self.inner.borrow_mut().type_variables().probe_with_root_vid(v); + value.known().map_or_else( + || if root_vid == v { ty } else { Ty::new_var(self.tcx, root_vid) }, + |t| self.shallow_resolve(t), + ) } ty::IntVar(v) => { - match self.inner.borrow_mut().int_unification_table().probe_value(v) { + let (root, value) = + self.inner.borrow_mut().int_unification_table().inlined_probe_key_value(v); + match value { ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), - ty::IntVarValue::Unknown => ty, + ty::IntVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_int_var(self.tcx, root) + } + } } } ty::FloatVar(v) => { - match self.inner.borrow_mut().float_unification_table().probe_value(v) { + let (root, value) = self + .inner + .borrow_mut() + .float_unification_table() + .inlined_probe_key_value(v); + match value { ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), - ty::FloatVarValue::Unknown => ty, + ty::FloatVarValue::Unknown => { + if root == v { + ty + } else { + Ty::new_float_var(self.tcx, root) + } + } } } @@ -1128,13 +1151,16 @@ impl<'tcx> InferCtxt<'tcx> { pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(infer_ct) => match infer_ct { - InferConst::Var(vid) => self - .inner - .borrow_mut() - .const_unification_table() - .probe_value(vid) - .known() - .unwrap_or(ct), + InferConst::Var(vid) => { + let (root, value) = self + .inner + .borrow_mut() + .const_unification_table() + .inlined_probe_key_value(vid); + value.known().unwrap_or_else(|| { + if root.vid == vid { ct } else { ty::Const::new_var(self.tcx, root.vid) } + }) + } InferConst::Fresh(_) => ct, }, ty::ConstKind::Param(_) @@ -1158,6 +1184,13 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } + /// If `ty` is an unresolved type variable, returns its root vid. + pub fn root_vid(&self, ty: Ty<'tcx>) -> Option { + let (root, value) = + self.inner.borrow_mut().type_variables().inlined_probe_with_vid(ty.ty_vid()?); + value.is_unknown().then_some(root) + } + pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) { self.inner.borrow_mut().type_variables().sub_unify(a, b); } @@ -1300,13 +1333,13 @@ impl<'tcx> InferCtxt<'tcx> { } impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { self.args[br.var.index()].expect_region() } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { self.args[bt.var.index()].expect_ty() } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { self.args[bc.var.index()].expect_const() } } 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 7be5daf61056..479daf67a8ba 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -91,7 +91,7 @@ pub(super) fn can_match_erased_ty<'tcx>( struct MatchAgainstHigherRankedOutlives<'tcx> { tcx: TyCtxt<'tcx>, pattern_depth: ty::DebruijnIndex, - map: FxHashMap>, + map: FxHashMap, ty::Region<'tcx>>, } impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { @@ -115,7 +115,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { #[instrument(level = "trace", skip(self))] fn bind( &mut self, - br: ty::BoundRegion, + br: ty::BoundRegion<'tcx>, value: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { match self.map.entry(br) { diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 7a0f70e979b8..324725a079bb 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -33,13 +33,13 @@ impl<'tcx> InferCtxt<'tcx> { let next_universe = self.create_next_universe(); let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { ty::Region::new_placeholder(self.tcx, ty::PlaceholderRegion::new(next_universe, br)) }, - types: &mut |bound_ty: ty::BoundTy| { + types: &mut |bound_ty: ty::BoundTy<'tcx>| { Ty::new_placeholder(self.tcx, ty::PlaceholderType::new(next_universe, bound_ty)) }, - consts: &mut |bound_const: ty::BoundConst| { + consts: &mut |bound_const: ty::BoundConst<'tcx>| { ty::Const::new_placeholder( self.tcx, ty::PlaceholderConst::new(next_universe, bound_const), diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 65f77fe8e25f..9b928cc5cc8c 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -258,6 +258,25 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { self.eq_relations().inlined_probe_value(vid) } + /// Retrieves the type to which `vid` has been instantiated, if + /// any, along with the root `vid`. + pub(crate) fn probe_with_root_vid( + &mut self, + vid: ty::TyVid, + ) -> (ty::TyVid, TypeVariableValue<'tcx>) { + self.inlined_probe_with_vid(vid) + } + + /// An always-inlined variant of `probe_with_root_vid`, for very hot call sites. + #[inline(always)] + pub(crate) fn inlined_probe_with_vid( + &mut self, + vid: ty::TyVid, + ) -> (ty::TyVid, TypeVariableValue<'tcx>) { + let (id, value) = self.eq_relations().inlined_probe_key_value(vid); + (id.vid, value) + } + #[inline] fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> { self.storage.eq_relations.with_log(self.undo_log) diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 05ea0f813818..008b5c94a5ea 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -14,7 +14,7 @@ // tidy-alphabetical-start #![allow(rustc::direct_use_of_rustc_type_ir)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(extend_one)] #![recursion_limit = "512"] // For rustdoc // tidy-alphabetical-end @@ -22,5 +22,3 @@ mod errors; pub mod infer; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index d785030b5f2c..c234e21b9254 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -19,7 +19,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } @@ -36,7 +35,6 @@ rustc_parse = { path = "../rustc_parse" } rustc_passes = { path = "../rustc_passes" } rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } -rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl deleted file mode 100644 index d898e9bf7d1e..000000000000 --- a/compiler/rustc_interface/messages.ftl +++ /dev/null @@ -1,56 +0,0 @@ -interface_abi_required_feature = - target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly - .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -interface_abi_required_feature_issue = for more information, see issue #116344 - -interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}` - -interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen - -interface_emoji_identifier = - identifiers cannot contain emoji: `{$ident}` - -interface_error_writing_dependencies = - error writing dependencies to `{$path}`: {$error} - -interface_failed_writing_file = - failed to write file {$path}: {$error}" - -interface_ferris_identifier = - Ferris cannot be used as an identifier - .suggestion = try using their name instead - -interface_generated_file_conflicts_with_directory = - the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}" - -interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag - -interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag - -interface_input_file_would_be_overwritten = - the input file "{$path}" would be overwritten by the generated executable - -interface_mixed_bin_crate = - cannot mix `bin` crate type with others - -interface_mixed_proc_macro_crate = - cannot mix `proc-macro` crate type with others - -interface_multiple_output_types_adaption = - due to multiple output types requested, the explicitly specified output file name will be adapted for each output type - -interface_multiple_output_types_to_stdout = can't use option `-o` or `--emit` to write multiple output types to stdout -interface_out_dir_error = - failed to find or create the directory specified by `--out-dir` - -interface_proc_macro_crate_panic_abort = - building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic - -interface_temps_dir_error = - failed to find or create the directory specified by `--temps-dir` - -interface_unsupported_crate_type_for_codegen_backend = - dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}` - -interface_unsupported_crate_type_for_target = - dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 3d8d5d59b118..5aa1616397f8 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -12,11 +12,10 @@ use std::fmt; use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC}; -use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef}; +use rustc_middle::dep_graph::dep_node::default_dep_kind_debug; +use rustc_middle::dep_graph::{DepContext, DepKind, DepNode, DepNodeExt, TaskDepsRef}; use rustc_middle::ty::tls; use rustc_query_impl::QueryCtxt; -use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; -use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { tls::with_context_opt(|icx| { @@ -107,9 +106,9 @@ pub fn dep_node_debug(node: DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fm 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 + rustc_middle::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 + rustc_middle::dep_graph::dep_node::DEP_NODE_DEBUG .swap(&(dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index aee8ec20e14d..7e4671889f57 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -7,7 +7,9 @@ use rustc_span::{Span, Symbol}; use rustc_target::spec::TargetTuple; #[derive(Diagnostic)] -#[diag(interface_crate_name_does_not_match)] +#[diag( + "`--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`" +)] pub(crate) struct CrateNameDoesNotMatch { #[primary_span] pub(crate) span: Span, @@ -16,23 +18,27 @@ pub(crate) struct CrateNameDoesNotMatch { } #[derive(Diagnostic)] -#[diag(interface_crate_name_invalid)] +#[diag("crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen")] pub(crate) struct CrateNameInvalid<'a> { pub(crate) crate_name: &'a str, } #[derive(Diagnostic)] -#[diag(interface_ferris_identifier)] +#[diag("Ferris cannot be used as an identifier")] pub struct FerrisIdentifier { #[primary_span] pub spans: Vec, - #[suggestion(code = "{ferris_fix}", applicability = "maybe-incorrect")] + #[suggestion( + "try using their name instead", + code = "{ferris_fix}", + applicability = "maybe-incorrect" + )] pub first_span: Span, pub ferris_fix: &'static str, } #[derive(Diagnostic)] -#[diag(interface_emoji_identifier)] +#[diag("identifiers cannot contain emoji: `{$ident}`")] pub struct EmojiIdentifier { #[primary_span] pub spans: Vec, @@ -40,86 +46,96 @@ pub struct EmojiIdentifier { } #[derive(Diagnostic)] -#[diag(interface_mixed_bin_crate)] +#[diag("cannot mix `bin` crate type with others")] pub struct MixedBinCrate; #[derive(Diagnostic)] -#[diag(interface_mixed_proc_macro_crate)] +#[diag("cannot mix `proc-macro` crate type with others")] pub struct MixedProcMacroCrate; #[derive(Diagnostic)] -#[diag(interface_error_writing_dependencies)] +#[diag("error writing dependencies to `{$path}`: {$error}")] pub struct ErrorWritingDependencies<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(interface_input_file_would_be_overwritten)] +#[diag("the input file \"{$path}\" would be overwritten by the generated executable")] pub struct InputFileWouldBeOverWritten<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(interface_generated_file_conflicts_with_directory)] +#[diag( + "the generated executable for the input file \"{$input_path}\" conflicts with the existing directory \"{$dir_path}\"" +)] pub struct GeneratedFileConflictsWithDirectory<'a> { pub input_path: &'a Path, pub dir_path: &'a Path, } #[derive(Diagnostic)] -#[diag(interface_temps_dir_error)] +#[diag("failed to find or create the directory specified by `--temps-dir`")] pub struct TempsDirError; #[derive(Diagnostic)] -#[diag(interface_out_dir_error)] +#[diag("failed to find or create the directory specified by `--out-dir`")] pub struct OutDirError; #[derive(Diagnostic)] -#[diag(interface_failed_writing_file)] +#[diag("failed to write file {$path}: {$error}\"")] pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(interface_proc_macro_crate_panic_abort)] +#[diag( + "building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic" +)] pub struct ProcMacroCratePanicAbort; #[derive(Diagnostic)] -#[diag(interface_multiple_output_types_adaption)] +#[diag( + "due to multiple output types requested, the explicitly specified output file name will be adapted for each output type" +)] pub struct MultipleOutputTypesAdaption; #[derive(Diagnostic)] -#[diag(interface_ignoring_extra_filename)] +#[diag("ignoring -C extra-filename flag due to -o flag")] pub struct IgnoringExtraFilename; #[derive(Diagnostic)] -#[diag(interface_ignoring_out_dir)] +#[diag("ignoring --out-dir flag due to -o flag")] pub struct IgnoringOutDir; #[derive(Diagnostic)] -#[diag(interface_multiple_output_types_to_stdout)] +#[diag("can't use option `-o` or `--emit` to write multiple output types to stdout")] pub struct MultipleOutputTypesToStdout; #[derive(Diagnostic)] -#[diag(interface_abi_required_feature)] -#[note] -#[note(interface_abi_required_feature_issue)] +#[diag( + "target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly" +)] +#[note( + "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 #116344 ")] pub(crate) struct AbiRequiredTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, } #[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_codegen_backend)] +#[diag("dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`")] pub(crate) struct UnsupportedCrateTypeForCodegenBackend { pub(crate) crate_type: CrateType, pub(crate) codegen_backend: &'static str, } #[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_target)] +#[diag("dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`")] pub(crate) struct UnsupportedCrateTypeForTarget<'a> { pub(crate) crate_type: CrateType, pub(crate) target_triple: &'a TargetTuple, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index f76e8d4632fc..34c064362168 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -7,7 +7,6 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::jobserver::{self, Proxy}; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; use rustc_middle::ty; @@ -17,8 +16,7 @@ use rustc_parse::lexer::StripTokens; use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::Recovery; use rustc_parse::parser::attr::AllowLeadingUnsafe; -use rustc_query_impl::QueryCtxt; -use rustc_query_system::query::print_query_stack; +use rustc_query_impl::{QueryCtxt, print_query_stack}; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; @@ -54,14 +52,9 @@ pub struct Compiler { pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { - let psess = ParseSess::emitter_with_note( - vec![ - crate::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, - ], - format!("this occurred on the command line: `--cfg={s}`"), - ); + let psess = ParseSess::emitter_with_note(format!( + "this occurred on the command line: `--cfg={s}`" + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { @@ -130,14 +123,9 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; for s in specs { - let psess = ParseSess::emitter_with_note( - vec![ - crate::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, - ], - format!("this occurred on the command line: `--check-cfg={s}`"), - ); + let psess = ParseSess::emitter_with_note(format!( + "this occurred on the command line: `--check-cfg={s}`" + )); let filename = FileName::cfg_spec_source_code(&s); const VISIT: &str = @@ -343,9 +331,6 @@ pub struct Config { /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for /// running rustc without having to save". (See #102759.) pub file_loader: Option>, - /// The list of fluent resources, used for lints declared with - /// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic). - pub locale_resources: Vec<&'static str>, pub lint_caps: FxHashMap, @@ -382,9 +367,6 @@ pub struct Config { pub make_codegen_backend: Option Box + Send>>, - /// Registry of diagnostics codes. - pub registry: Registry, - /// The inner atomic value is set to true when a feature marked as `internal` is /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. @@ -463,9 +445,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")), }; - let mut locale_resources = config.locale_resources; - locale_resources.push(codegen_backend.locale_resource()); - let mut sess = rustc_session::build_session( config.opts, CompilerIO { @@ -475,8 +454,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se temps_dir, }, bundle, - config.registry, - locale_resources, config.lint_caps, target, util::rustc_version_str().unwrap_or("unknown"), @@ -485,6 +462,8 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se ); codegen_backend.init(&sess); + sess.replaced_intrinsics = FxHashSet::from_iter(codegen_backend.replaced_intrinsics()); + sess.thin_lto_supported = codegen_backend.thin_lto_supported(); let cfg = parse_cfg(sess.dcx(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index ce2398fab919..b5e4a384861f 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -21,5 +21,3 @@ pub use queries::Linker; #[cfg(test)] mod tests; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f5fb8031ab0f..a2c11c608330 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -12,17 +12,17 @@ use rustc_codegen_ssa::{CodegenResults, CrateInfo}; use rustc_data_structures::indexmap::IndexMap; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal}; -use rustc_data_structures::{parallel, thousands}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal, par_fns}; +use rustc_data_structures::thousands; use rustc_errors::timings::TimingSection; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; -use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap}; use rustc_hir::definitions::Definitions; use rustc_hir::limit::Limit; +use rustc_hir::{Attribute, find_attr}; use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; use rustc_metadata::EncodedMetadata; @@ -582,7 +582,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P let deps_output = outputs.path(OutputType::DepInfo); let deps_filename = deps_output.as_path(); - let result: io::Result<()> = try { + let result = try { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let mut files: IndexMap)> = sess @@ -1052,8 +1052,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { let sess = tcx.sess; sess.time("misc_checking_1", || { - parallel!( - { + par_fns(&mut [ + &mut || { sess.time("looking_for_entry_point", || tcx.ensure_ok().entry_fn(())); sess.time("check_externally_implementable_items", || { tcx.ensure_ok().check_externally_implementable_items(()) @@ -1065,7 +1065,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { CStore::from_tcx(tcx).report_unused_deps(tcx); }, - { + &mut || { tcx.ensure_ok().exportable_items(LOCAL_CRATE); tcx.ensure_ok().stable_order_of_exportable_impls(LOCAL_CRATE); tcx.par_hir_for_each_module(|module| { @@ -1073,14 +1073,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.ensure_ok().check_mod_unstable_api_usage(module); }); }, - { + &mut || { // We force these queries to run, // since they might not otherwise get called. // This marks the corresponding crate-level attributes // as used, and ensures that their values are valid. tcx.ensure_ok().limits(()); - } - ); + }, + ]); }); rustc_hir_analysis::check_crate(tcx); @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { { tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } - if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure_ok().mir_coroutine_witnesses(def_id); - let _ = tcx.ensure_ok().check_coroutine_obligations( - tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), + if tcx.is_coroutine(def_id.to_def_id()) + && (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id())) + { + // Eagerly check the unsubstituted layout for cycles. + tcx.ensure_ok().layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(tcx.type_of(def_id).instantiate_identity()), ); - if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) { - // Eagerly check the unsubstituted layout for cycles. - tcx.ensure_ok().layout_of( - ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) - .as_query_input(tcx.type_of(def_id).instantiate_identity()), - ); - } } }); }); @@ -1156,39 +1152,39 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { } sess.time("misc_checking_3", || { - parallel!( - { + par_fns(&mut [ + &mut || { tcx.ensure_ok().effective_visibilities(()); - parallel!( - { + par_fns(&mut [ + &mut || { tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_private_in_public(module) }) }, - { + &mut || { tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_deathness(module) }); }, - { + &mut || { sess.time("lint_checking", || { rustc_lint::check_crate(tcx); }); }, - { + &mut || { tcx.ensure_ok().clashing_extern_declarations(()); - } - ); + }, + ]); }, - { + &mut || { sess.time("privacy_checking_modules", || { tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_privacy(module); }); }); - } - ); + }, + ]); // This check has to be run after all lints are done processing. We don't // define a lint filter, as all lint checks should have finished at this point. @@ -1227,7 +1223,7 @@ pub(crate) fn start_codegen<'tcx>( // Hook for tests. if let Some((def_id, _)) = tcx.entry_fn(()) - && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query) + && find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcDelayedBugFromInsideQuery) { tcx.ensure_ok().trigger_delayed_bug(def_id); } diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index a2c1f1dbeda6..bd08faa1ed3a 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -1,15 +1,14 @@ -use rustc_ast::attr; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_span::sym; fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option { let mut decls = None; for id in tcx.hir_free_items() { - let attrs = tcx.hir_attrs(id.hir_id()); - if attr::contains_name(attrs, sym::rustc_proc_macro_decls) { + if find_attr!(tcx.hir_attrs(id.hir_id()), AttributeKind::RustcProcMacroDecls) { decls = Some(id.owner_id.def_id); } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0f60e86e0ca3..5ebf898f45a3 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -6,8 +6,8 @@ use std::sync::atomic::AtomicBool; use rustc_abi::Align; use rustc_data_structures::profiling::TimePassesFormat; +use rustc_errors::ColorConfig; use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::{ColorConfig, registry}; use rustc_hir::attrs::{CollapseMacroDebuginfo, NativeLibKind}; use rustc_session::config::{ AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CoverageLevel, CoverageOptions, @@ -72,8 +72,6 @@ where sessopts, io, None, - registry::Registry::new(&[]), - vec![], Default::default(), target, "", @@ -379,7 +377,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -401,7 +399,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -423,13 +421,13 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { name: String::from("b"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -445,7 +443,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -467,7 +465,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -501,7 +499,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -528,7 +526,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -549,7 +547,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index b3889849430a..613b3c64efed 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -184,8 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals< use rustc_data_structures::defer; use rustc_data_structures::sync::FromDyn; use rustc_middle::ty::tls; - use rustc_query_impl::QueryCtxt; - use rustc_query_system::query::{QueryContext, break_query_cycles}; + use rustc_query_impl::{QueryCtxt, break_query_cycles}; let thread_stack_size = init_stack_size(thread_builder_diag); @@ -231,7 +230,12 @@ pub(crate) fn run_in_thread_pool_with_globals< .name("rustc query cycle handler".to_string()) .spawn(move || { let on_panic = defer(|| { - eprintln!("internal compiler error: query cycle handler thread panicked, aborting process"); + // Split this long string so that it doesn't cause rustfmt to + // give up on the entire builder expression. + // + const MESSAGE: &str = "\ +internal compiler error: query cycle handler thread panicked, aborting process"; + eprintln!("{MESSAGE}"); // We need to abort here as we failed to resolve the deadlock, // otherwise the compiler could just hang, process::abort(); @@ -244,12 +248,17 @@ pub(crate) fn run_in_thread_pool_with_globals< tls::with(|tcx| { // Accessing session globals is sound as they outlive `GlobalCtxt`. // They are needed to hash query keys containing spans or symbols. - let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || { - // Ensure there was no errors collecting all active jobs. - // We need the complete map to ensure we find a cycle to break. - QueryCtxt::new(tcx).collect_active_jobs(false).expect("failed to collect active queries in deadlock handler") - }); - break_query_cycles(query_map, ®istry); + let job_map = rustc_span::set_session_globals_then( + unsafe { &*(session_globals as *const SessionGlobals) }, + || { + // Ensure there were no errors collecting all active jobs. + // We need the complete map to ensure we find a cycle to break. + QueryCtxt::new(tcx).collect_active_jobs_from_all_queries(false).expect( + "failed to collect active queries in deadlock handler", + ) + }, + ); + break_query_cycles(job_map, ®istry); }) }) }); @@ -351,10 +360,6 @@ pub struct DummyCodegenBackend { } impl CodegenBackend for DummyCodegenBackend { - fn locale_resource(&self) -> &'static str { - "" - } - fn name(&self) -> &'static str { "dummy" } diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs deleted file mode 100644 index 165262b82c75..000000000000 --- a/compiler/rustc_lexer/src/cursor.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::str::Chars; - -pub enum FrontmatterAllowed { - Yes, - No, -} - -/// Peekable iterator over a char sequence. -/// -/// Next characters can be peeked via `first` method, -/// and position can be shifted forward via `bump` method. -pub struct Cursor<'a> { - len_remaining: usize, - /// Iterator over chars. Slightly faster than a &str. - chars: Chars<'a>, - pub(crate) frontmatter_allowed: FrontmatterAllowed, - #[cfg(debug_assertions)] - prev: char, -} - -pub(crate) const EOF_CHAR: char = '\0'; - -impl<'a> Cursor<'a> { - pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { - Cursor { - len_remaining: input.len(), - chars: input.chars(), - frontmatter_allowed, - #[cfg(debug_assertions)] - prev: EOF_CHAR, - } - } - - pub fn as_str(&self) -> &'a str { - self.chars.as_str() - } - - /// Returns the last eaten symbol (or `'\0'` in release builds). - /// (For debug assertions only.) - pub(crate) fn prev(&self) -> char { - #[cfg(debug_assertions)] - { - self.prev - } - - #[cfg(not(debug_assertions))] - { - EOF_CHAR - } - } - - /// Peeks the next symbol from the input stream without consuming it. - /// If requested position doesn't exist, `EOF_CHAR` is returned. - /// However, getting `EOF_CHAR` doesn't always mean actual end of file, - /// it should be checked with `is_eof` method. - pub fn first(&self) -> char { - // `.next()` optimizes better than `.nth(0)` - self.chars.clone().next().unwrap_or(EOF_CHAR) - } - - /// Peeks the second symbol from the input stream without consuming it. - pub(crate) fn second(&self) -> char { - // `.next()` optimizes better than `.nth(1)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Peeks the third symbol from the input stream without consuming it. - pub fn third(&self) -> char { - // `.next()` optimizes better than `.nth(2)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Checks if there is nothing more to consume. - pub(crate) fn is_eof(&self) -> bool { - self.chars.as_str().is_empty() - } - - /// Returns amount of already consumed symbols. - pub(crate) fn pos_within_token(&self) -> u32 { - (self.len_remaining - self.chars.as_str().len()) as u32 - } - - /// Resets the number of bytes consumed to 0. - pub(crate) fn reset_pos_within_token(&mut self) { - self.len_remaining = self.chars.as_str().len(); - } - - /// Moves to the next character. - pub(crate) fn bump(&mut self) -> Option { - let c = self.chars.next()?; - - #[cfg(debug_assertions)] - { - self.prev = c; - } - - Some(c) - } - - /// Moves to a substring by a number of bytes. - pub(crate) fn bump_bytes(&mut self, n: usize) { - self.chars = self.as_str()[n..].chars(); - } - - /// Eats symbols while predicate returns true or until the end of file is reached. - pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - // It was tried making optimized version of this for eg. line comments, but - // LLVM can inline all of this and compile it down to fast iteration over bytes. - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } - - pub(crate) fn eat_until(&mut self, byte: u8) { - self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { - Some(index) => self.as_str()[index..].chars(), - None => "".chars(), - } - } -} diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 27ffcbc943bd..9d3da6ef4930 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -25,15 +25,13 @@ #![deny(unstable_features)] // tidy-alphabetical-end -mod cursor; - #[cfg(test)] mod tests; +use std::str::Chars; + use LiteralKind::*; use TokenKind::*; -use cursor::EOF_CHAR; -pub use cursor::{Cursor, FrontmatterAllowed}; pub use unicode_ident::UNICODE_VERSION; use unicode_properties::UnicodeEmoji; @@ -407,7 +405,129 @@ pub fn is_ident(string: &str) -> bool { } } -impl Cursor<'_> { +pub enum FrontmatterAllowed { + Yes, + No, +} + +/// Peekable iterator over a char sequence. +/// +/// Next characters can be peeked via `first` method, +/// and position can be shifted forward via `bump` method. +pub struct Cursor<'a> { + len_remaining: usize, + /// Iterator over chars. Slightly faster than a &str. + chars: Chars<'a>, + pub(crate) frontmatter_allowed: FrontmatterAllowed, + #[cfg(debug_assertions)] + prev: char, +} + +const EOF_CHAR: char = '\0'; + +impl<'a> Cursor<'a> { + pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { + Cursor { + len_remaining: input.len(), + chars: input.chars(), + frontmatter_allowed, + #[cfg(debug_assertions)] + prev: EOF_CHAR, + } + } + + pub fn as_str(&self) -> &'a str { + self.chars.as_str() + } + + /// Returns the last eaten symbol (or `'\0'` in release builds). + /// (For debug assertions only.) + pub(crate) fn prev(&self) -> char { + #[cfg(debug_assertions)] + { + self.prev + } + + #[cfg(not(debug_assertions))] + { + EOF_CHAR + } + } + + /// Peeks the next symbol from the input stream without consuming it. + /// If requested position doesn't exist, `EOF_CHAR` is returned. + /// However, getting `EOF_CHAR` doesn't always mean actual end of file, + /// it should be checked with `is_eof` method. + pub fn first(&self) -> char { + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) + } + + /// Peeks the second symbol from the input stream without consuming it. + pub(crate) fn second(&self) -> char { + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Peeks the third symbol from the input stream without consuming it. + pub fn third(&self) -> char { + // `.next()` optimizes better than `.nth(2)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Checks if there is nothing more to consume. + pub(crate) fn is_eof(&self) -> bool { + self.chars.as_str().is_empty() + } + + /// Returns amount of already consumed symbols. + pub(crate) fn pos_within_token(&self) -> u32 { + (self.len_remaining - self.chars.as_str().len()) as u32 + } + + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_pos_within_token(&mut self) { + self.len_remaining = self.chars.as_str().len(); + } + + /// Moves to the next character. + pub(crate) fn bump(&mut self) -> Option { + let c = self.chars.next()?; + + #[cfg(debug_assertions)] + { + self.prev = c; + } + + Some(c) + } + + /// Moves to a substring by a number of bytes. + pub(crate) fn bump_bytes(&mut self, n: usize) { + self.chars = self.as_str()[n..].chars(); + } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } + + pub(crate) fn eat_until(&mut self, byte: u8) { + self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { + Some(index) => self.as_str()[index..].chars(), + None => "".chars(), + } + } + /// Parses a token from the input string. pub fn advance_token(&mut self) -> Token { let Some(first_char) = self.bump() else { diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 035d8b4903fa..758d2762a6af 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -14,7 +14,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } 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_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl deleted file mode 100644 index 867b937d4090..000000000000 --- a/compiler/rustc_lint/messages.ftl +++ /dev/null @@ -1,1069 +0,0 @@ -lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - .suggestion = use `crate` - -lint_ambiguous_glob_reexport = ambiguous glob re-exports - .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here - .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here - -lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected - .example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` - .negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal - .current_behavior = add parentheses around the literal and the method call to keep the current behavior - -lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses - .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses - .cast_suggestion = use untyped pointers to only compare their addresses - .expect_suggestion = or expect the lint to compare the pointers metadata and addresses - -lint_associated_const_elided_lifetime = {$elided -> - [true] `&` without an explicit lifetime name cannot be used here - *[false] `'_` cannot be used here - } - .suggestion = use the `'static` lifetime - .note = cannot automatically infer `'static` because of other lifetimes in scope - -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`, but these cannot be relaxed without a breaking API change - -lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering - .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` - -lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write - .label = invalid failure ordering - .help = consider using `Acquire` or `Relaxed` failure ordering instead - -lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering - .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` - -lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering - .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` - -lint_attr_crate_level = - this attribute can only be applied at the crate level - .suggestion = to apply to the crate, use an inner attribute - .note = read for more information - -lint_bad_attribute_argument = bad attribute argument - -lint_bad_opt_access = {$msg} - -lint_break_with_label_and_loop = this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression - .suggestion = wrap this expression in parentheses - -lint_builtin_allow_internal_unsafe = - `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site - -lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition - .suggestion = try naming the parameter or explicitly ignoring it - -lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature - .previous_decl_label = `{$orig}` previously declared here - .mismatch_label = this signature doesn't match the previous declaration - -lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature - .previous_decl_label = `{$orig}` previously declared here - .mismatch_label = this signature doesn't match the previous declaration -lint_builtin_const_no_mangle = const items should never be `#[no_mangle]` - .suggestion = try a static value - -lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function -lint_builtin_decl_unsafe_method = declaration of an `unsafe` method - -lint_builtin_deref_nullptr = dereferencing a null pointer - .label = this code causes undefined behavior when executed - -lint_builtin_double_negations = use of a double negation - .note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages - .note_decrement = use `-= 1` if you meant to decrement the value - .add_parens_suggestion = add parentheses for clarity - -lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated - .suggestion = use `..=` for an inclusive range - -lint_builtin_explicit_outlives = outlives requirements can be inferred - .suggestion = remove {$count -> - [one] this bound - *[other] these bounds - } - -lint_builtin_export_name_fn = declaration of a function with `export_name` -lint_builtin_export_name_method = declaration of a method with `export_name` -lint_builtin_export_name_static = declaration of a static with `export_name` - -lint_builtin_global_asm = usage of `core::arch::global_asm` -lint_builtin_global_macro_unsafety = using this macro is unsafe even though it does not need an `unsafe` block - -lint_builtin_impl_unsafe_method = implementation of an `unsafe` method - -lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes - .note = see issue #{$n} for more information - .help = consider using `min_{$name}` instead, which is more stable and complete - -lint_builtin_internal_features = the feature `{$name}` is internal to the compiler or standard library - .note = using it is strongly discouraged - -lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition - .suggestion = you can use a raw identifier to stay compatible - -lint_builtin_link_section_fn = declaration of a function with `link_section` - -lint_builtin_link_section_static = declaration of a static with `link_section` - -lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy` - -lint_builtin_missing_debug_impl = - type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation - -lint_builtin_missing_doc = missing documentation for {$article} {$desc} - -lint_builtin_mutable_transmutes = - transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell - -lint_builtin_no_mangle_fn = declaration of a `no_mangle` function -lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled - .suggestion = remove this attribute - -lint_builtin_no_mangle_method = declaration of a `no_mangle` method -lint_builtin_no_mangle_static = declaration of a `no_mangle` static -lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant - .suggestion = use shorthand field pattern - -lint_builtin_overridden_symbol_name = - the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -lint_builtin_overridden_symbol_section = - the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them - -lint_builtin_special_module_name_used_lib = found module declaration for lib.rs - .note = lib.rs is the root of this crate's library target - .help = to refer to it from other targets, use the library's name as the path - -lint_builtin_special_module_name_used_main = found module declaration for main.rs - .note = a binary crate cannot be used as library - -lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters - -lint_builtin_type_alias_bounds_enable_feat_help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics -lint_builtin_type_alias_bounds_label = will not be checked at usage sites of the type alias -lint_builtin_type_alias_bounds_limitation_note = this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information -lint_builtin_type_alias_bounds_param_bounds = bounds on generic parameters in type aliases are not enforced - .suggestion = remove {$count -> - [one] this bound - *[other] these bounds - } -lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg = fully qualify this associated type -lint_builtin_type_alias_bounds_where_clause = where clauses on type aliases are not enforced - .suggestion = remove this where clause - -lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed -lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - -lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized - -lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization -lint_builtin_unreachable_pub = unreachable `pub` {$what} - .suggestion = consider restricting its visibility - .help = or consider exporting it for use by other crates - -lint_builtin_unsafe_block = usage of an `unsafe` block - -lint_builtin_unsafe_extern_block = usage of an `unsafe extern` block - -lint_builtin_unsafe_impl = implementation of an `unsafe` trait - -lint_builtin_unsafe_trait = declaration of an `unsafe` trait - -lint_builtin_unstable_features = use of an unstable feature - -lint_builtin_unused_doc_comment = unused doc comment - .label = rustdoc does not generate documentation for {$kind} - .plain_help = use `//` for a plain comment - .block_help = use `/* */` for a plain comment - -lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` - .suggestion = use `loop` - -lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}` - -lint_closure_returning_async_block = closure returning async block can be made into an async closure - .label = this async block can be removed, and the closure can be turned into an async closure - .suggestion = turn this into an async closure - -lint_command_line_source = `forbid` lint level was set on command line - -lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike - .current_use = this identifier can be confused with `{$existing_sym}` - .other_use = other identifier used here - -lint_const_item_interior_mutations = - mutation of an interior mutable `const` item with call to `{$method_name}` - .label = `{$const_name}` is a interior mutable `const` item of type `{$const_ty}` - .temporary = each usage of a `const` item creates a new temporary - .never_original = only the temporaries and never the original `const {$const_name}` will be modified - .suggestion_static = for a shared instance of `{$const_name}`, consider making it a `static` item instead - .help = for more details on interior mutability see - -lint_dangling_pointers_from_locals = {$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}` - .ret_ty = return type is `{$ret_ty}` - .local_var = local variable `{$local_var_name}` is dropped at the end of the {$fn_kind} - .created_at = dangling pointer created here - .note_safe = a dangling pointer is safe, but dereferencing one is undefined behavior - .note_more_info = for more information, see - -lint_dangling_pointers_from_temporaries = this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement - .label_ptr = pointer created here - .label_temporary = this `{$ty}` is dropped at end of statement - .help_bind = bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}` - .note_safe = a dangling pointer is safe, but dereferencing one is undefined behavior - .note_return = returning a pointer to a local variable will always result in a dangling pointer - .note_more_info = for more information, see - - -lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance - .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary - -lint_default_source = `forbid` lint level is the default for {$id} - -lint_deprecated_lint_name = - lint name `{$name}` is deprecated and may not have an effect in the future - .suggestion = change it to - .help = change it to {$replace} - -lint_deprecated_where_clause_location = where clause not allowed here - .note = see issue #89122 for more information - .suggestion_move_to_end = move it to the end of the type declaration - .suggestion_remove_where = remove this `where` - -lint_doc_alias_duplicated = doc alias is duplicated - .label = first defined here - -lint_doc_auto_cfg_expects_hide_or_show = - only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]` - -lint_doc_auto_cfg_hide_show_expects_list = - `#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items - -lint_doc_auto_cfg_hide_show_unexpected_item = - `#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items - -lint_doc_auto_cfg_wrong_literal = - expected boolean for `#[doc(auto_cfg = ...)]` - -lint_doc_invalid = - invalid `doc` attribute - -lint_doc_test_literal = `#![doc(test(...)]` does not take a literal - -lint_doc_test_takes_list = - `#[doc(test(...)]` takes a list of attributes - -lint_doc_test_unknown = - unknown `doc(test)` attribute `{$name}` - -lint_doc_unknown_any = - unknown `doc` attribute `{$name}` - -lint_doc_unknown_include = - unknown `doc` attribute `include` - .suggestion = use `doc = include_str!` instead - -lint_doc_unknown_passes = - unknown `doc` attribute `{$name}` - .note = `doc` attribute `{$name}` no longer functions; see issue #44136 - .label = no longer functions - .no_op_note = `doc({$name})` is now a no-op - -lint_doc_unknown_plugins = - unknown `doc` attribute `plugins` - .note = `doc` attribute `plugins` no longer functions; see issue #44136 and CVE-2018-1000622 - .label = no longer functions - .no_op_note = `doc(plugins)` is now a no-op - -lint_doc_unknown_spotlight = - unknown `doc` attribute `spotlight` - .note = `doc(spotlight)` was renamed to `doc(notable_trait)` - .suggestion = use `notable_trait` instead - .no_op_note = `doc(spotlight)` is now a no-op - - -lint_drop_glue = - types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped - -lint_drop_trait_constraints = - bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped - -lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing - .label = argument has type `{$arg_ty}` - -lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing - .label = argument has type `{$arg_ty}` - -lint_empty_attribute = - unused attribute - .suggestion = {$valid_without_list -> - [true] remove these parentheses - *[other] remove this attribute - } - .note = {$valid_without_list -> - [true] using `{$attr_path}` with an empty list is equivalent to not using a list at all - *[other] using `{$attr_path}` with an empty list has no effect - } - --lint_previously_accepted = - this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -lint_enum_intrinsics_mem_discriminant = - the return value of `mem::discriminant` is unspecified when called with a non-enum type - .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum - -lint_enum_intrinsics_mem_variant = - the return value of `mem::variant_count` is unspecified when called with a non-enum type - .note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum - -lint_expectation = this lint expectation is unfulfilled - .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message - .rationale = {$rationale} - -lint_for_loops_over_fallibles = - for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement - .suggestion = consider using `if let` to clear intent - .remove_next = to iterate over `{$recv_snip}` remove the call to `next` - .use_while_let = to check pattern in a loop use `while let` - .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents - -lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing - .label = argument has type `{$arg_ty}` - -lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing - .label = argument has type `{$arg_ty}` - -lint_function_casts_as_integer = direct cast of function item into an integer - .cast_as_fn = first cast to a pointer `as *const ()` - -lint_hidden_glob_reexport = private item shadows public glob re-export - .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here - .note_private_item = but the private item here shadows it - -lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated - -lint_identifier_non_ascii_char = identifier contains non-ASCII characters - -lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> - [one] { $identifier_type -> - [Exclusion] a character from an archaic script - [Technical] a character that is for non-linguistic, specialized usage - [Limited_Use] a character from a script in limited use - [Not_NFKC] a non normalized (NFKC) character - *[other] an uncommon character - } - *[other] { $identifier_type -> - [Exclusion] {$codepoints_len} characters from archaic scripts - [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage - [Limited_Use] {$codepoints_len} characters from scripts in limited use - [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters - *[other] uncommon characters - } -}: {$codepoints} - .note = {$codepoints_len -> - [one] this character is - *[other] these characters are - } included in the{$identifier_type -> - [Restricted] {""} - *[other] {" "}{$identifier_type} - } Unicode general security profile - -lint_if_let_dtor = {$dtor_kind -> - [dyn] value may invoke a custom destructor because it contains a trait object - *[concrete] value invokes this custom destructor - } - -lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 - .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion - .help = the value is now dropped here in Edition 2024 - .suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 - -lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level - -lint_ill_formed_attribute_input = {$num_suggestions -> - [1] attribute must be of the form {$suggestions} - *[other] valid forms for the attribute are {$suggestions} - } - .note = for more information, visit <{$docs}> - -lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024 - .note = specifically, {$num_captured -> - [one] this lifetime is - *[other] these lifetimes are - } in scope but not mentioned in the type's bounds - .note2 = all lifetimes in scope will be captured by `impl Trait`s in edition 2024 - -lint_impl_trait_redundant_captures = all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - .suggestion = remove the `use<...>` syntax - -lint_implicit_sysroot_crate_import = dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot - .help = try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate - -lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dereference of a raw pointer - .note = creating a reference requires the pointer target to be valid and imposes aliasing requirements - .raw_ptr = this raw pointer has type `{$raw_ptr_ty}` - .autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}` - .overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations - .method_def = method calls to `{$method_name}` require a reference - .suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit - -lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe - .label = not FFI-safe - .note = the type is defined here - -lint_improper_ctypes_array_help = consider passing a pointer to the array - -lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe -lint_improper_ctypes_box = box cannot be represented as a single pointer - -lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead - -lint_improper_ctypes_char_reason = the `char` type has no C equivalent - -lint_improper_ctypes_cstr_help = - consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` -lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout - -lint_improper_ctypes_dyn = trait objects have no C equivalent - -lint_improper_ctypes_enum_repr_help = - consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - -lint_improper_ctypes_enum_repr_reason = enum has no representation hint -lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead - -lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention -lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive -lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants - -lint_improper_ctypes_only_phantomdata = composed only of `PhantomData` - -lint_improper_ctypes_opaque = opaque types have no C equivalent - -lint_improper_ctypes_slice_help = consider using a raw pointer instead - -lint_improper_ctypes_slice_reason = slices have no C equivalent -lint_improper_ctypes_str_help = consider using `*const u8` and a length instead - -lint_improper_ctypes_str_reason = string slices have no C equivalent -lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct - -lint_improper_ctypes_struct_fieldless_reason = this struct has no fields -lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - -lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout -lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive -lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields - -lint_improper_ctypes_tuple_help = consider using a struct instead - -lint_improper_ctypes_tuple_reason = tuples have unspecified layout -lint_improper_ctypes_union_fieldless_help = consider adding a member to this union - -lint_improper_ctypes_union_fieldless_reason = this union has no fields -lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union - -lint_improper_ctypes_union_layout_reason = this union has unspecified layout -lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive - -lint_improper_ctypes_unsafe_binder = unsafe binders are incompatible with foreign function interfaces - -lint_improper_gpu_kernel_arg = passing type `{$ty}` to a function with "gpu-kernel" ABI may have unexpected behavior - .help = use primitive types and raw pointers to get reliable behavior - -lint_incorrect_do_not_recommend_args = - `#[diagnostic::do_not_recommend]` does not expect any arguments - -lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance - .note = this is dangerous because dereferencing the resulting pointer is undefined behavior - .note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - .help_transmute = for more information about transmute, see - .help_exposed_provenance = for more information about exposed provenance, see - .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance - .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` - -lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly - .label = use a different label that doesn't start with `0` or `1` - .help = start numbering with `2` instead - .note1 = an LLVM bug makes these labels ambiguous with a binary literal number on x86 - .note2 = see for more information - -lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly - .help = only local labels of the form `:` should be used in inline asm - .note1 = format arguments may expand to a non-numeric value - .note2 = see the asm section of Rust By Example for more information -lint_invalid_asm_label_named = avoid using named labels in inline assembly - .help = only local labels of the form `:` should be used in inline asm - .note = see the asm section of Rust By Example for more information -lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro - -lint_invalid_crate_type_value = invalid `crate_type` value - .suggestion = did you mean - -# FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error - .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes - -# FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_unchecked = calls to `{$method}` with an invalid literal are undefined behavior - .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes - -lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be directly compared to itself - .suggestion = use `f32::is_nan()` or `f64::is_nan()` instead - -lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable - -lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused - .origin = null pointer originates from here - .doc = for more information, visit and - -lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - .label = casting happened here - -lint_invalid_reference_casting_bigger_layout = casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused - .label = casting happened here - .alloc = backing allocation comes from here - .layout = casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes) - -lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - .label = casting happened here - -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_invalid_style = {$is_used_as_inner -> - [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]` - *[other] the `#![{$name}]` attribute can only be used at the crate root - } - .note = this attribute does not have an `!`, which means it is applied to this {$target} - -lint_invalid_target = `#[{$name}]` attribute cannot be used on {$target} - .warn = {-lint_previously_accepted} - .help = `#[{$name}]` can {$only}be applied to {$applied} - .suggestion = remove the attribute - -lint_lintpass_by_hand = implementing `LintPass` by hand - .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead - -lint_macro_expr_fragment_specifier_2024_migration = - the `expr` fragment specifier will accept more expressions in the 2024 edition - .suggestion = to keep the existing behavior, use the `expr_2021` fragment specifier - -lint_malformed_attribute = malformed lint attribute input - -lint_map_unit_fn = `Iterator::map` call that discard the iterator's values - .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated - .function_label = this function returns `()`, which is likely not what you wanted - .argument_label = called `Iterator::map` with callable that returns `()` - .map_label = after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items - .suggestion = you might have meant to use `Iterator::for_each` - -lint_mismatched_lifetime_syntaxes_eliding_while_named = - eliding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_help = - the same lifetime is referred to in inconsistent ways, making the signature confusing - -lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named = - hiding or eliding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_hiding_while_elided = - hiding a lifetime that's elided elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_hiding_while_named = - hiding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_input_elided = - the lifetime is elided here - -lint_mismatched_lifetime_syntaxes_input_hidden = - the lifetime is hidden here - -lint_mismatched_lifetime_syntaxes_input_named = - the lifetime is named here - -lint_mismatched_lifetime_syntaxes_output_elided = - the same lifetime is elided here - -lint_mismatched_lifetime_syntaxes_output_hidden = - the same lifetime is hidden here - -lint_mismatched_lifetime_syntaxes_output_named = - the same lifetime is named here - -lint_mismatched_lifetime_syntaxes_suggestion_explicit = - consistently use `{$lifetime_name}` - -lint_mismatched_lifetime_syntaxes_suggestion_implicit = - remove the lifetime name from references - -lint_mismatched_lifetime_syntaxes_suggestion_mixed = - remove the lifetime name from references and use `'_` for type paths - -lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths = - use `'_` for type paths - -lint_missing_gpu_kernel_export_name = function with the "gpu-kernel" ABI has a mangled name - .note = mangled names make it hard to find the kernel, this is usually not intended - .help = use `unsafe(no_mangle)` or `unsafe(export_name = "")` - -lint_mixed_script_confusables = - the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables - .includes_note = the usage includes {$includes} - .note = please recheck to make sure their usages are indeed what you want - -lint_multiple_supertrait_upcastable = `{$ident}` is dyn-compatible and has multiple supertraits - -lint_named_argument_used_positionally = named argument `{$named_arg_name}` is not used by name - .label_named_arg = this named argument is referred to by position in formatting string - .label_position_arg = this formatting argument uses named argument `{$named_arg_name}` by position - .suggestion = use the named argument by name to avoid ambiguity - -lint_node_source = `forbid` level set here - .note = {$reason} - -lint_non_binding_let_multi_drop_fn = - consider immediately dropping the value using `drop(..)` after the `let` statement - -lint_non_binding_let_multi_suggestion = - consider immediately dropping the value - -lint_non_binding_let_on_drop_type = - non-binding let on a type that has a destructor - -lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock - .label = this lock is not assigned to a binding and is immediately dropped - -lint_non_binding_let_suggestion = - consider binding to an unused variable to avoid immediately dropping the value - -lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name - .suggestion = convert the identifier to upper camel case - .label = should have an UpperCamelCase name - -lint_non_fmt_panic = panic message is not a string literal - .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021 - .more_info_note = for more information, see - .supports_fmt_note = the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here - .supports_fmt_suggestion = remove the `format!(..)` macro call - .display_suggestion = add a "{"{"}{"}"}" format string to `Display` the message - .debug_suggestion = - add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}` - .panic_suggestion = {$already_suggested -> - [true] or use - *[false] use - } std::panic::panic_any instead - -lint_non_fmt_panic_braces = - panic message contains {$count -> - [one] a brace - *[other] braces - } - .note = this message is not used as a format string, but will be in Rust 2021 - .suggestion = add a "{"{"}{"}"}" format string to use the message literally - -lint_non_fmt_panic_unused = - panic message contains {$count -> - [one] an unused - *[other] unused - } formatting {$count -> - [one] placeholder - *[other] placeholders - } - .note = this message is not used as a format string when given without arguments, but will be in Rust 2021 - .add_args_suggestion = add the missing {$count -> - [one] argument - *[other] arguments - } - .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally - -lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inherent` - .suggestion = try using a glob import instead - -lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` - -lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item - .non_local = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - .doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` - .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - .const_anon = use a const-anon item to suppress this lint - .macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed - -lint_non_local_definitions_impl_move_help = - move the `impl` block outside of this {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - } - -lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - .help = - remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - } - .help_doctest = - remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` - .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - -lint_non_snake_case = {$sort} `{$name}` should have a snake case name - .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier - .cannot_convert_note = `{$sc}` cannot be used as a raw identifier - .rename_suggestion = rename the identifier - .convert_suggestion = convert the identifier to snake case - .help = convert the identifier to snake case: `{$sc}` - .label = should have a snake_case name - -lint_non_upper_case_global = {$sort} `{$name}` should have an upper case name - .suggestion = convert the identifier to upper case - .label = should have an UPPER_CASE name - -lint_noop_method_call = call to `.{$method}()` on a reference in this situation does nothing - .suggestion = remove this redundant call - .note = the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed - .derive_suggestion = if you meant to clone `{$orig_ty}`, implement `Clone` for it - -lint_only_cast_u8_to_char = only `u8` can be cast into `char` - .suggestion = use a `char` literal instead - -lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds - .specifically = this associated type bound is unsatisfied for `{$proj_ty}` - -lint_opaque_hidden_inferred_bound_sugg = add this bound - -lint_overflowing_bin_hex = literal out of range for `{$ty}` - .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` - .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` - .positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}` - .suggestion = consider using the type `{$suggestion_ty}` instead - .sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}` - .help = consider using the type `{$suggestion_ty}` instead - -lint_overflowing_int = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - .help = consider using the type `{$suggestion_ty}` instead - -lint_overflowing_literal = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY` - -lint_overflowing_uint = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - -lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid - .label = overruled by previous forbid - -lint_pass_by_value = passing `{$ty}` by reference - .suggestion = try passing by value - -lint_path_statement_drop = path statement drops value - .suggestion = use `drop` to clarify the intent - -lint_path_statement_no_effect = path statement with no effect - -lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies - .label = pattern not allowed in function without body - -lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations - .label = pattern not allowed in foreign function - -lint_query_instability = using `{$query}` can result in unstable query results - .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale - -lint_query_untracked = `{$method}` accesses information that is not tracked by the query system - .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale - -lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` - -lint_range_use_inclusive_range = use an inclusive range instead - - -lint_raw_prefix = prefix `'r` is reserved - .label = reserved prefix - .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 - -lint_reason_must_be_string_literal = reason must be a string literal - -lint_reason_must_come_last = reason in lint attribute must come last - -lint_redundant_import = the item `{$ident}` is imported redundantly - .label_imported_here = the item `{$ident}` is already imported here - .label_defined_here = the item `{$ident}` is already defined here - .label_imported_prelude = the item `{$ident}` is already imported by the extern prelude - .label_defined_prelude = the item `{$ident}` is already defined by the extern prelude - -lint_redundant_semicolons = - unnecessary trailing {$multiple -> - [true] semicolons - *[false] semicolon - } - -lint_redundant_semicolons_suggestion = remove {$multiple_semicolons -> - [true] these semicolons - *[false] this semicolon - } - -lint_remove_mut_from_pattern = remove `mut` from the parameter - -lint_removed_lint = lint `{$name}` has been removed: {$reason} - -lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` - .suggestion = use the new name - .help = use the new name `{$replace}` - -lint_requested_level = requested on the command line with `{$level} {$lint_name}` - -lint_reserved_multihash = reserved token in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 - -lint_reserved_prefix = prefix `{$prefix}` is unknown - .label = unknown prefix - .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 - -lint_reserved_string = will be parsed as a guarded string in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 - -lint_shadowed_into_iter = - this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} - .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity - .remove_into_iter_suggestion = or remove `.into_iter()` to iterate by value - .use_explicit_into_iter_suggestion = - or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value - -lint_single_use_lifetime = lifetime parameter `{$ident}` only used once - .label_param = this lifetime... - .label_use = ...is used only here - .suggestion = elide the single-use lifetime - -lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` - -lint_static_mut_refs_lint = creating a {$shared_label}reference to mutable static - .label = {$shared_label}reference to mutable static - .suggestion = use `&raw const` instead to create a raw pointer - .suggestion_mut = use `&raw mut` instead to create a raw pointer - .shared_note = shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives - .mut_note = mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives - -lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion - .label = `{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}` - .label2 = target type is a supertrait of `{$self_ty}` - .help = consider removing this implementation or replacing it with a method instead - -lint_surrogate_char_cast = surrogate values are not valid for `char` - .note = `0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values - -lint_suspicious_double_ref_clone = - using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type - -lint_suspicious_double_ref_deref = - using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type - -lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal - .help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs` - -lint_too_large_char_cast = value exceeds maximum `char` value - .note = maximum valid `char` value is `0x10FFFF` - -lint_ty_qualified = usage of qualified `ty::{$ty}` - .suggestion = try importing it and using it unqualified - -lint_tykind = usage of `ty::TyKind` - .help = try using `Ty` instead - -lint_tykind_kind = usage of `ty::TyKind::` - .suggestion = try using `ty::` directly - -lint_type_ir_direct_use = do not use `rustc_type_ir` unless you are implementing type system internals - .note = use `rustc_middle::ty` instead - -lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler - -lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver - .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler - -lint_undefined_transmute = pointers cannot be transmuted to integers during const eval - .note = at compile-time, pointers do not have an integer value - .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior - .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html - -lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing - .label = argument has type `{$arg_ty}` - .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value - -lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs` -lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead -lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} -lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` -lint_unexpected_cfg_boolean = you may have meant to use `{$literal}` (notice the capitalization). Doing so makes this predicate evaluate to `{$literal}` unconditionally -lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` - -lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` -lint_unexpected_cfg_doc_cargo = see for more information about checking conditional configuration -lint_unexpected_cfg_doc_rustc = see for more information about checking conditional configuration - -lint_unexpected_cfg_from_external_macro_origin = using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate -lint_unexpected_cfg_from_external_macro_refer = try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg -lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` -lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> - [0] {""} - *[other] {" "}and {$and_more} more - } -lint_unexpected_cfg_name_expected_values = expected values for `{$best_match}` are: {$possibilities} -lint_unexpected_cfg_name_similar_name = there is a config with a similar name -lint_unexpected_cfg_name_similar_name_different_values = there is a config with a similar name and different values -lint_unexpected_cfg_name_similar_name_no_value = there is a config with a similar name and no value -lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value -lint_unexpected_cfg_name_version_syntax = there is a similar config predicate: `version("..")` -lint_unexpected_cfg_name_with_similar_value = found config with similar value - -lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value -> - [true] `{$value}` - *[false] (none) - } -lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml` -lint_unexpected_cfg_value_expected_values = expected values for `{$name}` are: {$have_none_possibility -> - [true] {"(none), "} - *[false] {""} - }{$possibilities}{$and_more -> - [0] {""} - *[other] {" "}and {$and_more} more - } -lint_unexpected_cfg_value_no_expected_value = no expected value for `{$name}` -lint_unexpected_cfg_value_no_expected_values = no expected values for `{$name}` -lint_unexpected_cfg_value_remove_condition = remove the condition -lint_unexpected_cfg_value_remove_value = remove the value -lint_unexpected_cfg_value_similar_name = there is a expected value with a similar name -lint_unexpected_cfg_value_specify_value = specify a config value - -lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op - .label = this function will not propagate the caller location - -lint_unicode_text_flow = unicode codepoint changing visible direction of text present in comment - .label = {$num_codepoints -> - [1] this comment contains an invisible unicode text flow control codepoint - *[other] this comment contains invisible unicode text flow control codepoints - } - .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen - .suggestion = if their presence wasn't intentional, you can remove them - .label_comment_char = {$c_debug} - - -lint_unit_bindings = binding has unit type `()` - .label = this pattern is inferred to be the unit type `()` - -lint_unknown_gated_lint = - unknown lint: `{$name}` - .note = the `{$name}` lint is unstable - -lint_unknown_lint = - unknown lint: `{$name}` - .suggestion = {$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints - *[false] did you mean - } - .help = {$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints: `{$replace}` - *[false] did you mean: `{$replace}` - } - -lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}` - .help = add `#![register_tool({$tool_name})]` to the crate root - -lint_unnecessary_qualification = unnecessary qualification - .suggestion = remove the unnecessary path segments - -lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - .note_duplicated_fn = the address of the same function can vary between different codegen units - .note_deduplicated_fn = furthermore, different functions could have the same address after being merged together - .note_visit_fn_addr_eq = for more information visit - .fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint - -lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` - -lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ - -lint_unused_allocation = unnecessary allocation, use `&` instead -lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead - -lint_unused_closure = - unused {$pre}{$count -> - [one] closure - *[other] closures - }{$post} that must be used - .note = closures are lazy and do nothing unless called - -lint_unused_comparisons = comparison is useless due to type limits - -lint_unused_coroutine = - unused {$pre}{$count -> - [one] coroutine - *[other] coroutine - }{$post} that must be used - .note = coroutines are lazy and do nothing unless resumed - -lint_unused_crate_dependency = extern crate `{$extern_crate}` is unused in crate `{$local_crate}` - .help = remove the dependency or add `use {$extern_crate} as _;` to the crate root - -lint_unused_def = unused {$pre}`{$def}`{$post} that must be used - .suggestion = use `let _ = ...` to ignore the resulting value - -lint_unused_delim = unnecessary {$delim} around {$item} - .suggestion = remove these {$delim} - -lint_unused_duplicate = - unused attribute - .suggestion = remove this attribute - .note = attribute also specified here - .warn = {-lint_previously_accepted} - -lint_unused_import_braces = braces around {$node} is unnecessary - -lint_unused_imports = {$num_snippets -> - [one] unused import: {$span_snippets} - *[other] unused imports: {$span_snippets} - } - .suggestion_remove_whole_use = remove the whole `use` item - .suggestion_remove_imports = {$num_to_remove -> - [one] remove the unused import - *[other] remove the unused imports - } - .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module - -lint_unused_lifetime = lifetime parameter `{$ident}` never used - .suggestion = elide the unused lifetime - -lint_unused_op = unused {$op} that must be used - .label = the {$op} produces a value - .suggestion = use `let _ = ...` to ignore the resulting value - -lint_unused_result = unused result of type `{$ty}` - -lint_unused_visibilities = visibility qualifiers have no effect on `const _` declarations - .note = `const _` does not declare a name, so there is nothing for the qualifier to apply to - .suggestion = remove the qualifier - -lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result - -lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false - .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value - .label = expression has type `{$orig_ty}` - -lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false - -lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false - .label = expression has type `{$orig_ty}` - -lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type - -lint_variant_size_differences = - enum variant is more than three times larger ({$largest} bytes) than the next largest diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs index 02fb22bf782e..0d3a954667f7 100644 --- a/compiler/rustc_lint/src/async_closures.rs +++ b/compiler/rustc_lint/src/async_closures.rs @@ -108,16 +108,18 @@ impl<'tcx> LateLintPass<'tcx> for AsyncClosureUsage { } #[derive(LintDiagnostic)] -#[diag(lint_closure_returning_async_block)] +#[diag("closure returning async block can be made into an async closure")] struct ClosureReturningAsyncBlock { - #[label] + #[label( + "this async block can be removed, and the closure can be turned into an async closure" + )] async_decl_span: Span, #[subdiagnostic] sugg: AsyncClosureSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion("turn this into an async closure", applicability = "maybe-incorrect")] struct AsyncClosureSugg { #[suggestion_part(code = "")] deletion_span: Span, diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index ed7ac0e33244..5bb7df80ffb3 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -1,7 +1,9 @@ use rustc_ast::{BorrowKind, UnOp}; use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, Mutability, find_attr}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref}; +use rustc_middle::ty::adjustment::{ + Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref, +}; use rustc_session::{declare_lint, declare_lint_pass}; use crate::lints::{ @@ -165,12 +167,14 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen /// an implicit borrow (or has an implicit borrow via an overloaded deref). fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> { match kind { - &Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)), + &Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { mutbl, .. })) => { + Some((mutbl, true)) + } &Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)), Adjust::NeverToAny | Adjust::Pointer(..) | Adjust::ReborrowPin(..) - | Adjust::Deref(None) + | Adjust::Deref(DerefAdjustKind::Builtin) | Adjust::Borrow(AutoBorrow::RawPtr(..)) => None, } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e2a061cab680..42e714230010 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -22,7 +22,7 @@ use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_parsing::AttributeParser; -use rustc_errors::{Applicability, LintDiagnostic}; +use rustc_errors::{Applicability, LintDiagnostic, msg}; use rustc_feature::GateIssue; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, DocAttribute}; @@ -61,10 +61,7 @@ use crate::lints::{ BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, }; -use crate::{ - EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, - fluent_generated as fluent, -}; +use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; declare_lint! { /// The `while_true` lint detects `while true { }`. /// @@ -2655,8 +2652,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { let conjured_ty = cx.typeck_results().expr_ty(expr); if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { let msg = match init { - InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed, - InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit, + InitKind::Zeroed => { + msg!("the type `{$ty}` does not permit zero-initialization") + } + InitKind::Uninit => { + msg!("the type `{$ty}` does not permit being left uninitialized") + } }; let sub = BuiltinUnpermittedTypeInitSub { err }; cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 19f3a9b4c062..561bdd1a2db6 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -154,6 +154,11 @@ impl LintStore { }) } + /// Returns all lint group names, including deprecated/aliased groups + pub fn get_all_group_names(&self) -> impl Iterator { + self.lint_groups.keys().copied() + } + pub fn register_early_pass( &mut self, pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync, diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index af4457f4314b..71ea801a408e 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -268,7 +268,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { && let ty = cx.typeck_results().expr_ty(receiver) && owns_allocation(cx.tcx, ty) && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::AsPtr(_)) + && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::RustcAsPtr(_)) { // FIXME: use `emit_node_lint` when `#[primary_span]` is added. cx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 377b3c439453..3da2b1bf4069 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -293,6 +293,14 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } + BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { + Some(wildcard_span) => { + lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span } + .decorate_lint(diag) + } + None => lints::UnreachableCfgSelectPredicate { span }.decorate_lint(diag), + }, + BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } @@ -375,6 +383,10 @@ pub fn decorate_attribute_lint( lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag) } + &AttributeLintKind::AmbiguousDeriveHelpers => { + lints::AmbiguousDeriveHelpers.decorate_lint(diag) + } + &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag) } @@ -428,5 +440,11 @@ pub fn decorate_attribute_lint( sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), } .decorate_lint(diag), + + &AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag), + + &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag), + + &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 8f2f3594161a..8fec30816bd1 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,17 +1,15 @@ use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(lint_overruled_attribute, code = E0453)] +#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid", code = E0453)] pub(crate) struct OverruledAttribute<'a> { #[primary_span] pub span: Span, - #[label] + #[label("overruled by previous forbid")] pub overruled: Span, pub lint_level: &'a str, pub lint_source: Symbol, @@ -22,31 +20,32 @@ pub(crate) struct OverruledAttribute<'a> { pub(crate) enum OverruledAttributeSub { DefaultSource { id: String }, NodeSource { span: Span, reason: Option }, - CommandLineSource, + CommandLineSource { id: Symbol }, } impl Subdiagnostic for OverruledAttributeSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverruledAttributeSub::DefaultSource { id } => { - diag.note(fluent::lint_default_source); + diag.note(msg!("`forbid` lint level is the default for {$id}")); diag.arg("id", id); } OverruledAttributeSub::NodeSource { span, reason } => { - diag.span_label(span, fluent::lint_node_source); + diag.span_label(span, msg!("`forbid` level set here")); if let Some(rationale) = reason { diag.note(rationale.to_string()); } } - OverruledAttributeSub::CommandLineSource => { - diag.note(fluent::lint_command_line_source); + OverruledAttributeSub::CommandLineSource { id } => { + diag.note(msg!("`forbid` lint level was set on command line (`-F {$id}`)")); + diag.arg("id", id); } } } } #[derive(Diagnostic)] -#[diag(lint_malformed_attribute, code = E0452)] +#[diag("malformed lint attribute input", code = E0452)] pub(crate) struct MalformedAttribute { #[primary_span] pub span: Span, @@ -56,50 +55,55 @@ pub(crate) struct MalformedAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedAttributeSub { - #[label(lint_bad_attribute_argument)] + #[label("bad attribute argument")] BadAttributeArgument(#[primary_span] Span), - #[label(lint_reason_must_be_string_literal)] + #[label("reason must be a string literal")] ReasonMustBeStringLiteral(#[primary_span] Span), - #[label(lint_reason_must_come_last)] + #[label("reason in lint attribute must come last")] ReasonMustComeLast(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(lint_unknown_tool_in_scoped_lint, code = E0710)] +#[diag("unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`", code = E0710)] pub(crate) struct UnknownToolInScopedLint { #[primary_span] pub span: Option, pub tool_name: Symbol, pub lint_name: String, - #[help] + #[help("add `#![register_tool({$tool_name})]` to the crate root")] pub is_nightly_build: bool, } #[derive(Diagnostic)] -#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)] +#[diag("`...` range patterns are deprecated", code = E0783)] pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { #[primary_span] pub span: Span, - #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + style = "short", + code = "{replace}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub replace: String, } #[derive(Subdiagnostic)] -#[note(lint_requested_level)] +#[note("requested on the command line with `{$level} {$lint_name}`")] pub(crate) struct RequestedLevel<'a> { pub level: Level, pub lint_name: &'a str, } #[derive(Diagnostic)] -#[diag(lint_unsupported_group, code = E0602)] +#[diag("`{$lint_group}` lint group is not supported with ´--force-warn´", code = E0602)] pub(crate) struct UnsupportedGroup { pub lint_group: String, } #[derive(Diagnostic)] -#[diag(lint_check_name_unknown_tool, code = E0602)] +#[diag("unknown lint tool: `{$tool_name}`", code = E0602)] pub(crate) struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 612d542a27de..7899d4690ea5 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use rustc_ast::Recovered; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle, msg}; use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::adjustment::Adjust; @@ -303,13 +303,15 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope { } #[derive(LintDiagnostic)] -#[diag(lint_if_let_rescope)] +#[diag("`if let` assigns a shorter lifetime since Edition 2024")] struct IfLetRescopeLint { #[subdiagnostic] destructors: Vec, - #[label] + #[label( + "this value has a significant drop implementation which may observe a major change in drop order and requires your discretion" + )] significant_droppers: Vec, - #[help] + #[help("the value is now dropped here in Edition 2024")] lifetime_ends: Vec, #[subdiagnostic] rewrite: Option, @@ -352,7 +354,9 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat_n('}', closing_brackets.count)) .collect(), )); - let msg = diag.eagerly_translate(crate::fluent_generated::lint_suggestion); + let msg = diag.eagerly_translate(msg!( + "a `match` with a single arm can preserve the drop order up to Edition 2021" + )); diag.multipart_suggestion_with_style( msg, suggestions, @@ -363,7 +367,12 @@ impl Subdiagnostic for IfLetRescopeRewrite { } #[derive(Subdiagnostic)] -#[note(lint_if_let_dtor)] +#[note( + "{$dtor_kind -> + [dyn] value may invoke a custom destructor because it contains a trait object + *[concrete] value invokes this custom destructor + }" +)] struct DestructorLabel { #[primary_span] span: Span, diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index f6c2e5946079..5e5f9b6f097f 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -3,7 +3,7 @@ use std::cell::LazyCell; use rustc_data_structures::debug_assert_matches; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{LintDiagnostic, Subdiagnostic}; +use rustc_errors::{LintDiagnostic, Subdiagnostic, msg}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -28,7 +28,7 @@ use rustc_trait_selection::errors::{ use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; use rustc_trait_selection::traits::ObligationCtxt; -use crate::{LateContext, LateLintPass, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass}; declare_lint! { /// The `impl_trait_overcaptures` lint warns against cases where lifetime @@ -211,7 +211,7 @@ where // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { - let arg: ty::BoundVariableKind = arg; + let arg: ty::BoundVariableKind<'tcx> = arg; match arg { ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => { @@ -435,11 +435,21 @@ struct ImplTraitOvercapturesLint<'tcx> { impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::lint_impl_trait_overcaptures); + diag.primary_message(msg!( + "`{$self_ty}` will capture more lifetimes than possibly intended in edition 2024" + )); diag.arg("self_ty", self.self_ty.to_string()) .arg("num_captured", self.num_captured) - .span_note(self.uncaptured_spans, fluent::lint_note) - .note(fluent::lint_note2); + .span_note( + self.uncaptured_spans, + msg!( + "specifically, {$num_captured -> + [one] this lifetime is + *[other] these lifetimes are + } in scope but not mentioned in the type's bounds" + ), + ) + .note(msg!("all lifetimes in scope will be captured by `impl Trait`s in edition 2024")); if let Some(suggestion) = self.suggestion { suggestion.add_to_diag(diag); } @@ -447,9 +457,9 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_impl_trait_redundant_captures)] +#[diag("all possible in-scope parameters are already captured, so `use<...>` syntax is redundant")] struct ImplTraitRedundantCapturesLint { - #[suggestion(lint_suggestion, code = "", applicability = "machine-applicable")] + #[suggestion("remove the `use<...>` syntax", code = "", applicability = "machine-applicable")] capturing_span: Span, } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index ccfba715a1be..3cc0d46d8541 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -7,7 +7,7 @@ use std::any::Any; use std::cell::Cell; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::join; +use rustc_data_structures::sync::par_join; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_middle::hir::nested_filter; @@ -461,7 +461,7 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>( /// Performs lint checking on a crate. pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) { - join( + par_join( || { tcx.sess.time("crate_lints", || { // Run whole crate non-incremental lints diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 57dacbc11e05..a3376ad967e0 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -2,7 +2,7 @@ use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{Diag, LintDiagnostic, MultiSpan}; +use rustc_errors::{Diag, LintDiagnostic, MultiSpan, msg}; use rustc_feature::{Features, GateIssue}; use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; @@ -31,7 +31,6 @@ use crate::errors::{ CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup, }; -use crate::fluent_generated as fluent; use crate::late::unerased_lint_store; use crate::lints::{ DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified, @@ -581,7 +580,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { LintLevelSource::Node { span, reason, .. } => { OverruledAttributeSub::NodeSource { span, reason } } - LintLevelSource::CommandLine(_, _) => OverruledAttributeSub::CommandLineSource, + LintLevelSource::CommandLine(name, _) => { + OverruledAttributeSub::CommandLineSource { id: name } + } }; if !fcw_warning { self.sess.dcx().emit_err(OverruledAttribute { @@ -942,9 +943,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let lint = builtin::UNKNOWN_LINTS; let level = self.lint_level(builtin::UNKNOWN_LINTS); lint_level(self.sess, lint, level, Some(span.into()), |lint| { - lint.primary_message(fluent::lint_unknown_gated_lint); + lint.primary_message(msg!("unknown lint: `{$name}`")); lint.arg("name", lint_id.lint.name_lower()); - lint.note(fluent::lint_note); + lint.note(msg!("the `{$name}` lint is unstable")); rustc_session::parse::add_feature_diagnostics_for_issue( lint, &self.sess, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 80b32645a895..94dc566d75f1 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -21,7 +21,7 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_order_by)] @@ -139,8 +139,6 @@ pub use rustc_errors::BufferedEarlyLint; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { levels::provide(providers); expect::provide(providers); @@ -297,6 +295,9 @@ fn register_builtins(store: &mut LintStore) { UNUSED_ASSIGNMENTS, DEAD_CODE, UNUSED_MUT, + // FIXME: add this lint when it becomes stable, + // see https://github.com/rust-lang/rust/issues/115585. + // UNREACHABLE_CFG_SELECT_PREDICATES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, UNUSED_MUST_USE, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a20d90e1227e..3b34a217edfd 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,7 +5,7 @@ use std::num::NonZero; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, + EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, msg, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -17,18 +17,24 @@ use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, Symbol, sym}; +use crate::LateContext; use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; use crate::errors::{OverruledAttributeSub, RequestedLevel}; use crate::lifetime_syntax::LifetimeSyntaxCategories; -use crate::{LateContext, fluent_generated as fluent}; // array_into_iter.rs #[derive(LintDiagnostic)] -#[diag(lint_shadowed_into_iter)] +#[diag( + "this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}" +)] pub(crate) struct ShadowedIntoIterDiag { pub target: &'static str, pub edition: &'static str, - #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")] + #[suggestion( + "use `.iter()` instead of `.into_iter()` to avoid ambiguity", + code = "iter", + applicability = "machine-applicable" + )] pub suggestion: Span, #[subdiagnostic] pub sub: Option, @@ -36,13 +42,17 @@ pub(crate) struct ShadowedIntoIterDiag { #[derive(Subdiagnostic)] pub(crate) enum ShadowedIntoIterDiagSub { - #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] + #[suggestion( + "or remove `.into_iter()` to iterate by value", + code = "", + applicability = "maybe-incorrect" + )] RemoveIntoIter { #[primary_span] span: Span, }, #[multipart_suggestion( - lint_use_explicit_into_iter_suggestion, + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", applicability = "maybe-incorrect" )] UseExplicitIntoIter { @@ -55,10 +65,12 @@ pub(crate) enum ShadowedIntoIterDiagSub { // autorefs.rs #[derive(LintDiagnostic)] -#[diag(lint_implicit_unsafe_autorefs)] -#[note] +#[diag("implicit autoref creates a reference to the dereference of a raw pointer")] +#[note( + "creating a reference requires the pointer target to be valid and imposes aliasing requirements" +)] pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { - #[label(lint_raw_ptr)] + #[label("this raw pointer has type `{$raw_ptr_ty}`")] pub raw_ptr_span: Span, pub raw_ptr_ty: Ty<'a>, #[subdiagnostic] @@ -71,18 +83,20 @@ pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { #[derive(Subdiagnostic)] pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> { - #[note(lint_autoref)] + #[note("autoref is being applied to this expression, resulting in: `{$autoref_ty}`")] Autoref { #[primary_span] autoref_span: Span, autoref_ty: Ty<'a>, }, - #[note(lint_overloaded_deref)] + #[note( + "references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations" + )] OverloadedDeref, } #[derive(Subdiagnostic)] -#[note(lint_method_def)] +#[note("method calls to `{$method_name}` require a reference")] pub(crate) struct ImplicitUnsafeAutorefsMethodNote { #[primary_span] pub def_span: Span, @@ -90,7 +104,10 @@ pub(crate) struct ImplicitUnsafeAutorefsMethodNote { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try using a raw pointer method instead; or if this reference is intentional, make it explicit", + applicability = "maybe-incorrect" +)] pub(crate) struct ImplicitUnsafeAutorefsSuggestion { pub mutbl: &'static str, pub deref: &'static str, @@ -102,78 +119,105 @@ pub(crate) struct ImplicitUnsafeAutorefsSuggestion { // builtin.rs #[derive(LintDiagnostic)] -#[diag(lint_builtin_while_true)] +#[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")] pub(crate) struct BuiltinWhileTrue { - #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `loop`", + style = "short", + code = "{replace}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub replace: String, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_non_shorthand_field_patterns)] +#[diag("the `{$ident}:` in this pattern is redundant")] pub(crate) struct BuiltinNonShorthandFieldPatterns { pub ident: Ident, - #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] + #[suggestion( + "use shorthand field pattern", + code = "{prefix}{ident}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: &'static str, } #[derive(LintDiagnostic)] pub(crate) enum BuiltinUnsafe { - #[diag(lint_builtin_allow_internal_unsafe)] + #[diag( + "`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site" + )] AllowInternalUnsafe, - #[diag(lint_builtin_unsafe_block)] + #[diag("usage of an `unsafe` block")] UnsafeBlock, - #[diag(lint_builtin_unsafe_extern_block)] + #[diag("usage of an `unsafe extern` block")] UnsafeExternBlock, - #[diag(lint_builtin_unsafe_trait)] + #[diag("declaration of an `unsafe` trait")] UnsafeTrait, - #[diag(lint_builtin_unsafe_impl)] + #[diag("implementation of an `unsafe` trait")] UnsafeImpl, - #[diag(lint_builtin_no_mangle_fn)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` function")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleFn, - #[diag(lint_builtin_export_name_fn)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a function with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameFn, - #[diag(lint_builtin_link_section_fn)] - #[note(lint_builtin_overridden_symbol_section)] + #[diag("declaration of a function with `link_section`")] + #[note( + "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" + )] LinkSectionFn, - #[diag(lint_builtin_no_mangle_static)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` static")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleStatic, - #[diag(lint_builtin_export_name_static)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a static with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameStatic, - #[diag(lint_builtin_link_section_static)] - #[note(lint_builtin_overridden_symbol_section)] + #[diag("declaration of a static with `link_section`")] + #[note( + "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" + )] LinkSectionStatic, - #[diag(lint_builtin_no_mangle_method)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` method")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleMethod, - #[diag(lint_builtin_export_name_method)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a method with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameMethod, - #[diag(lint_builtin_decl_unsafe_fn)] + #[diag("declaration of an `unsafe` function")] DeclUnsafeFn, - #[diag(lint_builtin_decl_unsafe_method)] + #[diag("declaration of an `unsafe` method")] DeclUnsafeMethod, - #[diag(lint_builtin_impl_unsafe_method)] + #[diag("implementation of an `unsafe` method")] ImplUnsafeMethod, - #[diag(lint_builtin_global_asm)] - #[note(lint_builtin_global_macro_unsafety)] + #[diag("usage of `core::arch::global_asm`")] + #[note("using this macro is unsafe even though it does not need an `unsafe` block")] GlobalAsm, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_missing_doc)] +#[diag("missing documentation for {$article} {$desc}")] pub(crate) struct BuiltinMissingDoc<'a> { pub article: &'a str, pub desc: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_missing_copy_impl)] +#[diag("type could implement `Copy`; consider adding `impl Copy`")] pub(crate) struct BuiltinMissingCopyImpl; pub(crate) struct BuiltinMissingDebugImpl<'a> { @@ -184,24 +228,24 @@ pub(crate) struct BuiltinMissingDebugImpl<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::lint_builtin_missing_debug_impl); + diag.primary_message(msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation")); diag.arg("debug", self.tcx.def_path_str(self.def_id)); } } #[derive(LintDiagnostic)] -#[diag(lint_builtin_anonymous_params)] +#[diag("anonymous parameters are deprecated and will be removed in the next edition")] pub(crate) struct BuiltinAnonymousParams<'a> { - #[suggestion(code = "_: {ty_snip}")] + #[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")] pub suggestion: (Span, Applicability), pub ty_snip: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_unused_doc_comment)] +#[diag("unused doc comment")] pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, - #[label] + #[label("rustdoc does not generate documentation for {$kind}")] pub label: Span, #[subdiagnostic] pub sub: BuiltinUnusedDocCommentSub, @@ -209,34 +253,41 @@ pub(crate) struct BuiltinUnusedDocComment<'a> { #[derive(Subdiagnostic)] pub(crate) enum BuiltinUnusedDocCommentSub { - #[help(lint_plain_help)] + #[help("use `//` for a plain comment")] PlainHelp, - #[help(lint_block_help)] + #[help("use `/* */` for a plain comment")] BlockHelp, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_no_mangle_generic)] +#[diag("functions generic over types or consts must be mangled")] pub(crate) struct BuiltinNoMangleGeneric { // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand - #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "remove this attribute", + style = "short", + code = "", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_const_no_mangle)] +#[diag("const items should never be `#[no_mangle]`")] pub(crate) struct BuiltinConstNoMangle { - #[suggestion(code = "pub static ", applicability = "machine-applicable")] + #[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")] pub suggestion: Option, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_mutable_transmutes)] +#[diag( + "transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell" +)] pub(crate) struct BuiltinMutablesTransmutes; #[derive(LintDiagnostic)] -#[diag(lint_builtin_unstable_features)] +#[diag("use of an unstable feature")] pub(crate) struct BuiltinUnstableFeatures; // lint_ungated_async_fn_track_caller @@ -247,8 +298,8 @@ pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_ungated_async_fn_track_caller); - diag.span_label(self.label, fluent::lint_label); + diag.primary_message(msg!("`#[track_caller]` on async functions is a no-op")); + diag.span_label(self.label, msg!("this function will not propagate the caller location")); rustc_session::parse::add_feature_diagnostics( diag, self.session, @@ -258,20 +309,24 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_unreachable_pub)] +#[diag("unreachable `pub` {$what}")] pub(crate) struct BuiltinUnreachablePub<'a> { pub what: &'a str, pub new_vis: &'a str, - #[suggestion(code = "{new_vis}")] + #[suggestion("consider restricting its visibility", code = "{new_vis}")] pub suggestion: (Span, Applicability), - #[help] + #[help("or consider exporting it for use by other crates")] pub help: bool, } #[derive(LintDiagnostic)] -#[diag(lint_macro_expr_fragment_specifier_2024_migration)] +#[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")] pub(crate) struct MacroExprFragment2024 { - #[suggestion(code = "expr_2021", applicability = "machine-applicable")] + #[suggestion( + "to keep the existing behavior, use the `expr_2021` fragment specifier", + code = "expr_2021", + applicability = "machine-applicable" + )] pub suggestion: Span, } @@ -287,14 +342,17 @@ pub(crate) struct BuiltinTypeAliasBounds<'hir> { impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(if self.in_where_clause { - fluent::lint_builtin_type_alias_bounds_where_clause + msg!("where clauses on type aliases are not enforced") } else { - fluent::lint_builtin_type_alias_bounds_param_bounds + msg!("bounds on generic parameters in type aliases are not enforced") }); - diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label); - diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note); + diag.span_label(self.label, msg!("will not be checked at usage sites of the type alias")); + diag.note(msg!( + "this is a known limitation of the type checker that may be lifted in a future edition. + see issue #112792 for more information" + )); if self.enable_feat_help { - diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help); + diag.help(msg!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); } // We perform the walk in here instead of in `` to @@ -319,7 +377,20 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { }; diag.arg("count", self.suggestions.len()); - diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability); + diag.multipart_suggestion( + if self.in_where_clause { + msg!("remove this where clause") + } else { + msg!( + "remove {$count -> + [one] this bound + *[other] these bounds + }" + ) + }, + self.suggestions, + applicability, + ); // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via // `::Assoc` to remove their reliance on any type param bounds. @@ -333,7 +404,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { // (We could employ some simple heuristics but that's likely not worth it). for qself in collector.qselves { diag.multipart_suggestion( - fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg, + msg!("fully qualify this associated type"), vec![ (qself.shrink_to_lo(), "<".into()), (qself.shrink_to_hi(), " as /* Trait */>".into()), @@ -345,23 +416,27 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_trivial_bounds)] +#[diag( + "{$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters" +)] pub(crate) struct BuiltinTrivialBounds<'a> { pub predicate_kind_name: &'a str, pub predicate: Clause<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_double_negations)] -#[note(lint_note)] -#[note(lint_note_decrement)] +#[diag("use of a double negation")] +#[note( + "the prefix `--` could be misinterpreted as a decrement operator which exists in other languages" +)] +#[note("use `-= 1` if you meant to decrement the value")] pub(crate) struct BuiltinDoubleNegations { #[subdiagnostic] pub add_parens: BuiltinDoubleNegationsAddParens, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion("add parentheses for clarity", applicability = "maybe-incorrect")] pub(crate) struct BuiltinDoubleNegationsAddParens { #[suggestion_part(code = "(")] pub start_span: Span, @@ -371,31 +446,44 @@ pub(crate) struct BuiltinDoubleNegationsAddParens { #[derive(LintDiagnostic)] pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { - #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + #[diag("`...` range patterns are deprecated")] Parenthesise { - #[suggestion(code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + code = "{replace}", + applicability = "machine-applicable" + )] suggestion: Span, replace: String, }, - #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + #[diag("`...` range patterns are deprecated")] NonParenthesise { - #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + style = "short", + code = "..=", + applicability = "machine-applicable" + )] suggestion: Span, }, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_keyword_idents)] +#[diag("`{$kw}` is a keyword in the {$next} edition")] pub(crate) struct BuiltinKeywordIdents { pub kw: Ident, pub next: Edition, - #[suggestion(code = "{prefix}r#{kw}", applicability = "machine-applicable")] + #[suggestion( + "you can use a raw identifier to stay compatible", + code = "{prefix}r#{kw}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_explicit_outlives)] +#[diag("outlives requirements can be inferred")] pub(crate) struct BuiltinExplicitOutlives { pub count: usize, #[subdiagnostic] @@ -403,7 +491,12 @@ pub(crate) struct BuiltinExplicitOutlives { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion)] +#[multipart_suggestion( + "remove {$count -> + [one] this bound + *[other] these bounds + }" +)] pub(crate) struct BuiltinExplicitOutlivesSuggestion { #[suggestion_part(code = "")] pub spans: Vec, @@ -412,7 +505,9 @@ pub(crate) struct BuiltinExplicitOutlivesSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_incomplete_features)] +#[diag( + "the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes" +)] pub(crate) struct BuiltinIncompleteFeatures { pub name: Symbol, #[subdiagnostic] @@ -422,18 +517,18 @@ pub(crate) struct BuiltinIncompleteFeatures { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_internal_features)] -#[note] +#[diag("the feature `{$name}` is internal to the compiler or standard library")] +#[note("using it is strongly discouraged")] pub(crate) struct BuiltinInternalFeatures { pub name: Symbol, } #[derive(Subdiagnostic)] -#[help(lint_help)] +#[help("consider using `min_{$name}` instead, which is more stable and complete")] pub(crate) struct BuiltinIncompleteFeaturesHelp; #[derive(Subdiagnostic)] -#[note(lint_note)] +#[note("see issue #{$n} for more information")] pub(crate) struct BuiltinFeatureIssueNote { pub n: NonZero, } @@ -450,12 +545,12 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(self.msg); diag.arg("ty", self.ty); - diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); + diag.span_label(self.label, msg!("this code causes undefined behavior when executed")); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. diag.span_label( self.label, - fluent::lint_builtin_unpermitted_type_init_label_suggestion, + msg!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), ); } self.sub.add_to_diag(diag); @@ -487,24 +582,24 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { #[derive(LintDiagnostic)] pub(crate) enum BuiltinClashingExtern<'a> { - #[diag(lint_builtin_clashing_extern_same_name)] + #[diag("`{$this}` redeclared with a different signature")] SameName { this: Symbol, orig: Symbol, - #[label(lint_previous_decl_label)] + #[label("`{$orig}` previously declared here")] previous_decl_label: Span, - #[label(lint_mismatch_label)] + #[label("this signature doesn't match the previous declaration")] mismatch_label: Span, #[subdiagnostic] sub: BuiltinClashingExternSub<'a>, }, - #[diag(lint_builtin_clashing_extern_diff_name)] + #[diag("`{$this}` redeclares `{$orig}` with a different signature")] DiffName { this: Symbol, orig: Symbol, - #[label(lint_previous_decl_label)] + #[label("`{$orig}` previously declared here")] previous_decl_label: Span, - #[label(lint_mismatch_label)] + #[label("this signature doesn't match the previous declaration")] mismatch_label: Span, #[subdiagnostic] sub: BuiltinClashingExternSub<'a>, @@ -529,9 +624,9 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_deref_nullptr)] +#[diag("dereferencing a null pointer")] pub(crate) struct BuiltinDerefNullptr { - #[label] + #[label("this code causes undefined behavior when executed")] pub label: Span, } @@ -539,30 +634,32 @@ pub(crate) struct BuiltinDerefNullptr { #[derive(LintDiagnostic)] pub(crate) enum BuiltinSpecialModuleNameUsed { - #[diag(lint_builtin_special_module_name_used_lib)] - #[note] - #[help] + #[diag("found module declaration for lib.rs")] + #[note("lib.rs is the root of this crate's library target")] + #[help("to refer to it from other targets, use the library's name as the path")] Lib, - #[diag(lint_builtin_special_module_name_used_main)] - #[note] + #[diag("found module declaration for main.rs")] + #[note("a binary crate cannot be used as library")] Main, } // deref_into_dyn_supertrait.rs #[derive(LintDiagnostic)] -#[diag(lint_supertrait_as_deref_target)] +#[diag("this `Deref` implementation is covered by an implicit supertrait coercion")] pub(crate) struct SupertraitAsDerefTarget<'a> { pub self_ty: Ty<'a>, pub supertrait_principal: PolyExistentialTraitRef<'a>, pub target_principal: PolyExistentialTraitRef<'a>, - #[label] + #[label( + "`{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}`" + )] pub label: Span, #[subdiagnostic] pub label2: Option, } #[derive(Subdiagnostic)] -#[label(lint_label2)] +#[label("target type is a supertrait of `{$self_ty}`")] pub(crate) struct SupertraitAsDerefTargetLabel { #[primary_span] pub label: Span, @@ -570,32 +667,38 @@ pub(crate) struct SupertraitAsDerefTargetLabel { // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] -#[diag(lint_enum_intrinsics_mem_discriminant)] +#[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")] pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub ty_param: Ty<'a>, - #[note] + #[note( + "the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum" + )] pub note: Span, } #[derive(LintDiagnostic)] -#[diag(lint_enum_intrinsics_mem_variant)] -#[note] +#[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")] +#[note( + "the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum" +)] pub(crate) struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } // expect.rs #[derive(LintDiagnostic)] -#[diag(lint_expectation)] +#[diag("this lint expectation is unfulfilled")] pub(crate) struct Expectation { #[subdiagnostic] pub rationale: Option, - #[note] + #[note( + "the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message" + )] pub note: bool, } #[derive(Subdiagnostic)] -#[note(lint_rationale)] +#[note("{$rationale}")] pub(crate) struct ExpectationNote { pub rationale: Symbol, } @@ -603,42 +706,58 @@ pub(crate) struct ExpectationNote { // ptr_nulls.rs #[derive(LintDiagnostic)] pub(crate) enum UselessPtrNullChecksDiag<'a> { - #[diag(lint_useless_ptr_null_checks_fn_ptr)] - #[help] + #[diag( + "function pointers are not nullable, so checking them for null will always return false" + )] + #[help( + "wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value" + )] FnPtr { orig_ty: Ty<'a>, - #[label] + #[label("expression has type `{$orig_ty}`")] label: Span, }, - #[diag(lint_useless_ptr_null_checks_ref)] + #[diag("references are not nullable, so checking them for null will always return false")] Ref { orig_ty: Ty<'a>, - #[label] + #[label("expression has type `{$orig_ty}`")] label: Span, }, - #[diag(lint_useless_ptr_null_checks_fn_ret)] + #[diag( + "returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false" + )] FnRet { fn_name: Ident }, } #[derive(LintDiagnostic)] pub(crate) enum InvalidNullArgumentsDiag { - #[diag(lint_invalid_null_arguments)] - #[help(lint_doc)] + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] NullPtrInline { - #[label(lint_origin)] + #[label("null pointer originates from here")] null_span: Span, }, - #[diag(lint_invalid_null_arguments)] - #[help(lint_doc)] + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] NullPtrThroughBinding { - #[note(lint_origin)] + #[note("null pointer originates from here")] null_span: Span, }, } // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] -#[diag(lint_for_loops_over_fallibles)] +#[diag( + "for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement" +)] pub(crate) struct ForLoopsOverFalliblesDiag<'a> { pub article: &'static str, pub ref_prefix: &'static str, @@ -653,13 +772,20 @@ pub(crate) struct ForLoopsOverFalliblesDiag<'a> { #[derive(Subdiagnostic)] pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { - #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] + #[suggestion( + "to iterate over `{$recv_snip}` remove the call to `next`", + code = ".by_ref()", + applicability = "maybe-incorrect" + )] RemoveNext { #[primary_span] suggestion: Span, recv_snip: String, }, - #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "to check pattern in a loop use `while let`", + applicability = "maybe-incorrect" + )] UseWhileLet { #[suggestion_part(code = "while let {var}(")] start_span: Span, @@ -670,14 +796,21 @@ pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { } #[derive(Subdiagnostic)] -#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")] +#[suggestion( + "consider unwrapping the `Result` with `?` to iterate over its contents", + code = "?", + applicability = "maybe-incorrect" +)] pub(crate) struct ForLoopsOverFalliblesQuestionMark { #[primary_span] pub suggestion: Span, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider using `if let` to clear intent", + applicability = "maybe-incorrect" +)] pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { pub var: &'a str, #[suggestion_part(code = "if let {var}(")] @@ -688,10 +821,10 @@ pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { #[derive(Subdiagnostic)] pub(crate) enum UseLetUnderscoreIgnoreSuggestion { - #[note(lint_use_let_underscore_ignore_suggestion)] + #[note("use `let _ = ...` to ignore the expression or result")] Note, #[multipart_suggestion( - lint_use_let_underscore_ignore_suggestion, + "use `let _ = ...` to ignore the expression or result", style = "verbose", applicability = "maybe-incorrect" )] @@ -705,57 +838,62 @@ pub(crate) enum UseLetUnderscoreIgnoreSuggestion { // drop_forget_useless.rs #[derive(LintDiagnostic)] -#[diag(lint_dropping_references)] +#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")] pub(crate) struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_dropping_copy_types)] +#[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")] pub(crate) struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_forgetting_references)] +#[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")] pub(crate) struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_forgetting_copy_types)] +#[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")] pub(crate) struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_undropped_manually_drops)] +#[diag( + "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" +)] pub(crate) struct UndroppedManuallyDropsDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub suggestion: UndroppedManuallyDropsSuggestion, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "use `std::mem::ManuallyDrop::into_inner` to get the inner value", + applicability = "machine-applicable" +)] pub(crate) struct UndroppedManuallyDropsSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] pub start_span: Span, @@ -766,33 +904,35 @@ pub(crate) struct UndroppedManuallyDropsSuggestion { // invalid_from_utf8.rs #[derive(LintDiagnostic)] pub(crate) enum InvalidFromUtf8Diag { - #[diag(lint_invalid_from_utf8_unchecked)] + #[diag("calls to `{$method}` with an invalid literal are undefined behavior")] Unchecked { method: String, valid_up_to: usize, - #[label] + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] label: Span, }, - #[diag(lint_invalid_from_utf8_checked)] + #[diag("calls to `{$method}` with an invalid literal always return an error")] Checked { method: String, valid_up_to: usize, - #[label] + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] label: Span, }, } // interior_mutable_consts.rs #[derive(LintDiagnostic)] -#[diag(lint_const_item_interior_mutations)] -#[note(lint_temporary)] -#[note(lint_never_original)] -#[help] +#[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")] +#[note("each usage of a `const` item creates a new temporary")] +#[note("only the temporaries and never the original `const {$const_name}` will be modified")] +#[help( + "for more details on interior mutability see " +)] pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { pub method_name: Ident, pub const_name: Ident, pub const_ty: Ty<'tcx>, - #[label] + #[label("`{$const_name}` is a interior mutable `const` item of type `{$const_ty}`")] pub receiver_span: Span, #[subdiagnostic] pub sugg_static: Option, @@ -801,7 +941,7 @@ pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { #[suggestion( - lint_suggestion_static, + "for a shared instance of `{$const_name}`, consider making it a `static` item instead", code = "{before}static ", style = "verbose", applicability = "maybe-incorrect" @@ -811,35 +951,47 @@ pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { const_: Span, before: &'static str, }, - #[help(lint_suggestion_static)] + #[help("for a shared instance of `{$const_name}`, consider making it a `static` item instead")] Spanless, } // reference_casting.rs #[derive(LintDiagnostic)] pub(crate) enum InvalidReferenceCastingDiag<'tcx> { - #[diag(lint_invalid_reference_casting_borrow_as_mut)] - #[note(lint_invalid_reference_casting_note_book)] + #[diag( + "casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`" + )] + #[note( + "for more information, visit " + )] BorrowAsMut { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + #[note( + "even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`" + )] ty_has_interior_mutability: bool, }, - #[diag(lint_invalid_reference_casting_assign_to_ref)] - #[note(lint_invalid_reference_casting_note_book)] + #[diag("assigning to `&T` is undefined behavior, consider using an `UnsafeCell`")] + #[note( + "for more information, visit " + )] AssignToRef { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + #[note( + "even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`" + )] ty_has_interior_mutability: bool, }, - #[diag(lint_invalid_reference_casting_bigger_layout)] - #[note(lint_layout)] + #[diag( + "casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused" + )] + #[note("casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes)")] BiggerLayout { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[label(lint_alloc)] + #[label("backing allocation comes from here")] alloc: Span, from_ty: Ty<'tcx>, from_size: u64, @@ -850,108 +1002,143 @@ pub(crate) enum InvalidReferenceCastingDiag<'tcx> { // map_unit_fn.rs #[derive(LintDiagnostic)] -#[diag(lint_map_unit_fn)] -#[note] +#[diag("`Iterator::map` call that discard the iterator's values")] +#[note( + "`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated" +)] pub(crate) struct MappingToUnit { - #[label(lint_function_label)] + #[label("this function returns `()`, which is likely not what you wanted")] pub function_label: Span, - #[label(lint_argument_label)] + #[label("called `Iterator::map` with callable that returns `()`")] pub argument_label: Span, - #[label(lint_map_label)] + #[label( + "after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items" + )] pub map_label: Span, - #[suggestion(style = "verbose", code = "for_each", applicability = "maybe-incorrect")] + #[suggestion( + "you might have meant to use `Iterator::for_each`", + style = "verbose", + code = "for_each", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } // internal.rs #[derive(LintDiagnostic)] -#[diag(lint_default_hash_types)] -#[note] +#[diag("prefer `{$preferred}` over `{$used}`, it has better performance")] +#[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")] pub(crate) struct DefaultHashTypesDiag<'a> { pub preferred: &'a str, pub used: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_query_instability)] -#[note] +#[diag("using `{$query}` can result in unstable query results")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] pub(crate) struct QueryInstability { pub query: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_query_untracked)] -#[note] +#[diag("`{$method}` accesses information that is not tracked by the query system")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] pub(crate) struct QueryUntracked { pub method: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_span_use_eq_ctxt)] +#[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")] pub(crate) struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] -#[diag(lint_symbol_intern_string_literal)] -#[help] +#[diag("using `Symbol::intern` on a string literal")] +#[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] pub(crate) struct SymbolInternStringLiteralDiag; #[derive(LintDiagnostic)] -#[diag(lint_tykind_kind)] +#[diag("usage of `ty::TyKind::`")] pub(crate) struct TykindKind { - #[suggestion(code = "ty", applicability = "maybe-incorrect")] + #[suggestion( + "try using `ty::` directly", + code = "ty", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_tykind)] -#[help] +#[diag("usage of `ty::TyKind`")] +#[help("try using `Ty` instead")] pub(crate) struct TykindDiag; #[derive(LintDiagnostic)] -#[diag(lint_ty_qualified)] +#[diag("usage of qualified `ty::{$ty}`")] pub(crate) struct TyQualified { pub ty: String, - #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + #[suggestion( + "try importing it and using it unqualified", + code = "{ty}", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_type_ir_inherent_usage)] -#[note] +#[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] pub(crate) struct TypeIrInherentUsage; #[derive(LintDiagnostic)] -#[diag(lint_type_ir_trait_usage)] -#[note] +#[diag( + "do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver" +)] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] pub(crate) struct TypeIrTraitUsage; #[derive(LintDiagnostic)] -#[diag(lint_type_ir_direct_use)] -#[note] +#[diag("do not use `rustc_type_ir` unless you are implementing type system internals")] +#[note("use `rustc_middle::ty` instead")] pub(crate) struct TypeIrDirectUse; #[derive(LintDiagnostic)] -#[diag(lint_non_glob_import_type_ir_inherent)] +#[diag("non-glob import of `rustc_type_ir::inherent`")] pub(crate) struct NonGlobImportTypeIrInherent { - #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")] + #[suggestion( + "try using a glob import instead", + code = "{snippet}", + applicability = "maybe-incorrect" + )] pub suggestion: Option, pub snippet: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_lintpass_by_hand)] -#[help] +#[diag("implementing `LintPass` by hand")] +#[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")] pub(crate) struct LintPassByHand; #[derive(LintDiagnostic)] -#[diag(lint_bad_opt_access)] +#[diag("{$msg}")] pub(crate) struct BadOptAccessDiag<'a> { pub msg: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_implicit_sysroot_crate_import)] -#[help] +#[diag( + "dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot" +)] +#[help( + "try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate" +)] pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { pub name: &'a str, } @@ -959,14 +1146,14 @@ pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { // let_underscore.rs #[derive(LintDiagnostic)] pub(crate) enum NonBindingLet { - #[diag(lint_non_binding_let_on_sync_lock)] + #[diag("non-binding let on a synchronization lock")] SyncLock { - #[label] + #[label("this lock is not assigned to a binding and is immediately dropped")] pat: Span, #[subdiagnostic] sub: NonBindingLetSub, }, - #[diag(lint_non_binding_let_on_drop_type)] + #[diag("non-binding let on a type that has a destructor")] DropType { #[subdiagnostic] sub: NonBindingLetSub, @@ -987,16 +1174,23 @@ impl Subdiagnostic for NonBindingLetSub { let prefix = if self.is_assign_desugar { "let " } else { "" }; diag.span_suggestion_verbose( self.suggestion, - fluent::lint_non_binding_let_suggestion, + msg!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), format!("{prefix}_unused"), Applicability::MachineApplicable, ); } else { - diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion); + diag.span_help( + self.suggestion, + msg!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), + ); } if let Some(drop_fn_start_end) = self.drop_fn_start_end { diag.multipart_suggestion( - fluent::lint_non_binding_let_multi_suggestion, + msg!("consider immediately dropping the value"), vec![ (drop_fn_start_end.0, "drop(".to_string()), (drop_fn_start_end.1, ")".to_string()), @@ -1004,16 +1198,18 @@ impl Subdiagnostic for NonBindingLetSub { Applicability::MachineApplicable, ); } else { - diag.help(fluent::lint_non_binding_let_multi_drop_fn); + diag.help(msg!( + "consider immediately dropping the value using `drop(..)` after the `let` statement" + )); } } } // levels.rs #[derive(LintDiagnostic)] -#[diag(lint_overruled_attribute)] +#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")] pub(crate) struct OverruledAttributeLint<'a> { - #[label] + #[label("overruled by previous forbid")] pub overruled: Span, pub lint_level: &'a str, pub lint_source: Symbol, @@ -1022,17 +1218,17 @@ pub(crate) struct OverruledAttributeLint<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_lint_name)] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] pub(crate) struct DeprecatedLintName<'a> { pub name: String, - #[suggestion(code = "{replace}", applicability = "machine-applicable")] + #[suggestion("change it to", code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, pub replace: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_lint_name)] -#[help] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] +#[help("change it to {$replace}")] pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { pub name: String, pub replace: &'a str, @@ -1041,7 +1237,7 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_renamed_lint)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLint<'a> { pub name: &'a str, pub replace: &'a str, @@ -1051,18 +1247,18 @@ pub(crate) struct RenamedLint<'a> { #[derive(Subdiagnostic)] pub(crate) enum RenamedLintSuggestion<'a> { - #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] + #[suggestion("use the new name", code = "{replace}", applicability = "machine-applicable")] WithSpan { #[primary_span] suggestion: Span, replace: &'a str, }, - #[help(lint_help)] + #[help("use the new name `{$replace}`")] WithoutSpan { replace: &'a str }, } #[derive(LintDiagnostic)] -#[diag(lint_renamed_lint)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLintFromCommandLine<'a> { pub name: &'a str, pub replace: &'a str, @@ -1073,14 +1269,14 @@ pub(crate) struct RenamedLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_removed_lint)] +#[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLint<'a> { pub name: &'a str, pub reason: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_removed_lint)] +#[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLintFromCommandLine<'a> { pub name: &'a str, pub reason: &'a str, @@ -1089,7 +1285,7 @@ pub(crate) struct RemovedLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_unknown_lint)] +#[diag("unknown lint: `{$name}`")] pub(crate) struct UnknownLint { pub name: String, #[subdiagnostic] @@ -1098,19 +1294,31 @@ pub(crate) struct UnknownLint { #[derive(Subdiagnostic)] pub(crate) enum UnknownLintSuggestion { - #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] + #[suggestion( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints + *[false] did you mean + }", + code = "{replace}", + applicability = "maybe-incorrect" + )] WithSpan { #[primary_span] suggestion: Span, replace: Symbol, from_rustc: bool, }, - #[help(lint_help)] + #[help( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints: `{$replace}` + *[false] did you mean: `{$replace}` + }" + )] WithoutSpan { replace: Symbol, from_rustc: bool }, } #[derive(LintDiagnostic)] -#[diag(lint_unknown_lint, code = E0602)] +#[diag("unknown lint: `{$name}`", code = E0602)] pub(crate) struct UnknownLintFromCommandLine<'a> { pub name: String, #[subdiagnostic] @@ -1120,7 +1328,7 @@ pub(crate) struct UnknownLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_ignored_unless_crate_specified)] +#[diag("{$level}({$name}) is ignored unless specified at crate level")] pub(crate) struct IgnoredUnlessCrateSpecified<'a> { pub level: &'a str, pub name: Symbol, @@ -1128,53 +1336,78 @@ pub(crate) struct IgnoredUnlessCrateSpecified<'a> { // dangling.rs #[derive(LintDiagnostic)] -#[diag(lint_dangling_pointers_from_temporaries)] -#[help(lint_help_bind)] -#[note(lint_note_safe)] -#[note(lint_note_return)] -#[note(lint_note_more_info)] +#[diag("this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement")] +#[help("bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("returning a pointer to a local variable will always result in a dangling pointer")] +#[note("for more information, see ")] // FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts pub(crate) struct DanglingPointersFromTemporaries<'tcx> { pub callee: Ident, pub ty: Ty<'tcx>, - #[label(lint_label_ptr)] + #[label("pointer created here")] pub ptr_span: Span, - #[label(lint_label_temporary)] + #[label("this `{$ty}` is dropped at end of statement")] pub temporary_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_dangling_pointers_from_locals)] -#[note(lint_note_safe)] -#[note(lint_note_more_info)] +#[diag("{$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("for more information, see ")] pub(crate) struct DanglingPointersFromLocals<'tcx> { pub ret_ty: Ty<'tcx>, - #[label(lint_ret_ty)] + #[label("return type is `{$ret_ty}`")] pub ret_ty_span: Span, pub fn_kind: &'static str, - #[label(lint_local_var)] + #[label("local variable `{$local_var_name}` is dropped at the end of the {$fn_kind}")] pub local_var: Span, pub local_var_name: Ident, pub local_var_ty: Ty<'tcx>, - #[label(lint_created_at)] + #[label("dangling pointer created here")] pub created_at: Option, } // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] -#[diag(lint_multiple_supertrait_upcastable)] +#[diag("`{$ident}` is dyn-compatible and has multiple supertraits")] pub(crate) struct MultipleSupertraitUpcastable { pub ident: Ident, } // non_ascii_idents.rs #[derive(LintDiagnostic)] -#[diag(lint_identifier_non_ascii_char)] +#[diag("identifier contains non-ASCII characters")] pub(crate) struct IdentifierNonAsciiChar; #[derive(LintDiagnostic)] -#[diag(lint_identifier_uncommon_codepoints)] -#[note] +#[diag( + "identifier contains {$codepoints_len -> + [one] { $identifier_type -> + [Exclusion] a character from an archaic script + [Technical] a character that is for non-linguistic, specialized usage + [Limited_Use] a character from a script in limited use + [Not_NFKC] a non normalized (NFKC) character + *[other] an uncommon character + } + *[other] { $identifier_type -> + [Exclusion] {$codepoints_len} characters from archaic scripts + [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage + [Limited_Use] {$codepoints_len} characters from scripts in limited use + [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters + *[other] uncommon characters + } + }: {$codepoints}" +)] +#[note( + r#"{$codepoints_len -> + [one] this character is + *[other] these characters are + } included in the{$identifier_type -> + [Restricted] {""} + *[other] {" "}{$identifier_type} + } Unicode general security profile"# +)] pub(crate) struct IdentifierUncommonCodepoints { pub codepoints: Vec, pub codepoints_len: usize, @@ -1182,20 +1415,22 @@ pub(crate) struct IdentifierUncommonCodepoints { } #[derive(LintDiagnostic)] -#[diag(lint_confusable_identifier_pair)] +#[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")] pub(crate) struct ConfusableIdentifierPair { pub existing_sym: Symbol, pub sym: Symbol, - #[label(lint_other_use)] + #[label("other identifier used here")] pub label: Span, - #[label(lint_current_use)] + #[label("this identifier can be confused with `{$existing_sym}`")] pub main_label: Span, } #[derive(LintDiagnostic)] -#[diag(lint_mixed_script_confusables)] -#[note(lint_includes_note)] -#[note] +#[diag( + "the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables" +)] +#[note("the usage includes {$includes}")] +#[note("please recheck to make sure their usages are indeed what you want")] pub(crate) struct MixedScriptConfusables { pub set: String, pub includes: String, @@ -1210,19 +1445,32 @@ pub(crate) struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_non_fmt_panic_unused); + diag.primary_message(msg!( + "panic message contains {$count -> + [one] an unused + *[other] unused + } formatting {$count -> + [one] placeholder + *[other] placeholders + }" + )); diag.arg("count", self.count); - diag.note(fluent::lint_note); + diag.note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); if let Some(span) = self.suggestion { diag.span_suggestion( span.shrink_to_hi(), - fluent::lint_add_args_suggestion, + msg!( + "add the missing {$count -> + [one] argument + *[other] arguments + }" + ), ", ...", Applicability::HasPlaceholders, ); diag.span_suggestion( span.shrink_to_lo(), - fluent::lint_add_fmt_suggestion, + msg!(r#"or add a "{"{"}{"}"}" format string to use the message literally"#), "\"{}\", ", Applicability::MachineApplicable, ); @@ -1231,17 +1479,26 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { } #[derive(LintDiagnostic)] -#[diag(lint_non_fmt_panic_braces)] -#[note] +#[diag( + "panic message contains {$count -> + [one] a brace + *[other] braces + }" +)] +#[note("this message is not used as a format string, but will be in Rust 2021")] pub(crate) struct NonFmtPanicBraces { pub count: usize, - #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")] + #[suggestion( + "add a \"{\"{\"}{\"}\"}\" format string to use the message literally", + code = "\"{{}}\", ", + applicability = "machine-applicable" + )] pub suggestion: Option, } // nonstandard_style.rs #[derive(LintDiagnostic)] -#[diag(lint_non_camel_case_type)] +#[diag("{$sort} `{$name}` should have an upper camel case name")] pub(crate) struct NonCamelCaseType<'a> { pub sort: &'a str, pub name: &'a str, @@ -1251,12 +1508,16 @@ pub(crate) struct NonCamelCaseType<'a> { #[derive(Subdiagnostic)] pub(crate) enum NonCamelCaseTypeSub { - #[label(lint_label)] + #[label("should have an UpperCamelCase name")] Label { #[primary_span] span: Span, }, - #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] + #[suggestion( + "convert the identifier to upper camel case", + code = "{replace}", + applicability = "maybe-incorrect" + )] Suggestion { #[primary_span] span: Span, @@ -1265,7 +1526,7 @@ pub(crate) enum NonCamelCaseTypeSub { } #[derive(LintDiagnostic)] -#[diag(lint_non_snake_case)] +#[diag("{$sort} `{$name}` should have a snake case name")] pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, pub name: &'a str, @@ -1286,15 +1547,15 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { NonSnakeCaseDiagSub::Label { span } => { - diag.span_label(span, fluent::lint_label); + diag.span_label(span, msg!("should have a snake_case name")); } NonSnakeCaseDiagSub::Help => { - diag.help(fluent::lint_help); + diag.help(msg!("convert the identifier to snake case: `{$sc}`")); } NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - fluent::lint_convert_suggestion, + msg!("convert the identifier to snake case"), suggestion, Applicability::MaybeIncorrect, ); @@ -1302,16 +1563,16 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - fluent::lint_rename_or_convert_suggestion, + msg!("rename the identifier or convert it to a snake case raw identifier"), suggestion, Applicability::MaybeIncorrect, ); } NonSnakeCaseDiagSub::SuggestionAndNote { span } => { - diag.note(fluent::lint_cannot_convert_note); + diag.note(msg!("`{$sc}` cannot be used as a raw identifier")); diag.span_suggestion( span, - fluent::lint_rename_suggestion, + msg!("rename the identifier"), "", Applicability::MaybeIncorrect, ); @@ -1321,7 +1582,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { } #[derive(LintDiagnostic)] -#[diag(lint_non_upper_case_global)] +#[diag("{$sort} `{$name}` should have an upper case name")] pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str, pub name: &'a str, @@ -1333,12 +1594,12 @@ pub(crate) struct NonUpperCaseGlobal<'a> { #[derive(Subdiagnostic)] pub(crate) enum NonUpperCaseGlobalSub { - #[label(lint_label)] + #[label("should have an UPPER_CASE name")] Label { #[primary_span] span: Span, }, - #[suggestion(lint_suggestion, code = "{replace}")] + #[suggestion("convert the identifier to upper case", code = "{replace}")] Suggestion { #[primary_span] span: Span, @@ -1350,7 +1611,7 @@ pub(crate) enum NonUpperCaseGlobalSub { #[derive(Subdiagnostic)] #[suggestion( - lint_suggestion, + "convert the identifier to upper case", code = "{replace}", applicability = "machine-applicable", style = "tool-only" @@ -1363,16 +1624,18 @@ pub(crate) struct NonUpperCaseGlobalSubTool { // noop_method_call.rs #[derive(LintDiagnostic)] -#[diag(lint_noop_method_call)] -#[note] +#[diag("call to `.{$method}()` on a reference in this situation does nothing")] +#[note( + "the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed" +)] pub(crate) struct NoopMethodCallDiag<'a> { pub method: Ident, pub orig_ty: Ty<'a>, pub trait_: Symbol, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this redundant call", code = "", applicability = "machine-applicable")] pub label: Span, #[suggestion( - lint_derive_suggestion, + "if you meant to clone `{$orig_ty}`, implement `Clone` for it", code = "#[derive(Clone)]\n", applicability = "maybe-incorrect" )] @@ -1380,13 +1643,17 @@ pub(crate) struct NoopMethodCallDiag<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_suspicious_double_ref_deref)] +#[diag( + "using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type" +)] pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_suspicious_double_ref_clone)] +#[diag( + "using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type" +)] pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { pub ty: Ty<'a>, } @@ -1423,7 +1690,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, macro_to_change, } => { - diag.primary_message(fluent::lint_non_local_definitions_impl); + diag.primary_message(msg!("non-local `impl` definition, `impl` blocks should be written at the same level as their item")); diag.arg("depth", depth); diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); @@ -1431,24 +1698,24 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { if let Some((macro_to_change, macro_kind)) = macro_to_change { diag.arg("macro_to_change", macro_to_change); diag.arg("macro_kind", macro_kind); - diag.note(fluent::lint_macro_to_change); + diag.note(msg!("the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed")); } if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); } - diag.note(fluent::lint_non_local); + diag.note(msg!("an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`")); if doctest { - diag.help(fluent::lint_doctest); + diag.help(msg!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); } if let Some(const_anon) = const_anon { - diag.note(fluent::lint_exception); + diag.note(msg!("items in an anonymous const item (`const _: () = {\"{\"} ... {\"}\"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint")); if let Some(const_anon) = const_anon { diag.span_suggestion( const_anon, - fluent::lint_const_anon, + msg!("use a const-anon item to suppress this lint"), "_", Applicability::MachineApplicable, ); @@ -1462,18 +1729,23 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, cargo_update, } => { - diag.primary_message(fluent::lint_non_local_definitions_macro_rules); + diag.primary_message(msg!("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")); diag.arg("depth", depth); diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); if doctest { - diag.help(fluent::lint_help_doctest); + diag.help(msg!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); } else { - diag.help(fluent::lint_help); + diag.help(msg!( + "remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }" + )); } - diag.note(fluent::lint_non_local); + diag.note(msg!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); @@ -1484,7 +1756,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } #[derive(Subdiagnostic)] -#[note(lint_non_local_definitions_cargo_update)] +#[note( + "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" +)] pub(crate) struct NonLocalDefinitionsCargoUpdateNote { pub macro_kind: &'static str, pub macro_name: Symbol, @@ -1493,8 +1767,8 @@ pub(crate) struct NonLocalDefinitionsCargoUpdateNote { // precedence.rs #[derive(LintDiagnostic)] -#[diag(lint_ambiguous_negative_literals)] -#[note(lint_example)] +#[diag("`-` has lower precedence than method calls, which might be unexpected")] +#[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")] pub(crate) struct AmbiguousNegativeLiteralsDiag { #[subdiagnostic] pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, @@ -1503,7 +1777,10 @@ pub(crate) struct AmbiguousNegativeLiteralsDiag { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "add parentheses around the `-` and the literal to call the method on a negative literal", + applicability = "maybe-incorrect" +)] pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, @@ -1512,7 +1789,10 @@ pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "add parentheses around the literal and the method call to keep the current behavior", + applicability = "maybe-incorrect" +)] pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, @@ -1522,16 +1802,21 @@ pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { // pass_by_value.rs #[derive(LintDiagnostic)] -#[diag(lint_pass_by_value)] +#[diag("passing `{$ty}` by reference")] pub(crate) struct PassByValueDiag { pub ty: String, - #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + #[suggestion("try passing by value", code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, } // redundant_semicolon.rs #[derive(LintDiagnostic)] -#[diag(lint_redundant_semicolons)] +#[diag( + "unnecessary trailing {$multiple -> + [true] semicolons + *[false] semicolon + }" +)] pub(crate) struct RedundantSemicolonsDiag { pub multiple: bool, #[subdiagnostic] @@ -1539,7 +1824,14 @@ pub(crate) struct RedundantSemicolonsDiag { } #[derive(Subdiagnostic)] -#[suggestion(lint_redundant_semicolons_suggestion, code = "", applicability = "maybe-incorrect")] +#[suggestion( + "remove {$multiple_semicolons -> + [true] these semicolons + *[false] this semicolon + }", + code = "", + applicability = "maybe-incorrect" +)] pub(crate) struct RedundantSemicolonsSuggestion { pub multiple_semicolons: bool, #[primary_span] @@ -1556,7 +1848,7 @@ pub(crate) struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_drop_trait_constraints); + diag.primary_message(msg!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")); diag.arg("predicate", self.predicate); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } @@ -1570,19 +1862,27 @@ pub(crate) struct DropGlue<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_drop_glue); + diag.primary_message(msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } } // transmute.rs #[derive(LintDiagnostic)] -#[diag(lint_int_to_ptr_transmutes)] -#[note] -#[note(lint_note_exposed_provenance)] -#[help(lint_suggestion_without_provenance_mut)] -#[help(lint_help_transmute)] -#[help(lint_help_exposed_provenance)] +#[diag("transmuting an integer to a pointer creates a pointer without provenance")] +#[note("this is dangerous because dereferencing the resulting pointer is undefined behavior")] +#[note( + "exposed provenance semantics can be used to create a pointer based on some previously exposed provenance" +)] +#[help( + "if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`" +)] +#[help( + "for more information about transmute, see " +)] +#[help( + "for more information about exposed provenance, see " +)] pub(crate) struct IntegerToPtrTransmutes<'tcx> { #[subdiagnostic] pub suggestion: Option>, @@ -1591,7 +1891,7 @@ pub(crate) struct IntegerToPtrTransmutes<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { #[multipart_suggestion( - lint_suggestion_with_exposed_provenance, + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] @@ -1602,7 +1902,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { start_call: Span, }, #[multipart_suggestion( - lint_suggestion_with_exposed_provenance, + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] @@ -1619,7 +1919,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { // types.rs #[derive(LintDiagnostic)] -#[diag(lint_range_endpoint_out_of_range)] +#[diag("range endpoint is out of range for `{$ty}`")] pub(crate) struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, #[subdiagnostic] @@ -1629,7 +1929,7 @@ pub(crate) struct RangeEndpointOutOfRange<'a> { #[derive(Subdiagnostic)] pub(crate) enum UseInclusiveRange<'a> { #[suggestion( - lint_range_use_inclusive_range, + "use an inclusive range instead", code = "{start}..={literal}{suffix}", applicability = "machine-applicable" )] @@ -1640,7 +1940,7 @@ pub(crate) enum UseInclusiveRange<'a> { literal: u128, suffix: &'a str, }, - #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")] + #[multipart_suggestion("use an inclusive range instead", applicability = "machine-applicable")] WithParen { #[suggestion_part(code = "=")] eq_sugg: Span, @@ -1652,7 +1952,7 @@ pub(crate) enum UseInclusiveRange<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_bin_hex)] +#[diag("literal out of range for `{$ty}`")] pub(crate) struct OverflowingBinHex<'a> { pub ty: &'a str, pub lit: String, @@ -1666,29 +1966,21 @@ pub(crate) struct OverflowingBinHex<'a> { pub sign_bit_sub: Option>, } +#[derive(Subdiagnostic)] pub(crate) enum OverflowingBinHexSign { + #[note( + "the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`" + )] Positive, + #[note("the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`")] + #[note("and the value `-{$lit}` will become `{$actually}{$ty}`")] Negative, } -impl Subdiagnostic for OverflowingBinHexSign { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - match self { - OverflowingBinHexSign::Positive => { - diag.note(fluent::lint_positive_note); - } - OverflowingBinHexSign::Negative => { - diag.note(fluent::lint_negative_note); - diag.note(fluent::lint_negative_becomes_note); - } - } - } -} - #[derive(Subdiagnostic)] pub(crate) enum OverflowingBinHexSub<'a> { #[suggestion( - lint_suggestion, + "consider using the type `{$suggestion_ty}` instead", code = "{sans_suffix}{suggestion_ty}", applicability = "machine-applicable" )] @@ -1698,13 +1990,13 @@ pub(crate) enum OverflowingBinHexSub<'a> { suggestion_ty: &'a str, sans_suffix: &'a str, }, - #[help(lint_help)] + #[help("consider using the type `{$suggestion_ty}` instead")] Help { suggestion_ty: &'a str }, } #[derive(Subdiagnostic)] #[suggestion( - lint_sign_bit_suggestion, + "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", code = "{lit_no_suffix}{uint_ty} as {int_ty}", applicability = "maybe-incorrect" )] @@ -1718,8 +2010,8 @@ pub(crate) struct OverflowingBinHexSignBitSub<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_int)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, @@ -1730,22 +2022,26 @@ pub(crate) struct OverflowingInt<'a> { } #[derive(Subdiagnostic)] -#[help(lint_help)] +#[help("consider using the type `{$suggestion_ty}` instead")] pub(crate) struct OverflowingIntHelp<'a> { pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_only_cast_u8_to_char)] +#[diag("only `u8` can be cast into `char`")] pub(crate) struct OnlyCastu8ToChar { - #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")] + #[suggestion( + "use a `char` literal instead", + code = "'\\u{{{literal:X}}}'", + applicability = "machine-applicable" + )] pub span: Span, pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_uint)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingUInt<'a> { pub ty: &'a str, pub lit: String, @@ -1754,50 +2050,54 @@ pub(crate) struct OverflowingUInt<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_literal)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note( + "the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`" +)] pub(crate) struct OverflowingLiteral<'a> { pub ty: &'a str, pub lit: String, } #[derive(LintDiagnostic)] -#[diag(lint_surrogate_char_cast)] -#[note] +#[diag("surrogate values are not valid for `char`")] +#[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")] pub(crate) struct SurrogateCharCast { pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_too_large_char_cast)] -#[note] +#[diag("value exceeds maximum `char` value")] +#[note("maximum valid `char` value is `0x10FFFF`")] pub(crate) struct TooLargeCharCast { pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_uses_power_alignment)] +#[diag( + "repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type" +)] pub(crate) struct UsesPowerAlignment; #[derive(LintDiagnostic)] -#[diag(lint_unused_comparisons)] +#[diag("comparison is useless due to type limits")] pub(crate) struct UnusedComparisons; #[derive(LintDiagnostic)] pub(crate) enum InvalidNanComparisons { - #[diag(lint_invalid_nan_comparisons_eq_ne)] + #[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")] EqNe { #[subdiagnostic] suggestion: InvalidNanComparisonsSuggestion, }, - #[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)] + #[diag("incorrect NaN comparison, NaN is not orderable")] LtLeGtGe, } #[derive(Subdiagnostic)] pub(crate) enum InvalidNanComparisonsSuggestion { #[multipart_suggestion( - lint_suggestion, + "use `f32::is_nan()` or `f64::is_nan()` instead", style = "verbose", applicability = "machine-applicable" )] @@ -1809,35 +2109,41 @@ pub(crate) enum InvalidNanComparisonsSuggestion { #[suggestion_part(code = "")] nan_plus_binop: Span, }, - #[help(lint_suggestion)] + #[help("use `f32::is_nan()` or `f64::is_nan()` instead")] Spanless, } #[derive(LintDiagnostic)] pub(crate) enum AmbiguousWidePointerComparisons<'a> { - #[diag(lint_ambiguous_wide_pointer_comparisons)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] SpanfulEq { #[subdiagnostic] addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>, #[subdiagnostic] addr_metadata_suggestion: Option>, }, - #[diag(lint_ambiguous_wide_pointer_comparisons)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] SpanfulCmp { #[subdiagnostic] cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>, #[subdiagnostic] expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>, }, - #[diag(lint_ambiguous_wide_pointer_comparisons)] - #[help(lint_addr_metadata_suggestion)] - #[help(lint_addr_suggestion)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + #[help("use explicit `std::ptr::eq` method to compare metadata and addresses")] + #[help("use `std::ptr::addr_eq` or untyped pointers to only compare their addresses")] Spanless, } #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_addr_metadata_suggestion, + "use explicit `std::ptr::eq` method to compare metadata and addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1858,7 +2164,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_addr_suggestion, + "use `std::ptr::addr_eq` or untyped pointers to only compare their addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1879,7 +2185,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_cast_suggestion, + "use untyped pointers to only compare their addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1903,7 +2209,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_expect_suggestion, + "or expect the lint to compare the pointers metadata and addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1922,25 +2228,37 @@ pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { #[derive(LintDiagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { - #[diag(lint_unpredictable_fn_pointer_comparisons)] - #[note(lint_note_duplicated_fn)] - #[note(lint_note_deduplicated_fn)] - #[note(lint_note_visit_fn_addr_eq)] + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] Suggestion { #[subdiagnostic] sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>, }, - #[diag(lint_unpredictable_fn_pointer_comparisons)] - #[note(lint_note_duplicated_fn)] - #[note(lint_note_deduplicated_fn)] - #[note(lint_note_visit_fn_addr_eq)] + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] Warn, } #[derive(Subdiagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { #[multipart_suggestion( - lint_fn_addr_eq_suggestion, + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] @@ -1956,7 +2274,7 @@ pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { right: Span, }, #[multipart_suggestion( - lint_fn_addr_eq_suggestion, + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] @@ -1986,69 +2304,71 @@ pub(crate) struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagMessage, and Option impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_improper_ctypes); + diag.primary_message(msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe")); diag.arg("ty", self.ty); diag.arg("desc", self.desc); - diag.span_label(self.label, fluent::lint_label); + diag.span_label(self.label, msg!("not FFI-safe")); if let Some(help) = self.help { diag.help(help); } diag.note(self.note); if let Some(note) = self.span_note { - diag.span_note(note, fluent::lint_note); + diag.span_note(note, msg!("the type is defined here")); } } } #[derive(LintDiagnostic)] -#[diag(lint_improper_gpu_kernel_arg)] -#[help] +#[diag("passing type `{$ty}` to a function with \"gpu-kernel\" ABI may have unexpected behavior")] +#[help("use primitive types and raw pointers to get reliable behavior")] pub(crate) struct ImproperGpuKernelArg<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_missing_gpu_kernel_export_name)] -#[help] -#[note] +#[diag("function with the \"gpu-kernel\" ABI has a mangled name")] +#[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"\")`")] +#[note("mangled names make it hard to find the kernel, this is usually not intended")] pub(crate) struct MissingGpuKernelExportName; #[derive(LintDiagnostic)] -#[diag(lint_variant_size_differences)] +#[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")] pub(crate) struct VariantSizeDifferencesDiag { pub largest: u64, } #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_load)] -#[help] +#[diag("atomic loads cannot have `Release` or `AcqRel` ordering")] +#[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingLoad; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_store)] -#[help] +#[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")] +#[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingStore; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_fence)] -#[help] +#[diag("memory fences cannot have `Relaxed` ordering")] +#[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")] pub(crate) struct AtomicOrderingFence; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_invalid)] -#[help] +#[diag( + "`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write" +)] +#[help("consider using `Acquire` or `Relaxed` failure ordering instead")] pub(crate) struct InvalidAtomicOrderingDiag { pub method: Symbol, - #[label] + #[label("invalid failure ordering")] pub fail_order_arg_span: Span, } // unused.rs #[derive(LintDiagnostic)] -#[diag(lint_unused_op)] +#[diag("unused {$op} that must be used")] pub(crate) struct UnusedOp<'a> { pub op: &'a str, - #[label] + #[label("the {$op} produces a value")] pub label: Span, #[subdiagnostic] pub suggestion: UnusedOpSuggestion, @@ -2057,7 +2377,7 @@ pub(crate) struct UnusedOp<'a> { #[derive(Subdiagnostic)] pub(crate) enum UnusedOpSuggestion { #[suggestion( - lint_suggestion, + "use `let _ = ...` to ignore the resulting value", style = "verbose", code = "let _ = ", applicability = "maybe-incorrect" @@ -2066,7 +2386,11 @@ pub(crate) enum UnusedOpSuggestion { #[primary_span] span: Span, }, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] BlockTailExpr { #[suggestion_part(code = "let _ = ")] before_span: Span, @@ -2076,7 +2400,7 @@ pub(crate) enum UnusedOpSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_result)] +#[diag("unused result of type `{$ty}`")] pub(crate) struct UnusedResult<'a> { pub ty: Ty<'a>, } @@ -2084,8 +2408,13 @@ pub(crate) struct UnusedResult<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] -#[diag(lint_unused_closure)] -#[note] +#[diag( + "unused {$pre}{$count -> + [one] closure + *[other] closures + }{$post} that must be used" +)] +#[note("closures are lazy and do nothing unless called")] pub(crate) struct UnusedClosure<'a> { pub count: usize, pub pre: &'a str, @@ -2095,8 +2424,13 @@ pub(crate) struct UnusedClosure<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] -#[diag(lint_unused_coroutine)] -#[note] +#[diag( + "unused {$pre}{$count -> + [one] coroutine + *[other] coroutine + }{$post} that must be used" +)] +#[note("coroutines are lazy and do nothing unless resumed")] pub(crate) struct UnusedCoroutine<'a> { pub count: usize, pub pre: &'a str, @@ -2115,10 +2449,9 @@ pub(crate) struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] - pub(crate) enum UnusedDefSuggestion { #[suggestion( - lint_suggestion, + "use `let _ = ...` to ignore the resulting value", style = "verbose", code = "let _ = ", applicability = "maybe-incorrect" @@ -2127,7 +2460,11 @@ pub(crate) enum UnusedDefSuggestion { #[primary_span] span: Span, }, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] BlockTailExpr { #[suggestion_part(code = "let _ = ")] before_span: Span, @@ -2139,7 +2476,7 @@ pub(crate) enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_unused_def); + diag.primary_message(msg!("unused {$pre}`{$def}`{$post} that must be used")); diag.arg("pre", self.pre); diag.arg("post", self.post); diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); @@ -2154,7 +2491,7 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { } #[derive(LintDiagnostic)] -#[diag(lint_path_statement_drop)] +#[diag("path statement drops value")] pub(crate) struct PathStatementDrop { #[subdiagnostic] pub sub: PathStatementDropSub, @@ -2162,13 +2499,17 @@ pub(crate) struct PathStatementDrop { #[derive(Subdiagnostic)] pub(crate) enum PathStatementDropSub { - #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")] + #[suggestion( + "use `drop` to clarify the intent", + code = "drop({snippet});", + applicability = "machine-applicable" + )] Suggestion { #[primary_span] span: Span, snippet: String, }, - #[help(lint_help)] + #[help("use `drop` to clarify the intent")] Help { #[primary_span] span: Span, @@ -2176,11 +2517,11 @@ pub(crate) enum PathStatementDropSub { } #[derive(LintDiagnostic)] -#[diag(lint_path_statement_no_effect)] +#[diag("path statement with no effect")] pub(crate) struct PathStatementNoEffect; #[derive(LintDiagnostic)] -#[diag(lint_unused_delim)] +#[diag("unnecessary {$delim} around {$item}")] pub(crate) struct UnusedDelim<'a> { pub delim: &'static str, pub item: &'a str, @@ -2189,7 +2530,7 @@ pub(crate) struct UnusedDelim<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("remove these {$delim}", applicability = "machine-applicable")] pub(crate) struct UnusedDelimSuggestion { #[suggestion_part(code = "{start_replace}")] pub start_span: Span, @@ -2200,17 +2541,17 @@ pub(crate) struct UnusedDelimSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_import_braces)] +#[diag("braces around {$node} is unnecessary")] pub(crate) struct UnusedImportBracesDiag { pub node: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_unused_allocation)] +#[diag("unnecessary allocation, use `&` instead")] pub(crate) struct UnusedAllocationDiag; #[derive(LintDiagnostic)] -#[diag(lint_unused_allocation_mut)] +#[diag("unnecessary allocation, use `&mut` instead")] pub(crate) struct UnusedAllocationMutDiag; pub(crate) struct AsyncFnInTraitDiag { @@ -2219,59 +2560,67 @@ pub(crate) struct AsyncFnInTraitDiag { impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_async_fn_in_trait); - diag.note(fluent::lint_note); + diag.primary_message(msg!("use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified")); + diag.note(msg!("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`")); if let Some(sugg) = self.sugg { - diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); + diag.multipart_suggestion(msg!("you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change"), sugg, Applicability::MaybeIncorrect); } } } #[derive(LintDiagnostic)] -#[diag(lint_unit_bindings)] +#[diag("binding has unit type `()`")] pub(crate) struct UnitBindingsDiag { - #[label] + #[label("this pattern is inferred to be the unit type `()`")] pub label: Span, } #[derive(LintDiagnostic)] pub(crate) enum InvalidAsmLabel { - #[diag(lint_invalid_asm_label_named)] - #[help] - #[note] + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note( + "see the asm section of Rust By Example for more information" + )] Named { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, }, - #[diag(lint_invalid_asm_label_format_arg)] - #[help] - #[note(lint_note1)] - #[note(lint_note2)] + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note("format arguments may expand to a non-numeric value")] + #[note( + "see the asm section of Rust By Example for more information" + )] FormatArg { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, }, - #[diag(lint_invalid_asm_label_binary)] - #[help] - #[note(lint_note1)] - #[note(lint_note2)] + #[diag("avoid using labels containing only the digits `0` and `1` in inline assembly")] + #[help("start numbering with `2` instead")] + #[note("an LLVM bug makes these labels ambiguous with a binary literal number on x86")] + #[note("see for more information")] Binary { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, // hack to get a label on the whole span, must match the emitted span - #[label] + #[label("use a different label that doesn't start with `0` or `1`")] span: Span, }, } #[derive(Subdiagnostic)] pub(crate) enum UnexpectedCfgCargoHelp { - #[help(lint_unexpected_cfg_add_cargo_feature)] - #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] + #[help("consider using a Cargo feature instead")] + #[help( + "or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}" + )] LintCfg { cargo_toml_lint_cfg: String }, - #[help(lint_unexpected_cfg_add_cargo_feature)] - #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] - #[help(lint_unexpected_cfg_add_build_rs_println)] + #[help("consider using a Cargo feature instead")] + #[help( + "or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}" + )] + #[help("or consider adding `{$build_rs_println}` to the top of the `build.rs`")] LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String }, } @@ -2297,7 +2646,7 @@ impl UnexpectedCfgCargoHelp { } #[derive(Subdiagnostic)] -#[help(lint_unexpected_cfg_add_cmdline_arg)] +#[help("to expect this configuration use `{$cmdline_arg}`")] pub(crate) struct UnexpectedCfgRustcHelp { pub cmdline_arg: String, } @@ -2309,17 +2658,23 @@ impl UnexpectedCfgRustcHelp { } #[derive(Subdiagnostic)] -#[note(lint_unexpected_cfg_from_external_macro_origin)] -#[help(lint_unexpected_cfg_from_external_macro_refer)] +#[note( + "using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate" +)] +#[help("try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg")] pub(crate) struct UnexpectedCfgRustcMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, } #[derive(Subdiagnostic)] -#[note(lint_unexpected_cfg_from_external_macro_origin)] -#[help(lint_unexpected_cfg_from_external_macro_refer)] -#[help(lint_unexpected_cfg_cargo_update)] +#[note( + "using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate" +)] +#[help("try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg")] +#[help( + "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" +)] pub(crate) struct UnexpectedCfgCargoMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, @@ -2327,7 +2682,7 @@ pub(crate) struct UnexpectedCfgCargoMacroHelp { } #[derive(LintDiagnostic)] -#[diag(lint_unexpected_cfg_name)] +#[diag("unexpected `cfg` condition name: `{$name}`")] pub(crate) struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, @@ -2344,10 +2699,10 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] pub(crate) enum CodeSuggestion { - #[help(lint_unexpected_cfg_define_features)] + #[help("consider defining some features in `Cargo.toml`")] DefineFeatures, #[multipart_suggestion( - lint_unexpected_cfg_name_version_syntax, + "there is a similar config predicate: `version(\"..\")`", applicability = "machine-applicable" )] VersionSyntax { @@ -2357,7 +2712,7 @@ pub(crate) mod unexpected_cfg_name { after_value: Span, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_value, + "there is a config with a similar name and value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2367,7 +2722,7 @@ pub(crate) mod unexpected_cfg_name { code: String, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_no_value, + "there is a config with a similar name and no value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2377,7 +2732,7 @@ pub(crate) mod unexpected_cfg_name { code: String, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_different_values, + "there is a config with a similar name and different values", applicability = "maybe-incorrect", code = "{code}" )] @@ -2389,7 +2744,7 @@ pub(crate) mod unexpected_cfg_name { expected: Option, }, #[suggestion( - lint_unexpected_cfg_name_similar_name, + "there is a config with a similar name", applicability = "maybe-incorrect", code = "{code}" )] @@ -2407,7 +2762,7 @@ pub(crate) mod unexpected_cfg_name { expected_names: Option, }, #[suggestion( - lint_unexpected_cfg_boolean, + "you may have meant to use `{$literal}` (notice the capitalization). Doing so makes this predicate evaluate to `{$literal}` unconditionally", applicability = "machine-applicable", style = "verbose", code = "{literal}" @@ -2420,7 +2775,7 @@ pub(crate) mod unexpected_cfg_name { } #[derive(Subdiagnostic)] - #[help(lint_unexpected_cfg_name_expected_values)] + #[help("expected values for `{$best_match}` are: {$possibilities}")] pub(crate) struct ExpectedValues { pub best_match: Symbol, pub possibilities: DiagSymbolList, @@ -2428,7 +2783,7 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[suggestion( - lint_unexpected_cfg_name_with_similar_value, + "found config with similar value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2439,7 +2794,12 @@ pub(crate) mod unexpected_cfg_name { } #[derive(Subdiagnostic)] - #[help_once(lint_unexpected_cfg_name_expected_names)] + #[help_once( + "expected names are: {$possibilities}{$and_more -> + [0] {\"\"} + *[other] {\" \"}and {$and_more} more + }" + )] pub(crate) struct ExpectedNames { pub possibilities: DiagSymbolList, pub and_more: usize, @@ -2447,14 +2807,18 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] pub(crate) enum InvocationHelp { - #[note(lint_unexpected_cfg_doc_cargo)] + #[note( + "see for more information about checking conditional configuration" + )] Cargo { #[subdiagnostic] macro_help: Option, #[subdiagnostic] help: Option, }, - #[note(lint_unexpected_cfg_doc_rustc)] + #[note( + "see for more information about checking conditional configuration" + )] Rustc { #[subdiagnostic] macro_help: Option, @@ -2465,7 +2829,12 @@ pub(crate) mod unexpected_cfg_name { } #[derive(LintDiagnostic)] -#[diag(lint_unexpected_cfg_value)] +#[diag( + "unexpected `cfg` condition value: {$has_value -> + [true] `{$value}` + *[false] (none) + }" +)] pub(crate) struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, @@ -2489,14 +2858,14 @@ pub(crate) mod unexpected_cfg_value { #[subdiagnostic] suggestion: Option, }, - #[note(lint_unexpected_cfg_value_no_expected_value)] + #[note("no expected value for `{$name}`")] RemoveValue { #[subdiagnostic] suggestion: Option, name: Symbol, }, - #[note(lint_unexpected_cfg_value_no_expected_values)] + #[note("no expected values for `{$name}`")] RemoveCondition { #[subdiagnostic] suggestion: RemoveConditionSuggestion, @@ -2508,7 +2877,7 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum ChangeValueSuggestion { #[suggestion( - lint_unexpected_cfg_value_similar_name, + "there is a expected value with a similar name", code = r#""{best_match}""#, applicability = "maybe-incorrect" )] @@ -2518,7 +2887,7 @@ pub(crate) mod unexpected_cfg_value { best_match: Symbol, }, #[suggestion( - lint_unexpected_cfg_value_specify_value, + "specify a config value", code = r#" = "{first_possibility}""#, applicability = "maybe-incorrect" )] @@ -2530,29 +2899,29 @@ pub(crate) mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - #[suggestion( - lint_unexpected_cfg_value_remove_value, - code = "", - applicability = "maybe-incorrect" - )] + #[suggestion("remove the value", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveValueSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] - #[suggestion( - lint_unexpected_cfg_value_remove_condition, - code = "", - applicability = "maybe-incorrect" - )] + #[suggestion("remove the condition", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveConditionSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] - #[note(lint_unexpected_cfg_value_expected_values)] + #[note( + "expected values for `{$name}` are: {$have_none_possibility -> + [true] {\"(none), \"} + *[false] {\"\"} + }{$possibilities}{$and_more -> + [0] {\"\"} + *[other] {\" \"}and {$and_more} more + }" + )] pub(crate) struct ExpectedValues { pub name: Symbol, pub have_none_possibility: bool, @@ -2562,14 +2931,18 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum InvocationHelp { - #[note(lint_unexpected_cfg_doc_cargo)] + #[note( + "see for more information about checking conditional configuration" + )] Cargo { #[subdiagnostic] help: Option, #[subdiagnostic] macro_help: Option, }, - #[note(lint_unexpected_cfg_doc_rustc)] + #[note( + "see for more information about checking conditional configuration" + )] Rustc { #[subdiagnostic] help: Option, @@ -2580,19 +2953,19 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum CargoHelp { - #[help(lint_unexpected_cfg_value_add_feature)] + #[help("consider adding `{$value}` as a feature in `Cargo.toml`")] AddFeature { value: Symbol, }, - #[help(lint_unexpected_cfg_define_features)] + #[help("consider defining some features in `Cargo.toml`")] DefineFeatures, Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp), } } #[derive(LintDiagnostic)] -#[diag(lint_unused_crate_dependency)] -#[help] +#[diag("extern crate `{$extern_crate}` is unused in crate `{$local_crate}`")] +#[help("remove the dependency or add `use {$extern_crate} as _;` to the crate root")] pub(crate) struct UnusedCrateDependency { pub extern_crate: Symbol, pub local_crate: Symbol, @@ -2600,20 +2973,32 @@ pub(crate) struct UnusedCrateDependency { // FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely. #[derive(LintDiagnostic)] -#[diag(lint_ill_formed_attribute_input)] +#[diag( + "{$num_suggestions -> + [1] attribute must be of the form {$suggestions} + *[other] valid forms for the attribute are {$suggestions} + }" +)] pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, pub suggestions: DiagArgValue, - #[note] + #[note("for more information, visit <{$docs}>")] pub has_docs: bool, pub docs: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_unicode_text_flow)] -#[note] +#[diag("unicode codepoint changing visible direction of text present in comment")] +#[note( + "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen" +)] pub(crate) struct UnicodeTextFlow { - #[label] + #[label( + "{$num_codepoints -> + [1] this comment contains an invisible unicode text flow control codepoint + *[other] this comment contains invisible unicode text flow control codepoints + }" + )] pub comment_span: Span, #[subdiagnostic] pub characters: Vec, @@ -2624,7 +3009,7 @@ pub(crate) struct UnicodeTextFlow { } #[derive(Subdiagnostic)] -#[label(lint_label_comment_char)] +#[label("{$c_debug}")] pub(crate) struct UnicodeCharNoteSub { #[primary_span] pub span: Span, @@ -2632,21 +3017,27 @@ pub(crate) struct UnicodeCharNoteSub { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] +#[multipart_suggestion( + "if their presence wasn't intentional, you can remove them", + applicability = "machine-applicable", + style = "hidden" +)] pub(crate) struct UnicodeTextFlowSuggestion { #[suggestion_part(code = "")] pub spans: Vec, } #[derive(LintDiagnostic)] -#[diag(lint_abs_path_with_module)] +#[diag( + "absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition" +)] pub(crate) struct AbsPathWithModule { #[subdiagnostic] pub sugg: AbsPathWithModuleSugg, } #[derive(Subdiagnostic)] -#[suggestion(lint_suggestion, code = "{replacement}")] +#[suggestion("use `crate`", code = "{replacement}")] pub(crate) struct AbsPathWithModuleSugg { #[primary_span] pub span: Span, @@ -2656,18 +3047,23 @@ pub(crate) struct AbsPathWithModuleSugg { } #[derive(LintDiagnostic)] -#[diag(lint_hidden_lifetime_parameters)] +#[diag("hidden lifetime parameters in types are deprecated")] pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: ElidedLifetimeInPathSubdiag, } #[derive(LintDiagnostic)] -#[diag(lint_unused_imports)] +#[diag( + "{$num_snippets -> + [one] unused import: {$span_snippets} + *[other] unused imports: {$span_snippets} + }" +)] pub(crate) struct UnusedImports { #[subdiagnostic] pub sugg: UnusedImportsSugg, - #[help] + #[help("if this is a test module, consider adding a `#[cfg(test)]` to the containing module")] pub test_module_span: Option, pub span_snippets: DiagArgValue, @@ -2677,7 +3073,7 @@ pub(crate) struct UnusedImports { #[derive(Subdiagnostic)] pub(crate) enum UnusedImportsSugg { #[suggestion( - lint_suggestion_remove_whole_use, + "remove the whole `use` item", applicability = "machine-applicable", code = "", style = "tool-only" @@ -2687,7 +3083,10 @@ pub(crate) enum UnusedImportsSugg { span: Span, }, #[multipart_suggestion( - lint_suggestion_remove_imports, + "{$num_to_remove -> + [one] remove the unused import + *[other] remove the unused imports + }", applicability = "machine-applicable", style = "tool-only" )] @@ -2699,7 +3098,7 @@ pub(crate) enum UnusedImportsSugg { } #[derive(LintDiagnostic)] -#[diag(lint_redundant_import)] +#[diag("the item `{$ident}` is imported redundantly")] pub(crate) struct RedundantImport { #[subdiagnostic] pub subs: Vec, @@ -2709,24 +3108,24 @@ pub(crate) struct RedundantImport { #[derive(Subdiagnostic)] pub(crate) enum RedundantImportSub { - #[label(lint_label_imported_here)] + #[label("the item `{$ident}` is already imported here")] ImportedHere(#[primary_span] Span), - #[label(lint_label_defined_here)] + #[label("the item `{$ident}` is already defined here")] DefinedHere(#[primary_span] Span), - #[label(lint_label_imported_prelude)] + #[label("the item `{$ident}` is already imported by the extern prelude")] ImportedPrelude(#[primary_span] Span), - #[label(lint_label_defined_prelude)] + #[label("the item `{$ident}` is already defined by the extern prelude")] DefinedPrelude(#[primary_span] Span), } #[derive(LintDiagnostic)] pub(crate) enum PatternsInFnsWithoutBody { - #[diag(lint_pattern_in_foreign)] + #[diag("patterns aren't allowed in foreign function declarations")] Foreign { #[subdiagnostic] sub: PatternsInFnsWithoutBodySub, }, - #[diag(lint_pattern_in_bodiless)] + #[diag("patterns aren't allowed in functions without bodies")] Bodiless { #[subdiagnostic] sub: PatternsInFnsWithoutBodySub, @@ -2734,7 +3133,11 @@ pub(crate) enum PatternsInFnsWithoutBody { } #[derive(Subdiagnostic)] -#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] +#[suggestion( + "remove `mut` from the parameter", + code = "{ident}", + applicability = "machine-applicable" +)] pub(crate) struct PatternsInFnsWithoutBodySub { #[primary_span] pub span: Span, @@ -2743,34 +3146,44 @@ pub(crate) struct PatternsInFnsWithoutBodySub { } #[derive(LintDiagnostic)] -#[diag(lint_reserved_prefix)] +#[diag("prefix `{$prefix}` is unknown")] pub(crate) struct ReservedPrefix { - #[label] + #[label("unknown prefix")] pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: String, } #[derive(LintDiagnostic)] -#[diag(lint_raw_prefix)] +#[diag("prefix `'r` is reserved")] pub(crate) struct RawPrefix { - #[label] + #[label("reserved prefix")] pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_break_with_label_and_loop)] +#[diag( + "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression" +)] pub(crate) struct BreakWithLabelAndLoop { #[subdiagnostic] pub sub: BreakWithLabelAndLoopSub, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("wrap this expression in parentheses", applicability = "machine-applicable")] pub(crate) struct BreakWithLabelAndLoopSub { #[suggestion_part(code = "(")] pub left: Span, @@ -2779,8 +3192,8 @@ pub(crate) struct BreakWithLabelAndLoopSub { } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_where_clause_location)] -#[note] +#[diag("where clause not allowed here")] +#[note("see issue #89122 for more information")] pub(crate) struct DeprecatedWhereClauseLocation { #[subdiagnostic] pub suggestion: DeprecatedWhereClauseLocationSugg, @@ -2788,7 +3201,10 @@ pub(crate) struct DeprecatedWhereClauseLocation { #[derive(Subdiagnostic)] pub(crate) enum DeprecatedWhereClauseLocationSugg { - #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] + #[multipart_suggestion( + "move it to the end of the type declaration", + applicability = "machine-applicable" + )] MoveToEnd { #[suggestion_part(code = "")] left: Span, @@ -2797,7 +3213,7 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { sugg: String, }, - #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")] + #[suggestion("remove this `where`", code = "", applicability = "machine-applicable")] RemoveWhere { #[primary_span] span: Span, @@ -2805,11 +3221,11 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { } #[derive(LintDiagnostic)] -#[diag(lint_single_use_lifetime)] +#[diag("lifetime parameter `{$ident}` only used once")] pub(crate) struct SingleUseLifetime { - #[label(lint_label_param)] + #[label("this lifetime...")] pub param_span: Span, - #[label(lint_label_use)] + #[label("...is used only here")] pub use_span: Span, #[subdiagnostic] pub suggestion: Option, @@ -2818,7 +3234,7 @@ pub(crate) struct SingleUseLifetime { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("elide the single-use lifetime", applicability = "machine-applicable")] pub(crate) struct SingleUseLifetimeSugg { #[suggestion_part(code = "")] pub deletion_span: Option, @@ -2829,22 +3245,27 @@ pub(crate) struct SingleUseLifetimeSugg { } #[derive(LintDiagnostic)] -#[diag(lint_unused_lifetime)] +#[diag("lifetime parameter `{$ident}` never used")] pub(crate) struct UnusedLifetime { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("elide the unused lifetime", code = "", applicability = "machine-applicable")] pub deletion_span: Option, pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(lint_named_argument_used_positionally)] +#[diag("named argument `{$named_arg_name}` is not used by name")] pub(crate) struct NamedArgumentUsedPositionally { - #[label(lint_label_named_arg)] + #[label("this named argument is referred to by position in formatting string")] pub named_arg_sp: Span, - #[label(lint_label_position_arg)] + #[label("this formatting argument uses named argument `{$named_arg_name}` by position")] pub position_label_sp: Option, - #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")] + #[suggestion( + "use the named argument by name to avoid ambiguity", + style = "verbose", + code = "{name}", + applicability = "maybe-incorrect" + )] pub suggestion: Option, pub name: String, @@ -2852,11 +3273,11 @@ pub(crate) struct NamedArgumentUsedPositionally { } #[derive(LintDiagnostic)] -#[diag(lint_ambiguous_glob_reexport)] +#[diag("ambiguous glob re-exports")] pub(crate) struct AmbiguousGlobReexports { - #[label(lint_label_first_reexport)] + #[label("the name `{$name}` in the {$namespace} namespace is first re-exported here")] pub first_reexport: Span, - #[label(lint_label_duplicate_reexport)] + #[label("but the name `{$name}` in the {$namespace} namespace is also re-exported here")] pub duplicate_reexport: Span, pub name: String, @@ -2864,11 +3285,13 @@ pub(crate) struct AmbiguousGlobReexports { } #[derive(LintDiagnostic)] -#[diag(lint_hidden_glob_reexport)] +#[diag("private item shadows public glob re-export")] pub(crate) struct HiddenGlobReexports { - #[note(lint_note_glob_reexport)] + #[note( + "the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here" + )] pub glob_reexport: Span, - #[note(lint_note_private_item)] + #[note("but the private item here shadows it")] pub private_item: Span, pub name: String, @@ -2876,47 +3299,70 @@ pub(crate) struct HiddenGlobReexports { } #[derive(LintDiagnostic)] -#[diag(lint_unnecessary_qualification)] +#[diag("unnecessary qualification")] pub(crate) struct UnusedQualifications { - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove the unnecessary path segments", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub removal_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_associated_const_elided_lifetime)] +#[diag( + "{$elided -> + [true] `&` without an explicit lifetime name cannot be used here + *[false] `'_` cannot be used here + }" +)] pub(crate) struct AssociatedConstElidedLifetime { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + #[suggestion( + "use the `'static` lifetime", + style = "verbose", + code = "{code}", + applicability = "machine-applicable" + )] pub span: Span, pub code: &'static str, pub elided: bool, - #[note] + #[note("cannot automatically infer `'static` because of other lifetimes in scope")] pub lifetimes_in_scope: MultiSpan, } #[derive(LintDiagnostic)] -#[diag(lint_static_mut_refs_lint)] +#[diag("creating a {$shared_label}reference to mutable static")] pub(crate) struct RefOfMutStatic<'a> { - #[label] + #[label("{$shared_label}reference to mutable static")] pub span: Span, #[subdiagnostic] pub sugg: Option, pub shared_label: &'a str, - #[note(lint_shared_note)] + #[note( + "shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives" + )] pub shared_note: bool, - #[note(lint_mut_note)] + #[note( + "mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives" + )] pub mut_note: bool, } #[derive(Subdiagnostic)] pub(crate) enum MutRefSugg { - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `&raw const` instead to create a raw pointer", + style = "verbose", + applicability = "maybe-incorrect" + )] Shared { #[suggestion_part(code = "&raw const ")] span: Span, }, #[multipart_suggestion( - lint_suggestion_mut, + "use `&raw mut` instead to create a raw pointer", style = "verbose", applicability = "maybe-incorrect" )] @@ -2927,25 +3373,33 @@ pub(crate) enum MutRefSugg { } #[derive(LintDiagnostic)] -#[diag(lint_unqualified_local_imports)] +#[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] pub(crate) struct UnqualifiedLocalImportsDiag {} #[derive(LintDiagnostic)] -#[diag(lint_reserved_string)] +#[diag("will be parsed as a guarded string in Rust 2024")] pub(crate) struct ReservedString { - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a guarded string in Rust 2024", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_reserved_multihash)] +#[diag("reserved token in Rust 2024")] pub(crate) struct ReservedMultihash { - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_function_casts_as_integer)] +#[diag("direct cast of function item into an integer")] pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { #[subdiagnostic] pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>, @@ -2953,7 +3407,7 @@ pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - lint_cast_as_fn, + "first cast to a pointer `as *const ()`", code = " as *const ()", applicability = "machine-applicable", style = "verbose" @@ -2981,44 +3435,46 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta } LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_while_elided + msg!("hiding a lifetime that's elided elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_while_named + msg!("hiding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_eliding_while_named + msg!("eliding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named + msg!("hiding or eliding a lifetime that's named elsewhere is confusing") } }; diag.primary_message(message); for s in self.inputs.hidden { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_hidden); + diag.span_label(s, msg!("the lifetime is hidden here")); } for s in self.inputs.elided { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_elided); + diag.span_label(s, msg!("the lifetime is elided here")); } for s in self.inputs.named { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_named); + diag.span_label(s, msg!("the lifetime is named here")); } for s in self.outputs.hidden { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_hidden); + diag.span_label(s, msg!("the same lifetime is hidden here")); } for s in self.outputs.elided { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_elided); + diag.span_label(s, msg!("the same lifetime is elided here")); } for s in self.outputs.named { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_named); + diag.span_label(s, msg!("the same lifetime is named here")); } - diag.help(fluent::lint_mismatched_lifetime_syntaxes_help); + diag.help(msg!( + "the same lifetime is referred to in inconsistent ways, making the signature confusing" + )); let mut suggestions = self.suggestions.into_iter(); if let Some(s) = suggestions.next() { @@ -3092,7 +3548,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { Implicit { suggestions, optional_alternative } => { let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); diag.multipart_suggestion_with_style( - fluent::lint_mismatched_lifetime_syntaxes_suggestion_implicit, + msg!("remove the lifetime name from references"), suggestions, applicability(optional_alternative), style(optional_alternative), @@ -3105,9 +3561,9 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { optional_alternative, } => { let message = if implicit_suggestions.is_empty() { - fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths + msg!("use `'_` for type paths") } else { - fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed + msg!("remove the lifetime name from references and use `'_` for type paths") }; let implicit_suggestions = @@ -3126,9 +3582,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { Explicit { lifetime_name, suggestions, optional_alternative } => { diag.arg("lifetime_name", lifetime_name); - let msg = diag.eagerly_translate( - fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit, - ); + let msg = diag.eagerly_translate(msg!("consistently use `{$lifetime_name}`")); diag.remove_arg("lifetime_name"); diag.multipart_suggestion_with_style( msg, @@ -3142,63 +3596,107 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_empty_attribute)] -#[note] +#[diag("unused attribute")] +#[note( + "{$valid_without_list -> + [true] using `{$attr_path}` with an empty list is equivalent to not using a list at all + *[other] using `{$attr_path}` with an empty list has no effect + }" +)] pub(crate) struct EmptyAttributeList { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "{$valid_without_list -> + [true] remove these parentheses + *[other] remove this attribute + }", + code = "", + applicability = "machine-applicable" + )] pub attr_span: Span, pub attr_path: String, pub valid_without_list: bool, } #[derive(LintDiagnostic)] -#[diag(lint_invalid_target)] -#[warning] -#[help] +#[diag("`#[{$name}]` attribute cannot be used on {$target}")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +#[help("`#[{$name}]` can {$only}be applied to {$applied}")] pub(crate) struct InvalidTargetLint { pub name: String, pub target: &'static str, pub applied: DiagArgValue, pub only: &'static str, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_invalid_style)] +#[diag( + "{$is_used_as_inner -> + [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]` + *[other] the `#![{$name}]` attribute can only be used at the crate root + }" +)] pub(crate) struct InvalidAttrStyle { pub name: String, pub is_used_as_inner: bool, - #[note] + #[note("this attribute does not have an `!`, which means it is applied to this {$target}")] pub target_span: Option, pub target: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_unused_duplicate)] +#[diag("unused attribute")] pub(crate) struct UnusedDuplicate { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, - #[warning] + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] pub warning: bool, } #[derive(LintDiagnostic)] -#[diag(lint_unsafe_attr_outside_unsafe)] +#[diag("malformed `doc` attribute input")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +pub(crate) struct MalformedDoc; + +#[derive(LintDiagnostic)] +#[diag("didn't expect any arguments here")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +pub(crate) struct ExpectedNoArgs; + +#[derive(LintDiagnostic)] +#[diag("expected this to be of the form `... = \"...\"`")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +pub(crate) struct ExpectedNameValue; + +#[derive(LintDiagnostic)] +#[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafeLint { - #[label] + #[label("usage of unsafe attribute")] pub span: Span, #[subdiagnostic] pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - lint_unsafe_attr_outside_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -3207,121 +3705,161 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_visibilities)] -#[note] +#[diag("visibility qualifiers have no effect on `const _` declarations")] +#[note("`const _` does not declare a name, so there is nothing for the qualifier to apply to")] pub(crate) struct UnusedVisibility { - #[suggestion(style = "short", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove the qualifier", + style = "short", + code = "", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_alias_duplicated)] +#[diag("doc alias is duplicated")] pub(crate) struct DocAliasDuplicated { - #[label] + #[label("first defined here")] pub first_defn: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_expects_hide_or_show)] +#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")] pub(crate) struct DocAutoCfgExpectsHideOrShow; #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_hide_show_unexpected_item)] +#[diag("there exists a built-in attribute with the same name")] +pub(crate) struct AmbiguousDeriveHelpers; + +#[derive(LintDiagnostic)] +#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items")] pub(crate) struct DocAutoCfgHideShowUnexpectedItem { pub attr_name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_hide_show_expects_list)] +#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items")] pub(crate) struct DocAutoCfgHideShowExpectsList { pub attr_name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_invalid)] +#[diag("invalid `doc` attribute")] pub(crate) struct DocInvalid; #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_include)] +#[diag("unknown `doc` attribute `include`")] pub(crate) struct DocUnknownInclude { pub inner: &'static str, pub value: Symbol, - #[suggestion(code = "#{inner}[doc = include_str!(\"{value}\")]")] + #[suggestion( + "use `doc = include_str!` instead", + code = "#{inner}[doc = include_str!(\"{value}\")]" + )] pub sugg: (Span, Applicability), } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_spotlight)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `spotlight`")] +#[note("`doc(spotlight)` was renamed to `doc(notable_trait)`")] +#[note("`doc(spotlight)` is now a no-op")] pub(crate) struct DocUnknownSpotlight { - #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")] + #[suggestion( + "use `notable_trait` instead", + style = "short", + applicability = "machine-applicable", + code = "notable_trait" + )] pub sugg_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_passes)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `{$name}`")] +#[note( + "`doc` attribute `{$name}` no longer functions; see issue #44136 " +)] +#[note("`doc({$name})` is now a no-op")] pub(crate) struct DocUnknownPasses { pub name: Symbol, - #[label] + #[label("no longer functions")] pub note_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_plugins)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `plugins`")] +#[note( + "`doc` attribute `plugins` no longer functions; see issue #44136 and CVE-2018-1000622 " +)] +#[note("`doc(plugins)` is now a no-op")] pub(crate) struct DocUnknownPlugins { - #[label] + #[label("no longer functions")] pub label_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_any)] +#[diag("unknown `doc` attribute `{$name}`")] pub(crate) struct DocUnknownAny { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_wrong_literal)] +#[diag("expected boolean for `#[doc(auto_cfg = ...)]`")] pub(crate) struct DocAutoCfgWrongLiteral; #[derive(LintDiagnostic)] -#[diag(lint_doc_test_takes_list)] +#[diag("`#[doc(test(...)]` takes a list of attributes")] pub(crate) struct DocTestTakesList; #[derive(LintDiagnostic)] -#[diag(lint_doc_test_unknown)] +#[diag("unknown `doc(test)` attribute `{$name}`")] pub(crate) struct DocTestUnknown { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_test_literal)] +#[diag("`#![doc(test(...)]` does not take a literal")] pub(crate) struct DocTestLiteral; #[derive(LintDiagnostic)] -#[diag(lint_attr_crate_level)] -#[note] +#[diag("this attribute can only be applied at the crate level")] +#[note( + "read for more information" +)] pub(crate) struct AttrCrateLevelOnly; #[derive(LintDiagnostic)] -#[diag(lint_incorrect_do_not_recommend_args)] +#[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; #[derive(LintDiagnostic)] -#[diag(lint_invalid_crate_type_value)] +#[diag("invalid `crate_type` value")] pub(crate) struct UnknownCrateTypes { #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[suggestion(lint_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")] +#[suggestion("did you mean", code = r#""{snippet}""#, applicability = "maybe-incorrect")] pub(crate) struct UnknownCrateTypesSuggestion { #[primary_span] pub span: Span, pub snippet: Symbol, } + +#[derive(LintDiagnostic)] +#[diag("unreachable configuration predicate")] +pub(crate) struct UnreachableCfgSelectPredicate { + #[label("this configuration predicate is never reached")] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag("unreachable configuration predicate")] +pub(crate) struct UnreachableCfgSelectPredicateWildcard { + #[label("this configuration predicate is never reached")] + pub span: Span, + + #[label("always matches")] + pub wildcard_span: Span, +} diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index a07c3b372d34..bb04da96140a 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,5 +1,5 @@ use rustc_ast as ast; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, msg}; use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::{bug, ty}; @@ -10,7 +10,7 @@ use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym}; use rustc_trait_selection::infer::InferCtxtExt; use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first @@ -121,20 +121,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc } cx.span_lint(NON_FMT_PANICS, arg_span, |lint| { - lint.primary_message(fluent::lint_non_fmt_panic); + lint.primary_message(msg!("panic message is not a string literal")); lint.arg("name", symbol); - lint.note(fluent::lint_note); - lint.note(fluent::lint_more_info_note); + lint.note(msg!("this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021")); + lint.note(msg!("for more information, see ")); if !is_arg_inside_call(arg_span, span) { // No clue where this argument is coming from. return; } if arg_macro.is_some_and(|id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) { // A case of `panic!(format!(..))`. - lint.note(fluent::lint_supports_fmt_note); + lint.note(msg!("the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here")); if let Some((open, close, _)) = find_delimiters(cx, arg_span) { lint.multipart_suggestion( - fluent::lint_supports_fmt_suggestion, + msg!("remove the `format!(..)` macro call"), vec![ (arg_span.until(open.shrink_to_hi()), "".into()), (close.until(arg_span.shrink_to_hi()), "".into()), @@ -178,7 +178,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_display { lint.span_suggestion_verbose( arg_span.shrink_to_lo(), - fluent::lint_display_suggestion, + msg!(r#"add a "{"{"}{"}"}" format string to `Display` the message"#), "\"{}\", ", fmt_applicability, ); @@ -186,7 +186,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc lint.arg("ty", ty); lint.span_suggestion_verbose( arg_span.shrink_to_lo(), - fluent::lint_debug_suggestion, + msg!(r#"add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`"#), "\"{:?}\", ", fmt_applicability, ); @@ -196,7 +196,12 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if let Some((open, close, del)) = find_delimiters(cx, span) { lint.arg("already_suggested", suggest_display || suggest_debug); lint.multipart_suggestion( - fluent::lint_panic_suggestion, + msg!( + "{$already_suggested -> + [true] or use + *[false] use + } std::panic::panic_any instead" + ), if del == '(' { vec![(span.until(open), "std::panic::panic_any".into())] } else { diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index bcf4d9ec3b29..8fb6532e68c4 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,4 +1,4 @@ -use rustc_errors::MultiSpan; +use rustc_errors::{MultiSpan, msg}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; @@ -9,7 +9,7 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{ExpnKind, Span, kw}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `non_local_definitions` lint checks for `impl` blocks and `#[macro_export]` @@ -210,7 +210,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { if !doctest { ms.push_span_label( cx.tcx.def_span(parent), - fluent::lint_non_local_definitions_impl_move_help, + msg!( + "move the `impl` block outside of this {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }" + ), ); } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 24682c4562a0..66b4e3c16e93 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,7 +1,7 @@ use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; @@ -114,7 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { // If there is any user defined auto-deref step, then we don't want to warn. // https://github.com/rust-lang/rust-clippy/issues/9272 - if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) { + if arg_adjustments + .iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))) + { return; } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 3f2ca92a021a..b5b57eaa3389 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -202,11 +202,11 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } #[derive(LintDiagnostic)] -#[diag(lint_opaque_hidden_inferred_bound)] +#[diag("opaque type `{$ty}` does not satisfy its associated type bounds")] struct OpaqueHiddenInferredBoundLint<'tcx> { ty: Ty<'tcx>, proj_ty: Ty<'tcx>, - #[label(lint_specifically)] + #[label("this associated type bound is unsatisfied for `{$proj_ty}`")] assoc_pred_span: Span, #[subdiagnostic] add_bound: Option>, @@ -214,7 +214,7 @@ struct OpaqueHiddenInferredBoundLint<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - lint_opaque_hidden_inferred_bound_sugg, + "add this bound", style = "verbose", applicability = "machine-applicable", code = " + {trait_ref}" diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index f4a506d50a41..3823c9aa1861 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -44,7 +44,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option + if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::RustcPassByValue(_)) => { let name = cx.tcx.item_ident(def_id); let path_segment = path.segments.last().unwrap(); @@ -52,7 +52,10 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option { if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() { - if find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::PassByValue(_)) { + if find_attr!( + cx.tcx.get_all_attrs(adt.did()), + AttributeKind::RustcPassByValue(_) + ) { return Some(cx.tcx.def_path_str_with_args(adt.did(), args)); } } diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 6bc4617eb2dc..e4716c869c5f 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -369,8 +369,10 @@ fn check_unnecessary_transmute<'tcx>( } #[derive(LintDiagnostic)] -#[diag(lint_undefined_transmute)] -#[note] -#[note(lint_note2)] -#[help] +#[diag("pointers cannot be transmuted to integers during const eval")] +#[note("at compile-time, pointers do not have an integer value")] +#[note( + "avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior" +)] +#[help("for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html")] pub(crate) struct UndefinedTransmuteLint; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f3e6db6f2d8e..47e1fef8b82e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -746,24 +746,23 @@ fn pat_ty_is_known_nonnull<'tcx>( typing_env: ty::TypingEnv<'tcx>, pat: ty::Pattern<'tcx>, ) -> bool { - Option::unwrap_or_default( - try { - match *pat { - ty::PatternKind::Range { start, end } => { - let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?; - let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?; + try { + match *pat { + ty::PatternKind::Range { start, end } => { + let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?; + let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?; - // This also works for negative numbers, as we just need - // to ensure we aren't wrapping over zero. - start > 0 && end >= start - } - ty::PatternKind::NotNull => true, - ty::PatternKind::Or(patterns) => { - patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) - } + // This also works for negative numbers, as we just need + // to ensure we aren't wrapping over zero. + start > 0 && end >= start } - }, - ) + ty::PatternKind::NotNull => true, + ty::PatternKind::Or(patterns) => { + patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) + } + } + } + .unwrap_or_default() } /// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type. diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 38094c67c34a..9f10cba64cd4 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use bitflags::bitflags; use rustc_abi::VariantIdx; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::DiagMessage; +use rustc_errors::{DiagMessage, msg}; use rustc_hir::def::CtorKind; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg}; @@ -21,7 +21,7 @@ use tracing::debug; use super::repr_nullable_ptr; use crate::lints::{ImproperCTypes, UsesPowerAlignment}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `improper_ctypes` lint detects incorrect use of types in foreign @@ -158,12 +158,12 @@ pub(crate) fn check_non_exhaustive_variant( // with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }` // but exempt enums with unit ctors like C's (e.g. from rust-bindgen) if variant_has_complex_ctor(variant) { - return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive); + return ControlFlow::Break(msg!("this enum is non-exhaustive")); } } if variant.field_list_has_applicable_non_exhaustive() { - return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant); + return ControlFlow::Break(msg!("this enum has non-exhaustive variants")); } ControlFlow::Continue(()) @@ -424,7 +424,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if all_phantom { FfiPhantom(ty) } else if transparent_with_all_zst_fields { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None } + FfiUnsafe { + ty, + reason: msg!("this struct contains only zero-sized fields"), + help: None, + } } else { FfiSafe } @@ -460,7 +464,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_box, + reason: msg!("box cannot be represented as a single pointer"), help: None, }; } @@ -476,8 +480,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_cstr_reason, - help: Some(fluent::lint_improper_ctypes_cstr_help), + reason: msg!("`CStr`/`CString` do not have a guaranteed layout"), + help: Some(msg!( + "consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`" + )), }; } @@ -485,14 +491,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_layout_reason + msg!("this struct has unspecified layout") } else { - fluent::lint_improper_ctypes_union_layout_reason + msg!("this union has unspecified layout") }, help: if def.is_struct() { - Some(fluent::lint_improper_ctypes_struct_layout_help) + Some(msg!( + "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct" + )) } else { - Some(fluent::lint_improper_ctypes_union_layout_help) + Some(msg!( + "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union" + )) }, }; } @@ -501,9 +511,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_non_exhaustive + msg!("this struct is non-exhaustive") } else { - fluent::lint_improper_ctypes_union_non_exhaustive + msg!("this union is non-exhaustive") }, help: None, }; @@ -513,14 +523,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_fieldless_reason + msg!("this struct has no fields") } else { - fluent::lint_improper_ctypes_union_fieldless_reason + msg!("this union has no fields") }, help: if def.is_struct() { - Some(fluent::lint_improper_ctypes_struct_fieldless_help) + Some(msg!("consider adding a member to this struct")) } else { - Some(fluent::lint_improper_ctypes_union_fieldless_help) + Some(msg!("consider adding a member to this union")) }, }; } @@ -545,8 +555,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_enum_repr_reason, - help: Some(fluent::lint_improper_ctypes_enum_repr_help), + reason: msg!("enum has no representation hint"), + help: Some(msg!( + "consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum" + )), }; } @@ -572,8 +584,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Char => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_char_reason, - help: Some(fluent::lint_improper_ctypes_char_help), + reason: msg!("the `char` type has no C equivalent"), + help: Some(msg!("consider using `u32` or `libc::wchar_t` instead")), }, // It's just extra invariants on the type that you need to uphold, @@ -585,24 +597,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Slice(_) => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_slice_reason, - help: Some(fluent::lint_improper_ctypes_slice_help), + reason: msg!("slices have no C equivalent"), + help: Some(msg!("consider using a raw pointer instead")), }, ty::Dynamic(..) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_dyn, help: None } + FfiUnsafe { ty, reason: msg!("trait objects have no C equivalent"), help: None } } ty::Str => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_str_reason, - help: Some(fluent::lint_improper_ctypes_str_help), + reason: msg!("string slices have no C equivalent"), + help: Some(msg!("consider using `*const u8` and a length instead")), }, ty::Tuple(..) => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_tuple_reason, - help: Some(fluent::lint_improper_ctypes_tuple_help), + reason: msg!("tuples have unspecified layout"), + help: Some(msg!("consider using a struct instead")), }, ty::RawPtr(ty, _) | ty::Ref(_, ty, _) @@ -632,8 +644,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if sig.abi().is_rustic_abi() { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_fnptr_reason, - help: Some(fluent::lint_improper_ctypes_fnptr_help), + reason: msg!("this function pointer has Rust-specific calling convention"), + help: Some(msg!( + "consider using an `extern fn(...) -> ...` function pointer instead" + )), }; } @@ -658,7 +672,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // While opaque types are checked for earlier, if a projection in a struct field // normalizes to an opaque type, then it will reach this branch. ty::Alias(ty::Opaque, ..) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None } + FfiUnsafe { ty, reason: msg!("opaque types have no C equivalent"), help: None } } // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe, @@ -669,9 +683,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::UnsafeBinder(_) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_unsafe_binder, help: None } - } + ty::UnsafeBinder(_) => FfiUnsafe { + ty, + reason: msg!("unsafe binders are incompatible with foreign function interfaces"), + help: None, + }, ty::Param(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..) @@ -715,7 +731,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { Some(FfiResult::FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_opaque, + reason: msg!("opaque types have no C equivalent"), help: None, }) } else { @@ -728,8 +744,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let ty::Array(..) = ty.kind() { Some(FfiResult::FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_array_reason, - help: Some(fluent::lint_improper_ctypes_array_help), + reason: msg!("passing raw arrays by value is not FFI-safe"), + help: Some(msg!("consider passing a pointer to the array")), }) } else { None @@ -908,7 +924,7 @@ impl<'tcx> ImproperCTypesLint { cx, ty, sp, - fluent::lint_improper_ctypes_only_phantomdata, + msg!("composed only of `PhantomData`"), None, fn_mode, ); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 506a16355e22..8b2a6d1d2ab5 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -539,10 +539,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { - let span = span.find_ancestor_not_from_macro().unwrap_or(*span); + let ancenstor_span = span.find_ancestor_not_from_macro().unwrap_or(*span); + let is_redundant_let_ignore = cx + .sess() + .source_map() + .span_to_prev_source(ancenstor_span) + .ok() + .map(|prev| prev.trim_end().ends_with("let _ =")) + .unwrap_or(false); + let suggestion_span = + if is_redundant_let_ignore { *span } else { ancenstor_span }; cx.emit_span_lint( UNUSED_MUST_USE, - span, + ancenstor_span, UnusedDef { pre: descr_pre, post: descr_post, @@ -551,11 +560,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { note: *reason, suggestion: (!is_inner).then_some(if expr_is_from_block { UnusedDefSuggestion::BlockTailExpr { - before_span: span.shrink_to_lo(), - after_span: span.shrink_to_hi(), + before_span: suggestion_span.shrink_to_lo(), + after_span: suggestion_span.shrink_to_hi(), } } else { - UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() } + UnusedDefSuggestion::NormalExpr { + span: suggestion_span.shrink_to_lo(), + } }), }, ); @@ -794,7 +805,10 @@ trait UnusedDelimLint { ExprKind::Break(_label, None) => return false, ExprKind::Break(_label, Some(break_expr)) => { - return matches!(break_expr.kind, ExprKind::Block(..)); + // `if (break 'label i) { ... }` removing parens would make `i { ... }` + // be parsed as a struct literal, so keep parentheses if the break value + // ends with a path (which could be mistaken for a struct name). + return matches!(break_expr.kind, ExprKind::Block(..) | ExprKind::Path(..)); } ExprKind::Range(_lhs, Some(rhs), _limits) => { @@ -1044,8 +1058,8 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - let expr = if let Const(box ast::ConstItem { rhs: Some(rhs), .. }) = &item.kind { - rhs.expr() + let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind { + if let Some(e) = rhs_kind.expr() { e } else { return } } else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind { expr } else { @@ -1771,7 +1785,7 @@ declare_lint! { declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]); impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { - fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &hir::Expr<'_>) { match e.kind { hir::ExprKind::Call(path_expr, [_]) if let hir::ExprKind::Path(qpath) = &path_expr.kind @@ -1782,6 +1796,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { for adj in cx.typeck_results().expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind { + if let ty::Ref(_, inner_ty, _) = adj.target.kind() + && inner_ty.is_box() + { + // If the target type is `&Box` or `&mut Box`, the allocation is necessary + continue; + } match m { adjustment::AutoBorrowMutability::Not => { cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ff108031badc..9e80ddbd551f 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -17,9 +17,11 @@ declare_lint_pass! { AARCH64_SOFTFLOAT_NEON, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_ASSOCIATED_ITEMS, + AMBIGUOUS_DERIVE_HELPERS, AMBIGUOUS_GLOB_IMPORTED_TRAITS, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_GLOB_REEXPORTS, + AMBIGUOUS_IMPORT_VISIBILITIES, AMBIGUOUS_PANIC_IMPORTS, ARITHMETIC_OVERFLOW, ASM_SUB_REGISTER, @@ -122,6 +124,7 @@ declare_lint_pass! { UNKNOWN_LINTS, UNNAMEABLE_TEST_ITEMS, UNNAMEABLE_TYPES, + UNREACHABLE_CFG_SELECT_PREDICATES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, UNSAFE_ATTR_OUTSIDE_UNSAFE, @@ -854,6 +857,34 @@ declare_lint! { "detects unreachable patterns" } +declare_lint! { + /// The `unreachable_cfg_select_predicates` lint detects unreachable configuration + /// predicates in the `cfg_select!` macro. + /// + /// ### Example + /// + /// ```rust + /// #![feature(cfg_select)] + /// cfg_select! { + /// _ => (), + /// windows => (), + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This usually indicates a mistake in how the predicates are specified or + /// ordered. In this example, the `_` predicate will always match, so the + /// `windows` is impossible to reach. Remember, arms match in order, you + /// probably wanted to put the `windows` case above the `_` case. + pub UNREACHABLE_CFG_SELECT_PREDICATES, + Warn, + "detects unreachable configuration predicates in the cfg_select macro", + @feature_gate = cfg_select; +} + declare_lint! { /// The `overlapping_range_endpoints` lint detects `match` arms that have [range patterns] that /// overlap on their endpoints. @@ -3457,7 +3488,7 @@ declare_lint! { /// but this lint was introduced to avoid breaking any existing /// crates which included them. pub INVALID_DOC_ATTRIBUTES, - Deny, + Warn, "detects invalid `#[doc(...)]` attributes", } @@ -4237,6 +4268,75 @@ declare_lint! { }; } +declare_lint! { + /// The `ambiguous_derive_helpers` lint detects cases where a derive macro's helper attribute + /// is the same name as that of a built-in attribute. + /// + /// ### Example + /// + /// ```rust,ignore (proc-macro) + /// #![crate_type = "proc-macro"] + /// #![deny(ambiguous_derive_helpers)] + /// + /// use proc_macro::TokenStream; + /// + /// #[proc_macro_derive(Trait, attributes(ignore))] + /// pub fn example(input: TokenStream) -> TokenStream { + /// TokenStream::new() + /// } + /// ``` + /// + /// Produces: + /// + /// ```text + /// warning: there exists a built-in attribute with the same name + /// --> file.rs:5:39 + /// | + /// 5 | #[proc_macro_derive(Trait, attributes(ignore))] + /// | ^^^^^^ + /// | + /// = 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 #151152 + /// = note: `#[deny(ambiguous_derive_helpers)]` (part of `#[deny(future_incompatible)]`) on by default + /// ``` + /// + /// ### Explanation + /// + /// Attempting to use this helper attribute will throw an error: + /// + /// ```rust,ignore (needs-dependency) + /// #[derive(Trait)] + /// struct Example { + /// #[ignore] + /// fields: () + /// } + /// ``` + /// + /// Produces: + /// + /// ```text + /// error[E0659]: `ignore` is ambiguous + /// --> src/lib.rs:5:7 + /// | + /// 5 | #[ignore] + /// | ^^^^^^ ambiguous name + /// | + /// = note: ambiguous because of a name conflict with a builtin attribute + /// = note: `ignore` could refer to a built-in attribute + /// note: `ignore` could also refer to the derive helper attribute defined here + /// --> src/lib.rs:3:10 + /// | + /// 3 | #[derive(Trait)] + /// | ^^^^^ + /// ``` + pub AMBIGUOUS_DERIVE_HELPERS, + Warn, + "detects derive helper attributes that are ambiguous with built-in attributes", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #151276), + }; +} + declare_lint! { /// The `private_interfaces` lint detects types in a primary interface of an item, /// that are more private than the item itself. Primary interface of an item is all @@ -4564,6 +4664,55 @@ declare_lint! { }; } +declare_lint! { + /// The `ambiguous_import_visibilities` lint detects imports that should report ambiguity + /// errors, but previously didn't do that due to rustc bugs. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(unknown_lints)] + /// #![deny(ambiguous_import_visibilities)] + /// mod reexport { + /// mod m { + /// pub struct S {} + /// } + /// + /// macro_rules! mac { + /// () => { use m::S; } + /// } + /// + /// pub use m::*; + /// mac!(); + /// + /// pub use S as Z; // ambiguous visibility + /// } + /// + /// fn main() { + /// reexport::Z {}; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust compile it successfully because it + /// fetched the glob import's visibility for `pub use S as Z` import, and ignored the private + /// `use m::S` import that appeared later. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub AMBIGUOUS_IMPORT_VISIBILITIES, + Warn, + "detects certain glob imports that require reporting an ambiguity error", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #149145), + }; +} + declare_lint! { /// The `refining_impl_trait_reachable` lint detects `impl Trait` return /// types in method signatures that are refined by a publically reachable diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4c78287b7784..a1b8b135819a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -748,6 +748,10 @@ pub enum BuiltinLintDiag { }, UnusedVisibility(Span), AttributeLint(AttributeLintKind), + UnreachableCfg { + span: Span, + wildcard_span: Option, + }, } #[derive(Debug, HashStable_Generic)] @@ -796,6 +800,7 @@ pub enum AttributeLintKind { attr_name: Symbol, }, DocInvalid, + AmbiguousDeriveHelpers, DocUnknownInclude { span: Span, inner: &'static str, @@ -826,6 +831,9 @@ pub enum AttributeLintKind { span: Span, suggested: Option, }, + MalformedDoc, + ExpectedNoArgs, + ExpectedNameValue, } pub type RegisteredTools = FxIndexSet; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 97f95ac01e86..7aa4ddea78e1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -812,12 +812,12 @@ extern "C" LLVMRustResult LLVMRustOptimize( auto ThinLTOBuffer = std::make_unique(); raw_string_ostream ThinLTODataOS(ThinLTOBuffer->data); raw_string_ostream ThinLinkDataOS(ThinLTOBuffer->thin_link_data); + bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || + OptStage == LLVMRustOptStage::FatLTO; if (!NoPrepopulatePasses) { // The pre-link pipelines don't support O0 and require using // buildO0DefaultPipeline() instead. At the same time, the LTO pipelines do // support O0 and using them is required. - bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || - OptStage == LLVMRustOptStage::FatLTO; if (OptLevel == OptimizationLevel::O0 && !IsLTO) { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); @@ -908,7 +908,10 @@ extern "C" LLVMRustResult LLVMRustOptimize( // now load "-enzyme" pass: // With dlopen, ENZYME macro may not be defined, so check EnzymePtr directly - if (EnzymePtr) { + // In the case of debug builds with multiple codegen units, we might not + // have all function definitions available during the early compiler + // invocations. We therefore wait for the final lto step to run Enzyme. + if (EnzymePtr && IsLTO) { if (PrintBeforeEnzyme) { // Handle the Rust flag `-Zautodiff=PrintModBefore`. @@ -929,6 +932,7 @@ extern "C" LLVMRustResult LLVMRustOptimize( MPM.addPass(PrintModulePass(outs(), Banner, true, false)); } } + if (PrintPasses) { // Print all passes from the PM: std::string Pipeline; diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index f9d3b7583590..f097aee54abb 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -8,6 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start +fluent-bundle = "0.16" +fluent-syntax = "0.12" proc-macro2 = "1" quote = "1" syn = { version = "2.0.9", features = ["full"] } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 7e784e3464e9..dc8231e5f0b0 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -1,7 +1,5 @@ #![deny(unused_must_use)] -use std::cell::RefCell; - use proc_macro2::TokenStream; use quote::quote; use synstructure::Structure; @@ -22,20 +20,20 @@ impl<'a> DiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::Diagnostic; - let slugs = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let Some(slug) = builder.primary_message() else { + let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().push(slug.clone()); + let message = message.diag_message(Some(variant)); + let init = quote! { let mut diag = rustc_errors::Diag::new( dcx, level, - crate::fluent_generated::#slug + #message ); }; @@ -50,9 +48,7 @@ impl<'a> DiagnosticDerive<'a> { }); // A lifetime of `'a` causes conflicts, but `_sess` is fine. - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - let mut imp = structure.gen_impl(quote! { + structure.gen_impl(quote! { gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self where G: rustc_errors::EmissionGuarantee { @@ -65,11 +61,7 @@ impl<'a> DiagnosticDerive<'a> { #implementation } } - }); - for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { - imp.extend(test); - } - imp + }) } } @@ -86,17 +78,16 @@ impl<'a> LintDiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let LintDiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::LintDiagnostic; - let slugs = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let Some(slug) = builder.primary_message() else { + let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().push(slug.clone()); + let message = message.diag_message(Some(variant)); let primary_message = quote! { - diag.primary_message(crate::fluent_generated::#slug); + diag.primary_message(#message); }; let formatting_init = &builder.formatting_init; @@ -109,9 +100,7 @@ impl<'a> LintDiagnosticDerive<'a> { } }); - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - let mut imp = structure.gen_impl(quote! { + structure.gen_impl(quote! { gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( @@ -121,48 +110,6 @@ impl<'a> LintDiagnosticDerive<'a> { #implementation; } } - }); - for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { - imp.extend(test); - } - - imp - } -} - -/// Generates a `#[test]` that verifies that all referenced variables -/// exist on this structure. -fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream { - // FIXME: We can't identify variables in a subdiagnostic - for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) { - for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) { - if attr_name == "subdiagnostic" { - return quote!(); - } - } - } - use std::sync::atomic::{AtomicUsize, Ordering}; - // We need to make sure that the same diagnostic slug can be used multiple times without - // causing an error, so just have a global counter here. - static COUNTER: AtomicUsize = AtomicUsize::new(0); - let slug = slug.get_ident().unwrap(); - let ident = quote::format_ident!("verify_{slug}_{}", COUNTER.fetch_add(1, Ordering::Relaxed)); - let ref_slug = quote::format_ident!("{slug}_refs"); - let struct_name = &structure.ast().ident; - let variables: Vec<_> = structure - .variants() - .iter() - .flat_map(|v| v.ast().fields.iter().filter_map(|f| f.ident.as_ref().map(|i| i.to_string()))) - .collect(); - // tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this - quote! { - #[cfg(test)] - #[test ] - fn #ident() { - let variables = [#(#variables),*]; - for vref in crate::fluent_generated::#ref_slug { - assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug)); - } - } + }) } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index cbc70b55d7ee..de8ee42caf45 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -2,16 +2,18 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; +use syn::parse::ParseStream; use syn::spanned::Spanned; -use syn::{Attribute, Meta, Path, Token, Type, parse_quote}; +use syn::{Attribute, LitStr, Meta, Path, Token, Type}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; use crate::diagnostics::error::{ DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; use crate::diagnostics::utils::{ - FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, SubdiagnosticKind, build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, should_generate_arg, type_is_bool, type_is_unit, type_matches_path, }; @@ -40,21 +42,15 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { /// derive builder. pub field_map: FieldMap, - /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that + /// Message is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - pub slug: SpannedOption, + pub message: Option, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. pub code: SpannedOption<()>, } -impl HasFieldMap for DiagnosticDeriveVariantBuilder { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.field_map.get(field) - } -} - impl DiagnosticDeriveKind { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions @@ -95,7 +91,7 @@ impl DiagnosticDeriveKind { span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), - slug: None, + message: None, code: None, }; f(builder, variant) @@ -110,28 +106,18 @@ impl DiagnosticDeriveKind { } impl DiagnosticDeriveVariantBuilder { - pub(crate) fn primary_message(&self) -> Option<&Path> { - match self.slug.value_ref() { + pub(crate) fn primary_message(&self) -> Option<&Message> { + match self.message.as_ref() { None => { - span_err(self.span, "diagnostic slug not specified") + span_err(self.span, "diagnostic message not specified") .help( - "specify the slug as the first argument to the `#[diag(...)]` \ - attribute, such as `#[diag(hir_analysis_example_error)]`", + "specify the message as the first argument to the `#[diag(...)]` \ + attribute, such as `#[diag(\"Example error\")]`", ) .emit(); None } - Some(slug) - if let Some(Mismatch { slug_name, crate_name, slug_prefix }) = - Mismatch::check(slug) => - { - span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match") - .note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`")) - .help(format!("expected a slug starting with `{slug_prefix}_...`")) - .emit(); - None - } - Some(slug) => Some(slug), + Some(msg) => Some(msg), } } @@ -141,7 +127,8 @@ impl DiagnosticDeriveVariantBuilder { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { - self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) + self.generate_structure_code_for_attr(attr, variant) + .unwrap_or_else(|v| v.to_compile_error()) }); quote! { @@ -159,7 +146,7 @@ impl DiagnosticDeriveVariantBuilder { } // ..and then subdiagnostic additions. for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { - body.extend(self.generate_field_attrs_code(binding)); + body.extend(self.generate_field_attrs_code(binding, variant)); } body } @@ -168,8 +155,8 @@ impl DiagnosticDeriveVariantBuilder { fn parse_subdiag_attribute( &self, attr: &Attribute, - ) -> Result, DiagnosticDeriveError> { - let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, self)? else { + ) -> Result, DiagnosticDeriveError> { + let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(None); @@ -180,26 +167,20 @@ impl DiagnosticDeriveVariantBuilder { .help("consider creating a `Subdiagnostic` instead")); } - let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind { - SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, - SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, - SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once }, - SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, - SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once }, - SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, - SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, - SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), - }); + let Some(message) = subdiag.message else { + throw_invalid_attr!(attr, |diag| diag.help("subdiagnostic message is missing")) + }; - Ok(Some((subdiag.kind, slug, subdiag.no_span))) + Ok(Some((subdiag.kind, message, false))) } /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct - /// attributes like `#[diag(..)]`, such as the slug and error code. Generates + /// attributes like `#[diag(..)]`, such as the message and error code. Generates /// diagnostic builder calls for setting error code and creating note/help messages. fn generate_structure_code_for_attr( &mut self, attr: &Attribute, + variant: &VariantInfo<'_>, ) -> Result { // Always allow documentation comments. if is_doc_comment(attr) { @@ -209,51 +190,66 @@ impl DiagnosticDeriveVariantBuilder { let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); - let mut first = true; - if name == "diag" { let mut tokens = TokenStream::new(); - attr.parse_nested_meta(|nested| { - let path = &nested.path; - - if first && (nested.input.is_empty() || nested.input.peek(Token![,])) { - self.slug.set_once(path.clone(), path.span().unwrap()); - first = false; - return Ok(()); + attr.parse_args_with(|input: ParseStream<'_>| { + if input.peek(LitStr) { + // Parse an inline message + let message = input.parse::()?; + if !message.suffix().is_empty() { + span_err( + message.span().unwrap(), + "Inline message is not allowed to have a suffix", + ) + .emit(); + } + self.message = Some(Message { + attr_span: attr.span(), + message_span: message.span(), + value: message.value(), + }); } - first = false; - - let Ok(nested) = nested.value() else { - span_err( - nested.input.span().unwrap(), - "diagnostic slug must be the first argument", - ) - .emit(); - return Ok(()); - }; - - if path.is_ident("code") { - self.code.set_once((), path.span().unwrap()); - - let code = nested.parse::()?; - tokens.extend(quote! { - diag.code(#code); - }); - } else { - span_err(path.span().unwrap(), "unknown argument") - .note("only the `code` parameter is valid after the slug") + // Parse arguments + while !input.is_empty() { + input.parse::()?; + // Allow trailing comma + if input.is_empty() { + break; + } + let arg_name: Path = input.parse::()?; + if input.peek(Token![,]) { + span_err( + arg_name.span().unwrap(), + "diagnostic message must be the first argument", + ) .emit(); - - // consume the buffer so we don't have syntax errors from syn - let _ = nested.parse::(); + continue; + } + let arg_name = arg_name.require_ident()?; + input.parse::()?; + let arg_value = input.parse::()?; + match arg_name.to_string().as_str() { + "code" => { + self.code.set_once((), arg_name.span().unwrap()); + tokens.extend(quote! { + diag.code(#arg_value); + }); + } + _ => { + span_err(arg_name.span().unwrap(), "unknown argument") + .note("only the `code` parameter is valid after the message") + .emit(); + } + } } Ok(()) })?; + return Ok(tokens); } - let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else { + let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(quote! {}); @@ -264,7 +260,7 @@ impl DiagnosticDeriveVariantBuilder { | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help | SubdiagnosticKind::HelpOnce - | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug)), + | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message, variant)), SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); @@ -292,7 +288,11 @@ impl DiagnosticDeriveVariantBuilder { } } - fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + fn generate_field_attrs_code( + &mut self, + binding_info: &BindingInfo<'_>, + variant: &VariantInfo<'_>, + ) -> TokenStream { let field = binding_info.ast(); let field_binding = &binding_info.binding; @@ -331,6 +331,7 @@ impl DiagnosticDeriveVariantBuilder { attr, FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() }, binding, + variant ) .unwrap_or_else(|v| v.to_compile_error()); @@ -348,6 +349,7 @@ impl DiagnosticDeriveVariantBuilder { attr: &Attribute, info: FieldInfo<'_>, binding: TokenStream, + variant: &VariantInfo<'_>, ) -> Result { let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); @@ -377,7 +379,7 @@ impl DiagnosticDeriveVariantBuilder { _ => (), } - let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else { + let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(quote! {}); @@ -386,7 +388,7 @@ impl DiagnosticDeriveVariantBuilder { match subdiag { SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) } SubdiagnosticKind::Note | SubdiagnosticKind::NoteOnce @@ -397,11 +399,11 @@ impl DiagnosticDeriveVariantBuilder { if type_matches_path(inner, &["rustc_span", "Span"]) || type_matches_path(inner, &["rustc_span", "MultiSpan"]) { - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) } else if type_is_unit(inner) || (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner)) { - Ok(self.add_subdiagnostic(&fn_ident, slug)) + Ok(self.add_subdiagnostic(&fn_ident, message, variant)) } else { report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")? } @@ -427,6 +429,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } + let message = message.diag_message(Some(variant)); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -436,7 +439,7 @@ impl DiagnosticDeriveVariantBuilder { Ok(quote! { diag.span_suggestions_with_style( #span_field, - crate::fluent_generated::#slug, + #message, #code_field, #applicability, #style @@ -447,28 +450,36 @@ impl DiagnosticDeriveVariantBuilder { } } - /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current message /// and `fluent_attr_identifier`. fn add_spanned_subdiagnostic( &self, field_binding: TokenStream, kind: &Ident, - fluent_attr_identifier: Path, + message: Message, + variant: &VariantInfo<'_>, ) -> TokenStream { let fn_name = format_ident!("span_{}", kind); + let message = message.diag_message(Some(variant)); quote! { diag.#fn_name( #field_binding, - crate::fluent_generated::#fluent_attr_identifier + #message ); } } - /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current message /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { + fn add_subdiagnostic( + &self, + kind: &Ident, + message: Message, + variant: &VariantInfo<'_>, + ) -> TokenStream { + let message = message.diag_message(Some(variant)); quote! { - diag.#kind(crate::fluent_generated::#fluent_attr_identifier); + diag.#kind(#message); } } @@ -529,27 +540,3 @@ impl DiagnosticDeriveVariantBuilder { } } } - -struct Mismatch { - slug_name: String, - crate_name: String, - slug_prefix: String, -} - -impl Mismatch { - /// Checks whether the slug starts with the crate name it's in. - fn check(slug: &syn::Path) -> Option { - // If this is missing we're probably in a test, so bail. - let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?; - - // If we're not in a "rustc_" crate, bail. - let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None }; - - let slug_name = slug.segments.first()?.ident.to_string(); - if slug_name.starts_with(slug_prefix) { - return None; - } - - Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name }) - } -} diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs new file mode 100644 index 000000000000..dfc5c7e800c6 --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -0,0 +1,154 @@ +use fluent_bundle::FluentResource; +use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement}; +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::ext::IdentExt; +use synstructure::VariantInfo; + +use crate::diagnostics::error::span_err; + +#[derive(Clone)] +pub(crate) struct Message { + pub attr_span: Span, + pub message_span: Span, + pub value: String, +} + +impl Message { + /// Get the diagnostic message for this diagnostic + /// The passed `variant` is used to check whether all variables in the message are used. + /// For subdiagnostics, we cannot check this. + pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { + let message = &self.value; + self.verify(variant); + quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } + } + + fn verify(&self, variant: Option<&VariantInfo<'_>>) { + verify_variables_used(self.message_span, &self.value, variant); + verify_message_style(self.message_span, &self.value); + verify_message_formatting(self.attr_span, self.message_span, &self.value); + } +} + +fn verify_variables_used(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { + // Parse the fluent message + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = + FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message_str}\n")).unwrap(); + assert_eq!(resource.entries().count(), 1); + let Some(fluent_syntax::ast::Entry::Message(message)) = resource.get_entry(0) else { + panic!("Did not parse into a message") + }; + + // Check if all variables are used + if let Some(variant) = variant { + let fields: Vec = variant + .bindings() + .iter() + .flat_map(|b| b.ast().ident.as_ref()) + .map(|id| id.unraw().to_string()) + .collect(); + for variable in variable_references(&message) { + if !fields.iter().any(|f| f == variable) { + span_err( + msg_span.unwrap(), + format!("Variable `{variable}` not found in diagnostic "), + ) + .help(format!("Available fields: {:?}", fields.join(", "))) + .emit(); + } + } + } +} + +fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { + let mut refs = vec![]; + if let Some(Pattern { elements }) = &msg.value { + for elt in elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + for attr in &msg.attributes { + for elt in &attr.value.elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + refs +} + +const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ + // tidy-alphabetical-start + "ABI", + "ABIs", + "ADT", + "C-variadic", + "CGU-reuse", + "Cargo", + "Ferris", + "GCC", + "MIR", + "NaNs", + "OK", + "Rust", + "ThinLTO", + "Unicode", + "VS", + // tidy-alphabetical-end +]; + +/// See: https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-output-style-guide +fn verify_message_style(msg_span: Span, message: &str) { + // Verify that message starts with lowercase char + let Some(first_word) = message.split_whitespace().next() else { + span_err(msg_span.unwrap(), "message must not be empty").emit(); + return; + }; + let first_char = first_word.chars().next().expect("Word is not empty"); + if first_char.is_uppercase() && !ALLOWED_CAPITALIZED_WORDS.contains(&first_word) { + span_err(msg_span.unwrap(), "message `{value}` starts with an uppercase letter. Fix it or add it to `ALLOWED_CAPITALIZED_WORDS`").emit(); + return; + } + + // Verify that message does not end in `.` + if message.ends_with(".") && !message.ends_with("...") { + span_err(msg_span.unwrap(), "message `{value}` ends with a period").emit(); + return; + } +} + +/// Verifies that the message is properly indented into the code +fn verify_message_formatting(attr_span: Span, msg_span: Span, message: &str) { + // Find the indent at the start of the message (`column()` is one-indexed) + let start = attr_span.unwrap().column() - 1; + + for line in message.lines().skip(1) { + if line.is_empty() { + continue; + } + let indent = line.chars().take_while(|c| *c == ' ').count(); + if indent < start { + span_err( + msg_span.unwrap(), + format!("message is not properly indented. {indent} < {start}"), + ) + .emit(); + return; + } + if indent % 4 != 0 { + span_err(msg_span.unwrap(), "message is not indented with a multiple of 4 spaces") + .emit(); + return; + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 55228248188e..c0512e86bbcb 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,10 +1,13 @@ mod diagnostic; mod diagnostic_builder; mod error; +mod message; +mod msg_macro; mod subdiagnostic; mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; +pub(super) use msg_macro::msg_macro; use proc_macro2::TokenStream; use subdiagnostic::SubdiagnosticDerive; use synstructure::Structure; @@ -20,36 +23,25 @@ use synstructure::Structure; /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(Diagnostic)] -/// #[diag(borrowck_move_out_of_borrow, code = E0505)] -/// pub struct MoveOutOfBorrowError<'tcx> { +/// #[diag("this is an example message", code = E0123)] +/// pub(crate) struct ExampleError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, /// #[primary_span] -/// #[label] +/// #[label("with a label")] /// pub span: Span, -/// #[label(first_borrow_label)] -/// pub first_borrow_span: Span, -/// #[suggestion(code = "{name}.clone()")] -/// pub clone_sugg: Option<(Span, Applicability)> +/// #[label("with a label")] +/// pub other_span: Span, +/// #[suggestion("with a suggestion", code = "{name}.clone()")] +/// pub opt_sugg: Option<(Span, Applicability)>, /// } /// ``` /// -/// ```fluent -/// move_out_of_borrow = cannot move out of {$name} because it is borrowed -/// .label = cannot move out of borrow -/// .first_borrow_label = `{$ty}` first borrowed here -/// .suggestion = consider cloning here -/// ``` -/// /// Then, later, to emit the error: /// /// ```ignore (rust) -/// sess.emit_err(MoveOutOfBorrowError { -/// expected, -/// actual, -/// span, -/// first_borrow_span, -/// clone_sugg: Some(suggestion, Applicability::MachineApplicable), +/// sess.emit_err(ExampleError { +/// name, ty, span, other_span, opt_sugg /// }); /// ``` /// @@ -64,38 +56,24 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream { /// /// ```ignore (rust) /// #[derive(LintDiagnostic)] -/// #[diag(lint_atomic_ordering_invalid_fail_success)] -/// pub struct AtomicOrderingInvalidLint { -/// method: Symbol, -/// success_ordering: Symbol, -/// fail_ordering: Symbol, -/// #[label(fail_label)] -/// fail_order_arg_span: Span, -/// #[label(success_label)] -/// #[suggestion( -/// code = "std::sync::atomic::Ordering::{success_suggestion}", -/// applicability = "maybe-incorrect" +/// #[diag("unused attribute")] +/// pub(crate) struct UnusedAttribute { +/// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] +/// pub this: Span, +/// #[note("attribute also specified here")] +/// pub other: Span, +/// #[warning( +/// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" /// )] -/// success_order_arg_span: Span, +/// pub warning: bool, /// } /// ``` /// -/// ```fluent -/// lint_atomic_ordering_invalid_fail_success = `{$method}`'s success ordering must be at least as strong as its failure ordering -/// .fail_label = `{$fail_ordering}` failure ordering -/// .success_label = `{$success_ordering}` success ordering -/// .suggestion = consider using `{$success_suggestion}` success ordering instead -/// ``` -/// /// Then, later, to emit the error: /// /// ```ignore (rust) -/// cx.emit_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint { -/// method, -/// success_ordering, -/// fail_ordering, -/// fail_order_arg_span, -/// success_order_arg_span, +/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute { +/// ... /// }); /// ``` /// @@ -111,45 +89,25 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// /// ```ignore (rust) /// #[derive(Subdiagnostic)] -/// pub enum ExpectedIdentifierLabel<'tcx> { -/// #[label(expected_identifier)] -/// WithoutFound { -/// #[primary_span] -/// span: Span, -/// } -/// #[label(expected_identifier_found)] -/// WithFound { -/// #[primary_span] -/// span: Span, -/// found: String, -/// } -/// } -/// -/// #[derive(Subdiagnostic)] -/// #[suggestion(style = "verbose",parser::raw_identifier)] -/// pub struct RawIdentifierSuggestion<'tcx> { -/// #[primary_span] -/// span: Span, -/// #[applicability] -/// applicability: Applicability, -/// ident: Ident, +/// pub(crate) enum BuiltinUnusedDocCommentSub { +/// #[help("use `//` for a plain comment")] +/// PlainHelp, +/// #[help("use `/* */` for a plain comment")] +/// BlockHelp, /// } /// ``` -/// -/// ```fluent -/// parser_expected_identifier = expected identifier -/// -/// parser_expected_identifier_found = expected identifier, found {$found} -/// -/// parser_raw_identifier = escape `{$ident}` to use it as an identifier -/// ``` -/// -/// Then, later, to add the subdiagnostic: +/// Then, later, use the subdiagnostic in a diagnostic: /// /// ```ignore (rust) -/// diag.subdiagnostic(ExpectedIdentifierLabel::WithoutFound { span }); -/// -/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident }); +/// #[derive(LintDiagnostic)] +/// #[diag("unused doc comment")] +/// pub(crate) struct BuiltinUnusedDocComment<'a> { +/// pub kind: &'a str, +/// #[label("rustdoc does not generate documentation for {$kind}")] +/// pub label: Span, +/// #[subdiagnostic] +/// pub sub: BuiltinUnusedDocCommentSub, +/// } /// ``` pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream { SubdiagnosticDerive::new().into_tokens(s) diff --git a/compiler/rustc_macros/src/diagnostics/msg_macro.rs b/compiler/rustc_macros/src/diagnostics/msg_macro.rs new file mode 100644 index 000000000000..66bc200707ef --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/msg_macro.rs @@ -0,0 +1,10 @@ +use syn::{LitStr, parse_macro_input}; + +use crate::diagnostics::message::Message; + +pub(crate) fn msg_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let inline = parse_macro_input!(input as LitStr); + let message = + Message { attr_span: inline.span(), message_span: inline.span(), value: inline.value() }; + message.diag_message(None).into() +} diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index dcd0116d804d..7eb170ec236a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,20 +1,22 @@ #![deny(unused_must_use)] -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; +use syn::parse::ParseStream; use syn::spanned::Spanned; -use syn::{Attribute, Meta, MetaList, Path}; +use syn::{Attribute, Meta, MetaList, Path, Token}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; use crate::diagnostics::error::{ DiagnosticDeriveError, invalid_attr, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; use crate::diagnostics::utils::{ - AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, - SpannedOption, SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, - new_code_ident, report_error_if_not_applied_to_applicability, - report_error_if_not_applied_to_span, should_generate_arg, + AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, + SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, + should_generate_arg, }; /// The central struct for constructing the `add_to_diag` method from an annotated struct. @@ -142,12 +144,6 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { is_enum: bool, } -impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.fields.get(field) - } -} - /// Provides frequently-needed information about the diagnostic kinds being derived for this type. #[derive(Clone, Copy, Debug)] struct KindsStatistics { @@ -189,34 +185,34 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { fn identify_kind( &mut self, - ) -> Result, DiagnosticDeriveError> { - let mut kind_slugs = vec![]; + ) -> Result, DiagnosticDeriveError> { + let mut kind_messages = vec![]; for attr in self.variant.ast().attrs { - let Some(SubdiagnosticVariant { kind, slug, no_span }) = - SubdiagnosticVariant::from_attr(attr, self)? + let Some(SubdiagnosticVariant { kind, message }) = + SubdiagnosticVariant::from_attr(attr, &self.fields)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. continue; }; - let Some(slug) = slug else { + let Some(message) = message else { let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); throw_span_err!( attr.span().unwrap(), format!( - "diagnostic slug must be first argument of a `#[{name}(...)]` attribute" + "diagnostic message must be first argument of a `#[{name}(...)]` attribute" ) ); }; - kind_slugs.push((kind, slug, no_span)); + kind_messages.push((kind, message)); } - Ok(kind_slugs) + Ok(kind_messages) } /// Generates the code for a field with no attributes. @@ -437,23 +433,35 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut code = None; - list.parse_nested_meta(|nested| { - if nested.path.is_ident("code") { - let code_field = new_code_ident(); - let span = nested.path.span().unwrap(); - let formatting_init = build_suggestion_code( - &code_field, - nested, - self, - AllowMultipleAlternatives::No, - ); - code.set_once((code_field, formatting_init), span); - } else { - span_err( - nested.path.span().unwrap(), - "`code` is the only valid nested attribute", - ) - .emit(); + list.parse_args_with(|input: ParseStream<'_>| { + while !input.is_empty() { + let arg_name = input.parse::()?; + match arg_name.to_string().as_str() { + "code" => { + let code_field = new_code_ident(); + let formatting_init = build_suggestion_code( + &code_field, + input, + &self.fields, + AllowMultipleAlternatives::No, + )?; + code.set_once( + (code_field, formatting_init), + arg_name.span().unwrap(), + ); + } + _ => { + span_err( + arg_name.span().unwrap(), + "`code` is the only valid nested attribute", + ) + .emit(); + } + } + if input.is_empty() { + break; + } + input.parse::()?; } Ok(()) })?; @@ -490,10 +498,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } pub(crate) fn into_tokens(&mut self) -> Result { - let kind_slugs = self.identify_kind()?; + let kind_messages = self.identify_kind()?; - let kind_stats: KindsStatistics = - kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect(); + let kind_stats: KindsStatistics = kind_messages.iter().map(|(kind, _msg)| kind).collect(); let init = if kind_stats.has_multipart_suggestion { quote! { let mut suggestions = Vec::new(); } @@ -509,7 +516,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); - if kind_slugs.is_empty() && !self.has_subdiagnostic { + if kind_messages.is_empty() && !self.has_subdiagnostic { if self.is_enum { // It's okay for a variant to not be a subdiagnostic at all.. return Ok(quote! {}); @@ -526,17 +533,12 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let diag = &self.parent.diag; let mut calls = TokenStream::new(); - for (kind, slug, no_span) in kind_slugs { + for (kind, messages) in kind_messages { let message = format_ident!("__message"); - calls.extend( - quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); }, - ); + let message_stream = messages.diag_message(None); + calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); - let name = format_ident!( - "{}{}", - if span_field.is_some() && !no_span { "span_" } else { "" }, - kind - ); + let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let call = match kind { SubdiagnosticKind::Suggestion { suggestion_kind, @@ -588,9 +590,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } _ => { - if let Some(span) = span_field - && !no_span - { + if let Some(span) = span_field { quote! { #diag.#name(#span, #message); } } else { quote! { #diag.#name(#message); } diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index c310b99d5351..55a8445744cb 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -6,7 +6,7 @@ use std::str::FromStr; use proc_macro::Span; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, format_ident, quote}; -use syn::meta::ParseNestedMeta; +use syn::parse::ParseStream; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{Attribute, Field, LitStr, Meta, Path, Token, Type, TypeTuple, parenthesized}; @@ -16,6 +16,7 @@ use super::error::invalid_attr; use crate::diagnostics::error::{ DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; thread_local! { pub(crate) static CODE_IDENT_COUNT: RefCell = RefCell::new(0); @@ -261,108 +262,104 @@ impl SetOnce for SpannedOption { pub(super) type FieldMap = HashMap; -pub(crate) trait HasFieldMap { - /// Returns the binding for the field with the given name, if it exists on the type. - fn get_field_binding(&self, field: &String) -> Option<&TokenStream>; +/// In the strings in the attributes supplied to this macro, we want callers to be able to +/// reference fields in the format string. For example: +/// +/// ```ignore (not-usage-example) +/// /// Suggest `==` when users wrote `===`. +/// #[suggestion("example message", code = "{lhs} == {rhs}")] +/// struct NotJavaScriptEq { +/// #[primary_span] +/// span: Span, +/// lhs: Ident, +/// rhs: Ident, +/// } +/// ``` +/// +/// We want to automatically pick up that `{lhs}` refers `self.lhs` and `{rhs}` refers to +/// `self.rhs`, then generate this call to `format!`: +/// +/// ```ignore (not-usage-example) +/// format!("{lhs} == {rhs}", lhs = self.lhs, rhs = self.rhs) +/// ``` +/// +/// This function builds the entire call to `format!`. +pub(super) fn build_format( + field_map: &FieldMap, + input: &str, + span: proc_macro2::Span, +) -> TokenStream { + // This set is used later to generate the final format string. To keep builds reproducible, + // the iteration order needs to be deterministic, hence why we use a `BTreeSet` here + // instead of a `HashSet`. + let mut referenced_fields: BTreeSet = BTreeSet::new(); - /// In the strings in the attributes supplied to this macro, we want callers to be able to - /// reference fields in the format string. For example: - /// - /// ```ignore (not-usage-example) - /// /// Suggest `==` when users wrote `===`. - /// #[suggestion(slug = "parser-not-javascript-eq", code = "{lhs} == {rhs}")] - /// struct NotJavaScriptEq { - /// #[primary_span] - /// span: Span, - /// lhs: Ident, - /// rhs: Ident, - /// } - /// ``` - /// - /// We want to automatically pick up that `{lhs}` refers `self.lhs` and `{rhs}` refers to - /// `self.rhs`, then generate this call to `format!`: - /// - /// ```ignore (not-usage-example) - /// format!("{lhs} == {rhs}", lhs = self.lhs, rhs = self.rhs) - /// ``` - /// - /// This function builds the entire call to `format!`. - fn build_format(&self, input: &str, span: proc_macro2::Span) -> TokenStream { - // This set is used later to generate the final format string. To keep builds reproducible, - // the iteration order needs to be deterministic, hence why we use a `BTreeSet` here - // instead of a `HashSet`. - let mut referenced_fields: BTreeSet = BTreeSet::new(); + // At this point, we can start parsing the format string. + let mut it = input.chars().peekable(); - // At this point, we can start parsing the format string. - let mut it = input.chars().peekable(); - - // Once the start of a format string has been found, process the format string and spit out - // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so - // the next call to `it.next()` retrieves the next character. - while let Some(c) = it.next() { - if c != '{' { - continue; - } - if *it.peek().unwrap_or(&'\0') == '{' { - assert_eq!(it.next().unwrap(), '{'); - continue; - } - let mut eat_argument = || -> Option { - let mut result = String::new(); - // Format specifiers look like: - // - // format := '{' [ argument ] [ ':' format_spec ] '}' . - // - // Therefore, we only need to eat until ':' or '}' to find the argument. - while let Some(c) = it.next() { - result.push(c); - let next = *it.peek().unwrap_or(&'\0'); - if next == '}' { - break; - } else if next == ':' { - // Eat the ':' character. - assert_eq!(it.next().unwrap(), ':'); - break; - } - } - // Eat until (and including) the matching '}' - while it.next()? != '}' { - continue; - } - Some(result) - }; - - if let Some(referenced_field) = eat_argument() { - referenced_fields.insert(referenced_field); - } + // Once the start of a format string has been found, process the format string and spit out + // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so + // the next call to `it.next()` retrieves the next character. + while let Some(c) = it.next() { + if c != '{' { + continue; } + if *it.peek().unwrap_or(&'\0') == '{' { + assert_eq!(it.next().unwrap(), '{'); + continue; + } + let mut eat_argument = || -> Option { + let mut result = String::new(); + // Format specifiers look like: + // + // format := '{' [ argument ] [ ':' format_spec ] '}' . + // + // Therefore, we only need to eat until ':' or '}' to find the argument. + while let Some(c) = it.next() { + result.push(c); + let next = *it.peek().unwrap_or(&'\0'); + if next == '}' { + break; + } else if next == ':' { + // Eat the ':' character. + assert_eq!(it.next().unwrap(), ':'); + break; + } + } + // Eat until (and including) the matching '}' + while it.next()? != '}' { + continue; + } + Some(result) + }; - // At this point, `referenced_fields` contains a set of the unique fields that were - // referenced in the format string. Generate the corresponding "x = self.x" format - // string parameters: - let args = referenced_fields.into_iter().map(|field: String| { - let field_ident = format_ident!("{}", field); - let value = match self.get_field_binding(&field) { - Some(value) => value.clone(), - // This field doesn't exist. Emit a diagnostic. - None => { - span_err( - span.unwrap(), - format!("`{field}` doesn't refer to a field on this type"), - ) + if let Some(referenced_field) = eat_argument() { + referenced_fields.insert(referenced_field); + } + } + + // At this point, `referenced_fields` contains a set of the unique fields that were + // referenced in the format string. Generate the corresponding "x = self.x" format + // string parameters: + let args = referenced_fields.into_iter().map(|field: String| { + let field_ident = format_ident!("{}", field); + let value = match field_map.get(&field) { + Some(value) => value.clone(), + // This field doesn't exist. Emit a diagnostic. + None => { + span_err(span.unwrap(), format!("`{field}` doesn't refer to a field on this type")) .emit(); - quote! { - "{#field}" - } + quote! { + "{#field}" } - }; - quote! { - #field_ident = #value } - }); + }; quote! { - format!(#input #(,#args)*) + #field_ident = #value } + }); + quote! { + format!(#input #(,#args)*) } } @@ -428,76 +425,63 @@ pub(super) enum AllowMultipleAlternatives { } fn parse_suggestion_values( - nested: ParseNestedMeta<'_>, + nested: ParseStream<'_>, allow_multiple: AllowMultipleAlternatives, ) -> syn::Result> { - let values = if let Ok(val) = nested.value() { - vec![val.parse()?] - } else { - let content; - parenthesized!(content in nested.input); + if nested.parse::().is_ok() { + return Ok(vec![nested.parse::()?]); + } - if let AllowMultipleAlternatives::No = allow_multiple { + let content; + parenthesized!(content in nested); + if let AllowMultipleAlternatives::No = allow_multiple { + span_err(content.span().unwrap(), "expected exactly one string literal for `code = ...`") + .emit(); + return Ok(vec![]); + } + + let literals = Punctuated::::parse_terminated(&content); + Ok(match literals { + Ok(p) if p.is_empty() => { span_err( - nested.input.span().unwrap(), - "expected exactly one string literal for `code = ...`", + content.span().unwrap(), + "expected at least one string literal for `code(...)`", ) .emit(); vec![] - } else { - let literals = Punctuated::::parse_terminated(&content); - - match literals { - Ok(p) if p.is_empty() => { - span_err( - content.span().unwrap(), - "expected at least one string literal for `code(...)`", - ) - .emit(); - vec![] - } - Ok(p) => p.into_iter().collect(), - Err(_) => { - span_err( - content.span().unwrap(), - "`code(...)` must contain only string literals", - ) - .emit(); - vec![] - } - } } - }; - - Ok(values) + Ok(p) => p.into_iter().collect(), + Err(_) => { + span_err(content.span().unwrap(), "`code(...)` must contain only string literals") + .emit(); + vec![] + } + }) } /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or /// `#[suggestion*(code("foo", "bar"))]` attribute field pub(super) fn build_suggestion_code( code_field: &Ident, - nested: ParseNestedMeta<'_>, - fields: &impl HasFieldMap, + nested: ParseStream<'_>, + fields: &FieldMap, allow_multiple: AllowMultipleAlternatives, -) -> TokenStream { - let values = match parse_suggestion_values(nested, allow_multiple) { - Ok(x) => x, - Err(e) => return e.into_compile_error(), - }; +) -> Result { + let values = parse_suggestion_values(nested, allow_multiple)?; - if let AllowMultipleAlternatives::Yes = allow_multiple { + Ok(if let AllowMultipleAlternatives::Yes = allow_multiple { let formatted_strings: Vec<_> = values .into_iter() - .map(|value| fields.build_format(&value.value(), value.span())) + .map(|value| build_format(fields, &value.value(), value.span())) .collect(); quote! { let #code_field = [#(#formatted_strings),*].into_iter(); } } else if let [value] = values.as_slice() { - let formatted_str = fields.build_format(&value.value(), value.span()); + let formatted_str = build_format(fields, &value.value(), value.span()); quote! { let #code_field = #formatted_str; } } else { // error handled previously quote! { let #code_field = String::new(); } - } + }) } /// Possible styles for suggestion subdiagnostics. @@ -604,17 +588,16 @@ pub(super) enum SubdiagnosticKind { pub(super) struct SubdiagnosticVariant { pub(super) kind: SubdiagnosticKind, - pub(super) slug: Option, - pub(super) no_span: bool, + pub(super) message: Option, } impl SubdiagnosticVariant { /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`, - /// `#[error(parser::add_paren, no_span)]` or `#[suggestion(code = "...")]`. Returns the - /// `SubdiagnosticKind` and the diagnostic slug, if specified. + /// `#[error("add parenthesis")]` or `#[suggestion(code = "...")]`. Returns the + /// `SubdiagnosticKind` and the diagnostic message, if specified. pub(super) fn from_attr( attr: &Attribute, - fields: &impl HasFieldMap, + fields: &FieldMap, ) -> Result, DiagnosticDeriveError> { // Always allow documentation comments. if is_doc_comment(attr) { @@ -677,11 +660,11 @@ impl SubdiagnosticVariant { let list = match &attr.meta { Meta::List(list) => { // An attribute with properties, such as `#[suggestion(code = "...")]` or - // `#[error(some::slug)]` + // `#[error("message")]` list } Meta::Path(_) => { - // An attribute without a slug or other properties, such as `#[note]` - return + // An attribute without a message or other properties, such as `#[note]` - return // without further processing. // // Only allow this if there are no mandatory properties, such as `code = "..."` in @@ -694,7 +677,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::HelpOnce | SubdiagnosticKind::Warn | SubdiagnosticKind::MultipartSuggestion { .. } => { - return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false })); + return Ok(Some(SubdiagnosticVariant { kind, message: None })); } SubdiagnosticKind::Suggestion { .. } => { throw_span_err!(span, "suggestion without `code = \"...\"`") @@ -709,112 +692,103 @@ impl SubdiagnosticVariant { let mut code = None; let mut suggestion_kind = None; - let mut first = true; - let mut slug = None; - let mut no_span = false; + let mut message = None; - list.parse_nested_meta(|nested| { - if nested.input.is_empty() || nested.input.peek(Token![,]) { - if first { - slug = Some(nested.path); - } else if nested.path.is_ident("no_span") { - no_span = true; - } else { - span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit(); + list.parse_args_with(|input: ParseStream<'_>| { + let mut is_first = true; + while !input.is_empty() { + // Try to parse an inline diagnostic message + if input.peek(LitStr) { + let inline_message = input.parse::()?; + if !inline_message.suffix().is_empty() { + span_err( + inline_message.span().unwrap(), + "Inline message is not allowed to have a suffix", + ).emit(); + } + if !input.is_empty() { input.parse::()?; } + if is_first { + message = Some(Message { attr_span: attr.span(), message_span: inline_message.span(), value: inline_message.value() }); + is_first = false; + } else { + span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); + } + continue } + is_first = false; - first = false; - return Ok(()); - } + // Try to parse an argument + let arg_name: Path = input.parse::()?; + let arg_name_span = arg_name.span().unwrap(); + match (arg_name.require_ident()?.to_string().as_str(), &mut kind) { + ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { + let code_init = build_suggestion_code( + &code_field, + &input, + fields, + AllowMultipleAlternatives::Yes, + )?; + code.set_once(code_init, arg_name_span); + } + ( + "applicability", + SubdiagnosticKind::Suggestion { applicability, .. } + | SubdiagnosticKind::MultipartSuggestion { applicability, .. }, + ) => { + input.parse::()?; + let value = input.parse::()?; + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { + span_err(value.span().unwrap(), "invalid applicability").emit(); + Applicability::Unspecified + }); + applicability.set_once(value, span); + } + ( + "style", + SubdiagnosticKind::Suggestion { .. } + | SubdiagnosticKind::MultipartSuggestion { .. }, + ) => { + input.parse::()?; + let value = input.parse::()?; - first = false; + let value = value.value().parse().unwrap_or_else(|()| { + span_err(value.span().unwrap(), "invalid suggestion style") + .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") + .emit(); + SuggestionKind::Normal + }); - let nested_name = nested.path.segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); + suggestion_kind.set_once(value, span); + } - let path_span = nested.path.span().unwrap(); - let val_span = nested.input.span().unwrap(); - macro_rules! get_string { - () => {{ - let Ok(value) = nested.value().and_then(|x| x.parse::()) else { - span_err(val_span, "expected `= \"xxx\"`").emit(); - return Ok(()); - }; - value - }}; - } - - let mut has_errors = false; - let input = nested.input; - - match (nested_name, &mut kind) { - ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { - let code_init = build_suggestion_code( - code_field, - nested, - fields, - AllowMultipleAlternatives::Yes, - ); - code.set_once(code_init, path_span); - } - ( - "applicability", - SubdiagnosticKind::Suggestion { applicability, .. } - | SubdiagnosticKind::MultipartSuggestion { applicability, .. }, - ) => { - let value = get_string!(); - let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(value.span().unwrap(), "invalid applicability").emit(); - has_errors = true; - Applicability::Unspecified - }); - applicability.set_once(value, span); - } - ( - "style", - SubdiagnosticKind::Suggestion { .. } - | SubdiagnosticKind::MultipartSuggestion { .. }, - ) => { - let value = get_string!(); - - let value = value.value().parse().unwrap_or_else(|()| { - span_err(value.span().unwrap(), "invalid suggestion style") - .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") + // Invalid nested attribute + (_, SubdiagnosticKind::Suggestion { .. }) => { + span_err(arg_name_span, "invalid nested attribute") + .help( + "only `style`, `code` and `applicability` are valid nested attributes", + ) .emit(); - has_errors = true; - SuggestionKind::Normal - }); - - suggestion_kind.set_once(value, span); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } + (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { + span_err(arg_name_span, "invalid nested attribute") + .help("only `style` and `applicability` are valid nested attributes") + .emit(); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } + _ => { + span_err(arg_name_span, "no nested attribute expected here").emit(); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } } - // Invalid nested attribute - (_, SubdiagnosticKind::Suggestion { .. }) => { - span_err(path_span, "invalid nested attribute") - .help( - "only `no_span`, `style`, `code` and `applicability` are valid nested attributes", - ) - .emit(); - has_errors = true; - } - (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { - span_err(path_span, "invalid nested attribute") - .help("only `no_span`, `style` and `applicability` are valid nested attributes") - .emit(); - has_errors = true; - } - _ => { - span_err(path_span, "only `no_span` is a valid nested attribute").emit(); - has_errors = true; - } + if input.is_empty() { break } + input.parse::()?; } - - if has_errors { - // Consume the rest of the input to avoid spamming errors - let _ = input.parse::(); - } - Ok(()) })?; @@ -851,7 +825,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::Warn => {} } - Ok(Some(SubdiagnosticVariant { kind, slug, no_span })) + Ok(Some(SubdiagnosticVariant { kind, message })) } } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 8cd6c0264448..e4f43a22738d 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(rustc::default_hash_types)] -#![feature(if_let_guard)] #![feature(never_type)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_tracked_env)] @@ -241,6 +240,15 @@ decl_derive!( applicability)] => diagnostics::subdiagnostic_derive ); +/// This macro creates a translatable `DiagMessage` from a fluent format string. +/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired. +/// +/// This macro statically checks that the message is valid Fluent, but not that variables in the Fluent message actually exist. +#[proc_macro] +pub fn msg(input: TokenStream) -> TokenStream { + diagnostics::msg_macro(input) +} + decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 1ad9bbc3b4b3..5b869dc3409a 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -1,4 +1,5 @@ use proc_macro::TokenStream; +use proc_macro2::Span; use quote::{quote, quote_spanned}; use syn::parse::{Parse, ParseStream, Result}; use syn::punctuated::Punctuated; @@ -62,7 +63,7 @@ impl Parse for Query { // If there are no doc-comments, give at least some idea of what // it does by showing the query description. if doc_comments.is_empty() { - doc_comments.push(doc_comment_from_desc(&modifiers.desc.1)?); + doc_comments.push(doc_comment_from_desc(&modifiers.desc.expr_list)?); } Ok(Query { doc_comments, modifiers, name, key, arg, result }) @@ -82,15 +83,27 @@ impl Parse for List { } } +struct Desc { + modifier: Ident, + tcx_binding: Option, + expr_list: Punctuated, +} + +struct CacheOnDiskIf { + modifier: Ident, + tcx_binding: Option, + block: Block, +} + struct QueryModifiers { /// The description of the query. - desc: (Option, Punctuated), + desc: Desc, /// Use this type for the in-memory cache. arena_cache: Option, /// Cache the query to disk if the `Block` returns true. - cache: Option<(Option, Block)>, + cache_on_disk_if: Option, /// A cycle error for this query aborting the compilation with a fatal error. cycle_fatal: Option, @@ -134,7 +147,7 @@ struct QueryModifiers { fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut arena_cache = None; - let mut cache = None; + let mut cache_on_disk_if = None; let mut desc = None; let mut cycle_fatal = None; let mut cycle_delay_bug = None; @@ -164,7 +177,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { // `desc { |tcx| "foo {}", tcx.item_path(key) }` let attr_content; braced!(attr_content in input); - let tcx = if attr_content.peek(Token![|]) { + let tcx_binding = if attr_content.peek(Token![|]) { attr_content.parse::()?; let tcx = attr_content.parse()?; attr_content.parse::()?; @@ -172,12 +185,15 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { } else { None }; - let list = attr_content.parse_terminated(Expr::parse, Token![,])?; - try_insert!(desc = (tcx, list)); + let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?; + try_insert!(desc = Desc { modifier, tcx_binding, expr_list }); } else if modifier == "cache_on_disk_if" { - // Parse a cache modifier like: - // `cache(tcx) { |tcx| key.is_local() }` - let args = if input.peek(token::Paren) { + // Parse a cache-on-disk modifier like: + // + // `cache_on_disk_if { true }` + // `cache_on_disk_if { key.is_local() }` + // `cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }` + let tcx_binding = if input.peek(token::Paren) { let args; parenthesized!(args in input); let tcx = Pat::parse_single(&args)?; @@ -186,7 +202,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { None }; let block = input.parse()?; - try_insert!(cache = (args, block)); + try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, tcx_binding, block }); } else if modifier == "arena_cache" { try_insert!(arena_cache = modifier); } else if modifier == "cycle_fatal" { @@ -218,7 +234,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { }; Ok(QueryModifiers { arena_cache, - cache, + cache_on_disk_if, desc, cycle_fatal, cycle_delay_bug, @@ -260,13 +276,104 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(#tcx: TyCtxt<'tcx>, #key: &crate::queries::#name::Key<'tcx>) -> bool + #block + }); + } + + let Desc { tcx_binding, expr_list, .. } = &modifiers.desc; + let tcx = tcx_binding.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t }); + + let desc = quote! { + #[allow(unused_variables)] + pub fn #erased_name<'tcx>(tcx: TyCtxt<'tcx>, key: #arg) -> String { + let (#tcx, #key) = (tcx, key); + format!(#expr_list) + } + }; + + streams.description_fns_stream.extend(quote! { + #desc + }); +} + +/// Add hints for rust-analyzer +fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::TokenStream) { + // Add links to relevant modifiers + + let modifiers = &query.modifiers; + + let mut modifiers_stream = quote! {}; + + let name = &modifiers.desc.modifier; + modifiers_stream.extend(quote! { + crate::query::modifiers::#name; + }); + + if let Some(CacheOnDiskIf { modifier, .. }) = &modifiers.cache_on_disk_if { + modifiers_stream.extend(quote! { + crate::query::modifiers::#modifier; + }); + } + + macro_rules! doc_link { + ( $( $modifier:ident ),+ $(,)? ) => { + $( + if let Some(name) = &modifiers.$modifier { + modifiers_stream.extend(quote! { + crate::query::modifiers::#name; + }); + } + )+ + } + } + + doc_link!( + arena_cache, + cycle_fatal, + cycle_delay_bug, + cycle_stash, + no_hash, + anon, + eval_always, + depth_limit, + separate_provide_extern, + feedable, + return_result_from_ensure_ok, + ); + + let name = &query.name; + + // Replace span for `name` to make rust-analyzer ignore it. + let mut erased_name = name.clone(); + erased_name.set_span(Span::call_site()); + + let result = &query.result; // This dead code exists to instruct rust-analyzer about the link between the `rustc_queries` // query names and the corresponding produced provider. The issue is that by nature of this @@ -280,51 +387,13 @@ fn add_query_desc_cached_impl( let crate::query::Providers { #name: _, .. }; }; - // Find out if we should cache the query on disk - let cache = if let Some((args, expr)) = modifiers.cache.as_ref() { - let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ }); - // expr is a `Block`, meaning that `{ #expr }` gets expanded - // to `{ { stmts... } }`, which triggers the `unused_braces` lint. - // we're taking `key` by reference, but some rustc types usually prefer being passed by value - quote! { - #[allow(unused_variables, unused_braces, rustc::pass_by_value)] - #[inline] - pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool { - #ra_hint - #expr - } + analyzer_stream.extend(quote! { + #[inline(always)] + fn #erased_name<'tcx>() #result { + #ra_hint + #modifiers_stream + loop {} } - } else { - quote! { - // we're taking `key` by reference, but some rustc types usually prefer being passed by value - #[allow(rustc::pass_by_value)] - #[inline] - pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool { - #ra_hint - false - } - } - }; - - let (tcx, desc) = &modifiers.desc; - let tcx = tcx.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t }); - - let desc = quote! { - #[allow(unused_variables)] - pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String { - let (#tcx, #key) = (tcx, key); - ::rustc_middle::ty::print::with_no_trimmed_paths!( - format!(#desc) - ) - } - }; - - descs.extend(quote! { - #desc - }); - - cached.extend(quote! { - #cache }); } @@ -332,9 +401,9 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { let queries = parse_macro_input!(input as List); let mut query_stream = quote! {}; - let mut query_description_stream = quote! {}; - let mut query_cached_stream = quote! {}; + let mut helpers = HelperTokenStreams::default(); let mut feedable_queries = quote! {}; + let mut analyzer_stream = quote! {}; let mut errors = quote! {}; macro_rules! assert { @@ -373,14 +442,17 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { no_hash, anon, eval_always, + feedable, depth_limit, separate_provide_extern, return_result_from_ensure_ok, ); - // Pass on the cache modifier - if modifiers.cache.is_some() { - attributes.push(quote! { (cache) }); + // If there was a `cache_on_disk_if` modifier in the real input, pass + // on a synthetic `(cache_on_disk)` modifier that can be inspected by + // macro-rules macros. + if modifiers.cache_on_disk_if.is_some() { + attributes.push(quote! { (cache_on_disk) }); } // This uses the span of the query definition for the commas, @@ -414,9 +486,12 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { }); } - add_query_desc_cached_impl(&query, &mut query_description_stream, &mut query_cached_stream); + add_to_analyzer_stream(&query, &mut analyzer_stream); + make_helpers_for_query(&query, &mut helpers); } + let HelperTokenStreams { description_fns_stream, cache_on_disk_if_fns_stream } = helpers; + TokenStream::from(quote! { /// Higher-order macro that invokes the specified macro with a prepared /// list of all query signatures (including modifiers). @@ -444,14 +519,32 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { $macro!(#feedable_queries); } } - pub mod descs { + + // Add hints for rust-analyzer + mod _analyzer_hints { use super::*; - #query_description_stream + #analyzer_stream } - pub mod cached { + + /// Functions that format a human-readable description of each query + /// and its key, as specified by the `desc` query modifier. + /// + /// (The leading `_` avoids collisions with actual query names when + /// expanded in `rustc_middle::queries`, and makes this macro-generated + /// module easier to search for.) + pub mod _description_fns { use super::*; - #query_cached_stream + #description_fns_stream } + + // FIXME(Zalathar): Instead of declaring these functions directly, can + // we put them in a macro and then expand that macro downstream in + // `rustc_query_impl`, where the functions are actually used? + pub mod _cache_on_disk_if_fns { + use super::*; + #cache_on_disk_if_fns_stream + } + #errors }) } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 1b40d9f684ef..3a70ee130c27 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -15,7 +15,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl deleted file mode 100644 index fac7b6c21f60..000000000000 --- a/compiler/rustc_metadata/messages.ftl +++ /dev/null @@ -1,240 +0,0 @@ -metadata_async_drop_types_in_dependency = - found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` - .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used - -metadata_bad_panic_strategy = - the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}` - -metadata_binary_output_to_tty = - option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty - -metadata_cannot_find_crate = - can't find crate for `{$crate_name}`{$add_info} - -metadata_cant_find_crate = - can't find crate - -metadata_compiler_missing_profiler = - the compiler may have been built without the profiler runtime - -metadata_conflicting_alloc_error_handler = - the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name} - -metadata_conflicting_global_alloc = - the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} - -metadata_consider_adding_std = - consider adding the standard library to the sysroot with `x build library --target {$locator_triple}` - -metadata_consider_building_std = - consider building the standard library from source with `cargo build -Zbuild-std` - -metadata_consider_downloading_target = - consider downloading the target with `rustup target add {$locator_triple}` - -metadata_crate_dep_multiple = - cannot satisfy dependencies so `{$crate_name}` only shows up once - .help = having upstream crates all available in one format will likely make this go away - -metadata_crate_dep_not_static = - `{$crate_name}` was unavailable as a static crate, preventing fully static linking - -metadata_crate_dep_rustc_driver = - `feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library - -metadata_crate_location_unknown_type = - extern location for {$crate_name} is of an unknown type: {$path} - -metadata_crate_not_compiler_builtins = - the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]` - -metadata_crate_not_panic_runtime = - the crate `{$crate_name}` is not a panic runtime - -metadata_dl_error = - {$path}{$err} - -metadata_empty_renaming_target = - an empty renaming target was specified for library `{$lib_name}` - -metadata_extern_location_not_exist = - extern location for {$crate_name} does not exist: {$location} - -metadata_extern_location_not_file = - extern location for {$crate_name} is not a file: {$location} - -metadata_fail_create_file_encoder = - failed to create file encoder: {$err} - -metadata_fail_write_file = - failed to write to `{$path}`: {$err} - -metadata_failed_copy_to_stdout = - failed to copy {$filename} to stdout: {$err} - -metadata_failed_create_encoded_metadata = - failed to create encoded metadata from file: {$err} - -metadata_failed_create_file = - failed to create the file {$filename}: {$err} - -metadata_failed_create_tempdir = - couldn't create a temp dir: {$err} - -metadata_failed_write_error = - failed to write {$filename}: {$err} - -metadata_found_crate_versions = - the following crate versions were found:{$found_crates} - -metadata_found_staticlib = - found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} - .help = please recompile that crate using --crate-type lib - -metadata_full_metadata_not_found = - only metadata stub found for `{$flavor}` dependency `{$crate_name}` - please provide path to the corresponding .rmeta file with full metadata - -metadata_global_alloc_required = - no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait - -metadata_incompatible_panic_in_drop_strategy = - the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` - -metadata_incompatible_rustc = - found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info} - .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first) - -metadata_incompatible_target_modifiers = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely -metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error -metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_help_fix_l_missed = set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_help_fix_r_missed = unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_l_missed = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely -metadata_incompatible_target_modifiers_r_missed = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely - -metadata_incompatible_with_immediate_abort = - the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort` - -metadata_incompatible_with_immediate_abort_core = - the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort` - .help = consider building the standard library from source with `cargo build -Zbuild-std` - -metadata_install_missing_components = - maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` - -metadata_invalid_meta_files = - found invalid metadata files for crate `{$crate_name}`{$add_info} - -metadata_lib_filename_form = - file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix} - -metadata_lib_framework_apple = - library kind `framework` is only supported on Apple targets - -metadata_lib_required = - crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form - -metadata_link_ordinal_raw_dylib = - `#[link_ordinal]` is only supported if link kind is `raw-dylib` - -metadata_missing_native_library = - could not find native static library `{$libname}`, perhaps an -L flag is missing? - -metadata_multiple_candidates = - multiple candidates for `{$flavor}` dependency `{$crate_name}` found - -metadata_multiple_renamings = - multiple renamings were specified for library `{$lib_name}` - -metadata_newer_crate_version = - found possibly newer version of crate `{$crate_name}`{$add_info} - .note = perhaps that crate needs to be recompiled? - -metadata_no_crate_with_triple = - couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info} - -metadata_no_link_mod_override = - overriding linking modifiers from command line is not supported - -metadata_no_multiple_alloc_error_handler = - cannot define multiple allocation error handlers - .label = cannot define a new allocation error handler - -metadata_no_multiple_global_alloc = - cannot define multiple global allocators - .label = cannot define a new global allocator - -metadata_no_panic_strategy = - the crate `{$crate_name}` does not have the panic strategy `{$strategy}` - -metadata_no_transitive_needs_dep = - the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` - -metadata_non_ascii_name = - cannot load a crate with a non-ascii name `{$crate_name}` - -metadata_not_profiler_runtime = - the crate `{$crate_name}` is not a profiler runtime - -metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename - -metadata_prev_alloc_error_handler = - previous allocation error handler defined here - -metadata_prev_global_alloc = - previous global allocator defined here - -metadata_raw_dylib_malformed = - link name must be well-formed if link kind is `raw-dylib` -metadata_raw_dylib_unsupported_abi = - ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture - -metadata_renaming_no_link = - renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library - -metadata_required_panic_strategy = - the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` - -metadata_rlib_required = - crate `{$crate_name}` required to be available in rlib format, but was not found in this form - -metadata_rustc_lib_required = - crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form - .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver` - .help = try adding `extern crate rustc_driver;` at the top level of this crate - -metadata_stable_crate_id_collision = - found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values - -metadata_std_required = - `std` is required by `{$current_crate}` because it does not declare `#![no_std]` - -metadata_symbol_conflicts_current = - the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two - -metadata_target_no_std_support = - the `{$locator_triple}` target may not support the standard library - -metadata_target_not_installed = - the `{$locator_triple}` target may not be installed - -metadata_two_panic_runtimes = - cannot link together two panic runtimes: {$prev_name} and {$cur_name} - -metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}` - -metadata_wasm_c_abi = - older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index d30e8120993f..a74d387ad5a4 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -68,8 +68,7 @@ use crate::creader::CStore; use crate::errors::{ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired, - NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired, - TwoPanicRuntimes, + NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, }; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { @@ -318,7 +317,7 @@ fn add_library( .drain(..) .map(|cnum| NonStaticCrateDep { crate_name_: tcx.crate_name(cnum) }) .collect(), - rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp), + rustc_driver_help: linking_to_rustc_driver, }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 8eb4fad078fe..7320ad98d113 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -2,73 +2,78 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, TargetTuple}; -use crate::fluent_generated as fluent; use crate::locator::CrateFlavor; #[derive(Diagnostic)] -#[diag(metadata_rlib_required)] +#[diag( + "crate `{$crate_name}` required to be available in rlib format, but was not found in this form" +)] pub struct RlibRequired { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_lib_required)] +#[diag( + "crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form" +)] pub struct LibRequired<'a> { pub crate_name: Symbol, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_rustc_lib_required)] -#[help] +#[diag( + "crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form" +)] +#[help("try adding `extern crate rustc_driver;` at the top level of this crate")] pub struct RustcLibRequired<'a> { pub crate_name: Symbol, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_crate_dep_multiple)] -#[help] +#[diag("cannot satisfy dependencies so `{$crate_name}` only shows up once")] +#[help("having upstream crates all available in one format will likely make this go away")] pub struct CrateDepMultiple { pub crate_name: Symbol, #[subdiagnostic] pub non_static_deps: Vec, - #[subdiagnostic] - pub rustc_driver_help: Option, + #[help("`feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library")] + pub rustc_driver_help: bool, } #[derive(Subdiagnostic)] -#[note(metadata_crate_dep_not_static)] +#[note("`{$crate_name}` was unavailable as a static crate, preventing fully static linking")] pub struct NonStaticCrateDep { /// It's different from `crate_name` in main Diagnostic. pub crate_name_: Symbol, } -#[derive(Subdiagnostic)] -#[help(metadata_crate_dep_rustc_driver)] -pub struct RustcDriverHelp; - #[derive(Diagnostic)] -#[diag(metadata_two_panic_runtimes)] +#[diag("cannot link together two panic runtimes: {$prev_name} and {$cur_name}")] pub struct TwoPanicRuntimes { pub prev_name: Symbol, pub cur_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_bad_panic_strategy)] +#[diag( + "the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`" +)] pub struct BadPanicStrategy { pub runtime: Symbol, pub strategy: PanicStrategy, } #[derive(Diagnostic)] -#[diag(metadata_required_panic_strategy)] +#[diag( + "the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`" +)] pub struct RequiredPanicStrategy { pub crate_name: Symbol, pub found_strategy: PanicStrategy, @@ -76,17 +81,23 @@ pub struct RequiredPanicStrategy { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_with_immediate_abort)] +#[diag( + "the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort`" +)] pub struct IncompatibleWithImmediateAbort { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_incompatible_with_immediate_abort_core)] +#[diag( + "the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`" +)] pub struct IncompatibleWithImmediateAbortCore; #[derive(Diagnostic)] -#[diag(metadata_incompatible_panic_in_drop_strategy)] +#[diag( + "the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`" +)] pub struct IncompatiblePanicInDropStrategy { pub crate_name: Symbol, pub found_strategy: PanicStrategy, @@ -94,126 +105,138 @@ pub struct IncompatiblePanicInDropStrategy { } #[derive(Diagnostic)] -#[diag(metadata_link_ordinal_raw_dylib)] +#[diag("`#[link_ordinal]` is only supported if link kind is `raw-dylib`")] pub struct LinkOrdinalRawDylib { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_lib_framework_apple)] +#[diag("library kind `framework` is only supported on Apple targets")] pub struct LibFrameworkApple; #[derive(Diagnostic)] -#[diag(metadata_empty_renaming_target)] +#[diag("an empty renaming target was specified for library `{$lib_name}`")] pub struct EmptyRenamingTarget<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_renaming_no_link)] +#[diag( + "renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library" +)] pub struct RenamingNoLink<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_multiple_renamings)] +#[diag("multiple renamings were specified for library `{$lib_name}`")] pub struct MultipleRenamings<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_no_link_mod_override)] +#[diag("overriding linking modifiers from command line is not supported")] pub struct NoLinkModOverride { #[primary_span] pub span: Option, } #[derive(Diagnostic)] -#[diag(metadata_raw_dylib_unsupported_abi)] +#[diag("ABI not supported by `#[link(kind = \"raw-dylib\")]` on this architecture")] pub struct RawDylibUnsupportedAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_fail_create_file_encoder)] +#[diag("failed to create file encoder: {$err}")] pub struct FailCreateFileEncoder { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_fail_write_file)] +#[diag("failed to write to `{$path}`: {$err}")] pub struct FailWriteFile<'a> { pub path: &'a Path, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_crate_not_panic_runtime)] +#[diag("the crate `{$crate_name}` is not a panic runtime")] pub struct CrateNotPanicRuntime { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_crate_not_compiler_builtins)] +#[diag( + "the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]`" +)] pub struct CrateNotCompilerBuiltins { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_no_panic_strategy)] +#[diag("the crate `{$crate_name}` does not have the panic strategy `{$strategy}`")] pub struct NoPanicStrategy { pub crate_name: Symbol, pub strategy: PanicStrategy, } #[derive(Diagnostic)] -#[diag(metadata_not_profiler_runtime)] +#[diag("the crate `{$crate_name}` is not a profiler runtime")] pub struct NotProfilerRuntime { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_no_multiple_global_alloc)] +#[diag("cannot define multiple global allocators")] pub struct NoMultipleGlobalAlloc { #[primary_span] - #[label] + #[label("cannot define a new global allocator")] pub span2: Span, - #[label(metadata_prev_global_alloc)] + #[label("previous global allocator defined here")] pub span1: Span, } #[derive(Diagnostic)] -#[diag(metadata_no_multiple_alloc_error_handler)] +#[diag("cannot define multiple allocation error handlers")] pub struct NoMultipleAllocErrorHandler { #[primary_span] - #[label] + #[label("cannot define a new allocation error handler")] pub span2: Span, - #[label(metadata_prev_alloc_error_handler)] + #[label("previous allocation error handler defined here")] pub span1: Span, } #[derive(Diagnostic)] -#[diag(metadata_conflicting_global_alloc)] +#[diag( + "the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}" +)] pub struct ConflictingGlobalAlloc { pub crate_name: Symbol, pub other_crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_conflicting_alloc_error_handler)] +#[diag( + "the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}" +)] pub struct ConflictingAllocErrorHandler { pub crate_name: Symbol, pub other_crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_global_alloc_required)] +#[diag( + "no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait" +)] pub struct GlobalAllocRequired; #[derive(Diagnostic)] -#[diag(metadata_no_transitive_needs_dep)] +#[diag( + "the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`" +)] pub struct NoTransitiveNeedsDep<'a> { pub crate_name: Symbol, pub needs_crate_name: &'a str, @@ -221,25 +244,27 @@ pub struct NoTransitiveNeedsDep<'a> { } #[derive(Diagnostic)] -#[diag(metadata_failed_write_error)] +#[diag("failed to write {$filename}: {$err}")] pub struct FailedWriteError { pub filename: PathBuf, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_copy_to_stdout)] +#[diag("failed to copy {$filename} to stdout: {$err}")] pub struct FailedCopyToStdout { pub filename: PathBuf, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_binary_output_to_tty)] +#[diag( + "option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty" +)] pub struct BinaryOutputToTty; #[derive(Diagnostic)] -#[diag(metadata_missing_native_library)] +#[diag("could not find native static library `{$libname}`, perhaps an -L flag is missing?")] pub struct MissingNativeLibrary<'a> { libname: &'a str, #[subdiagnostic] @@ -273,32 +298,32 @@ impl<'a> MissingNativeLibrary<'a> { } #[derive(Subdiagnostic)] -#[help(metadata_only_provide_library_name)] +#[help("only provide the library name `{$suggested_name}`, not the full filename")] pub struct SuggestLibraryName<'a> { suggested_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_tempdir)] +#[diag("couldn't create a temp dir: {$err}")] pub struct FailedCreateTempdir { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_file)] +#[diag("failed to create the file {$filename}: {$err}")] pub struct FailedCreateFile<'a> { pub filename: &'a Path, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_encoded_metadata)] +#[diag("failed to create encoded metadata from file: {$err}")] pub struct FailedCreateEncodedMetadata { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_non_ascii_name)] +#[diag("cannot load a crate with a non-ascii name `{$crate_name}`")] pub struct NonAsciiName { #[primary_span] pub span: Span, @@ -306,7 +331,7 @@ pub struct NonAsciiName { } #[derive(Diagnostic)] -#[diag(metadata_extern_location_not_exist)] +#[diag("extern location for {$crate_name} does not exist: {$location}")] pub struct ExternLocationNotExist<'a> { #[primary_span] pub span: Span, @@ -315,7 +340,7 @@ pub struct ExternLocationNotExist<'a> { } #[derive(Diagnostic)] -#[diag(metadata_extern_location_not_file)] +#[diag("extern location for {$crate_name} is not a file: {$location}")] pub struct ExternLocationNotFile<'a> { #[primary_span] pub span: Span, @@ -332,7 +357,11 @@ pub(crate) struct MultipleCandidates { impl Diagnostic<'_, G> for MultipleCandidates { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_multiple_candidates); + let mut diag = Diag::new( + dcx, + level, + msg!("multiple candidates for `{$flavor}` dependency `{$crate_name}` found"), + ); diag.arg("crate_name", self.crate_name); diag.arg("flavor", self.flavor); diag.code(E0464); @@ -345,7 +374,9 @@ impl Diagnostic<'_, G> for MultipleCandidates { } #[derive(Diagnostic)] -#[diag(metadata_full_metadata_not_found)] +#[diag( + "only metadata stub found for `{$flavor}` dependency `{$crate_name}` please provide path to the corresponding .rmeta file with full metadata" +)] pub(crate) struct FullMetadataNotFound { #[primary_span] pub span: Span, @@ -354,7 +385,7 @@ pub(crate) struct FullMetadataNotFound { } #[derive(Diagnostic)] -#[diag(metadata_symbol_conflicts_current, code = E0519)] +#[diag("the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two", code = E0519)] pub struct SymbolConflictsCurrent { #[primary_span] pub span: Span, @@ -362,7 +393,7 @@ pub struct SymbolConflictsCurrent { } #[derive(Diagnostic)] -#[diag(metadata_stable_crate_id_collision)] +#[diag("found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values")] pub struct StableCrateIdCollision { #[primary_span] pub span: Span, @@ -371,7 +402,7 @@ pub struct StableCrateIdCollision { } #[derive(Diagnostic)] -#[diag(metadata_dl_error)] +#[diag("{$path}{$err}")] pub struct DlError { #[primary_span] pub span: Span, @@ -380,9 +411,9 @@ pub struct DlError { } #[derive(Diagnostic)] -#[diag(metadata_newer_crate_version, code = E0460)] -#[note] -#[note(metadata_found_crate_versions)] +#[diag("found possibly newer version of crate `{$crate_name}`{$add_info}", code = E0460)] +#[note("perhaps that crate needs to be recompiled?")] +#[note("the following crate versions were found:{$found_crates}")] pub struct NewerCrateVersion { #[primary_span] pub span: Span, @@ -392,8 +423,8 @@ pub struct NewerCrateVersion { } #[derive(Diagnostic)] -#[diag(metadata_no_crate_with_triple, code = E0461)] -#[note(metadata_found_crate_versions)] +#[diag("couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}", code = E0461)] +#[note("the following crate versions were found:{$found_crates}")] pub struct NoCrateWithTriple<'a> { #[primary_span] pub span: Span, @@ -404,9 +435,9 @@ pub struct NoCrateWithTriple<'a> { } #[derive(Diagnostic)] -#[diag(metadata_found_staticlib, code = E0462)] -#[note(metadata_found_crate_versions)] -#[help] +#[diag("found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}", code = E0462)] +#[note("the following crate versions were found:{$found_crates}")] +#[help("please recompile that crate using --crate-type lib")] pub struct FoundStaticlib { #[primary_span] pub span: Span, @@ -416,9 +447,11 @@ pub struct FoundStaticlib { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_rustc, code = E0514)] -#[note(metadata_found_crate_versions)] -#[help] +#[diag("found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}", code = E0514)] +#[note("the following crate versions were found:{$found_crates}")] +#[help( + "please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)" +)] pub struct IncompatibleRustc { #[primary_span] pub span: Span, @@ -438,7 +471,11 @@ pub struct InvalidMetadataFiles { impl Diagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_invalid_meta_files); + let mut diag = Diag::new( + dcx, + level, + msg!("found invalid metadata files for crate `{$crate_name}`{$add_info}"), + ); diag.arg("crate_name", self.crate_name); diag.arg("add_info", self.add_info); diag.code(E0786); @@ -466,7 +503,8 @@ pub struct CannotFindCrate { impl Diagnostic<'_, G> for CannotFindCrate { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_cannot_find_crate); + let mut diag = + Diag::new(dcx, level, msg!("can't find crate for `{$crate_name}`{$add_info}")); diag.arg("crate_name", self.crate_name); diag.arg("current_crate", self.current_crate); diag.arg("add_info", self.add_info); @@ -475,9 +513,11 @@ impl Diagnostic<'_, G> for CannotFindCrate { diag.span(self.span); if self.crate_name == sym::std || self.crate_name == sym::core { if self.missing_core { - diag.note(fluent::metadata_target_not_installed); + diag.note(msg!("the `{$locator_triple}` target may not be installed")); } else { - diag.note(fluent::metadata_target_no_std_support); + diag.note(msg!( + "the `{$locator_triple}` target may not support the standard library" + )); } let has_precompiled_std = !self.is_tier_3; @@ -485,12 +525,14 @@ impl Diagnostic<'_, G> for CannotFindCrate { if self.missing_core { if env!("CFG_RELEASE_CHANNEL") == "dev" && !self.is_ui_testing { // Note: Emits the nicer suggestion only for the dev channel. - diag.help(fluent::metadata_consider_adding_std); + diag.help(msg!("consider adding the standard library to the sysroot with `x build library --target {$locator_triple}`")); } else if has_precompiled_std { // NOTE: this suggests using rustup, even though the user may not have it installed. // That's because they could choose to install it; or this may give them a hint which // target they need to install from their distro. - diag.help(fluent::metadata_consider_downloading_target); + diag.help(msg!( + "consider downloading the target with `rustup target add {$locator_triple}`" + )); } } @@ -499,25 +541,25 @@ impl Diagnostic<'_, G> for CannotFindCrate { // If it's not a dummy, that means someone added `extern crate std` explicitly and // `#![no_std]` won't help. if !self.missing_core && self.span.is_dummy() { - diag.note(fluent::metadata_std_required); + diag.note(msg!("`std` is required by `{$current_crate}` because it does not declare `#![no_std]`")); } // Recommend -Zbuild-std even on stable builds for Tier 3 targets because // it's the recommended way to use the target, the user should switch to nightly. if self.is_nightly_build || !has_precompiled_std { - diag.help(fluent::metadata_consider_building_std); + diag.help(msg!("consider building the standard library from source with `cargo build -Zbuild-std`")); } } else if self.crate_name == self.profiler_runtime { - diag.note(fluent::metadata_compiler_missing_profiler); + diag.note(msg!("the compiler may have been built without the profiler runtime")); } else if self.crate_name.as_str().starts_with("rustc_") { - diag.help(fluent::metadata_install_missing_components); + diag.help(msg!("maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`")); } - diag.span_label(self.span, fluent::metadata_cant_find_crate); + diag.span_label(self.span, msg!("can't find crate")); diag } } #[derive(Diagnostic)] -#[diag(metadata_crate_location_unknown_type)] +#[diag("extern location for {$crate_name} is of an unknown type: {$path}")] pub struct CrateLocationUnknownType<'a> { #[primary_span] pub span: Span, @@ -526,7 +568,7 @@ pub struct CrateLocationUnknownType<'a> { } #[derive(Diagnostic)] -#[diag(metadata_lib_filename_form)] +#[diag("file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}")] pub struct LibFilenameForm<'a> { #[primary_span] pub span: Span, @@ -535,18 +577,28 @@ pub struct LibFilenameForm<'a> { } #[derive(Diagnostic)] -#[diag(metadata_wasm_c_abi)] +#[diag( + "older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88" +)] pub(crate) struct WasmCAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "`{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`" +)] +#[help( + "set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiers { #[primary_span] pub span: Span, @@ -559,11 +611,19 @@ pub struct IncompatibleTargetModifiers { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers_l_missed)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`" +)] +#[help( + "set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiersLMissed { #[primary_span] pub span: Span, @@ -575,11 +635,19 @@ pub struct IncompatibleTargetModifiersLMissed { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers_r_missed)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "`{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`" +)] +#[help( + "unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiersRMissed { #[primary_span] pub span: Span, @@ -591,7 +659,9 @@ pub struct IncompatibleTargetModifiersRMissed { } #[derive(Diagnostic)] -#[diag(metadata_unknown_target_modifier_unsafe_allowed)] +#[diag( + "unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`" +)] pub struct UnknownTargetModifierUnsafeAllowed { #[primary_span] pub span: Span, @@ -599,8 +669,12 @@ pub struct UnknownTargetModifierUnsafeAllowed { } #[derive(Diagnostic)] -#[diag(metadata_async_drop_types_in_dependency)] -#[help] +#[diag( + "found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`" +)] +#[help( + "if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used" +)] pub struct AsyncDropTypesInDependency { #[primary_span] pub span: Span, @@ -609,7 +683,7 @@ pub struct AsyncDropTypesInDependency { } #[derive(Diagnostic)] -#[diag(metadata_raw_dylib_malformed)] +#[diag("link name must be well-formed if link kind is `raw-dylib`")] pub struct RawDylibMalformed { #[primary_span] pub span: Span, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index f3b738f93d2d..73a97a67bc90 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(decl_macro)] #![feature(error_iter)] #![feature(file_buffered)] #![feature(gen_blocks)] @@ -34,5 +33,3 @@ pub use native_libs::{ try_find_native_static_library, walk_native_lib_search_dirs, }; pub use rmeta::{EncodedMetadata, METADATA_HEADER, encode_metadata, rendered_const}; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index b160b3fe9bb3..0c06d1be9a3f 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -161,7 +161,7 @@ fn find_bundled_library( tcx: TyCtxt<'_>, ) -> Option { let sess = tcx.sess; - if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind + if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive, .. } = kind && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib)) && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c7423386a771..bd5b3893e4e8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1298,10 +1298,6 @@ impl<'a> CrateMetadataRef<'a> { } } - fn is_ctfe_mir_available(self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { - self.root.tables.mir_for_ctfe.get((self, tcx), id).is_some() - } - fn is_item_mir_available(self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { self.root.tables.optimized_mir.get((self, tcx), id).is_some() } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7bd3f7db55f9..6ea9a2852804 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -11,7 +11,8 @@ use rustc_middle::bug; use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; -use rustc_middle::query::{ExternProviders, LocalCrate}; +use rustc_middle::queries::ExternProviders; +use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; @@ -134,8 +135,8 @@ macro_rules! provide_one { ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => { fn $name<'tcx>( $tcx: TyCtxt<'tcx>, - def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>, - ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> { + def_id_arg: rustc_middle::queries::$name::Key<'tcx>, + ) -> rustc_middle::queries::$name::ProvidedValue<'tcx> { let _prof_timer = $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name))); @@ -323,7 +324,6 @@ provide! { tcx, def_id, other, cdata, inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } attrs_for_def => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(tcx, def_id.index)) } is_mir_available => { cdata.is_item_mir_available(tcx, def_id.index) } - is_ctfe_mir_available => { cdata.is_ctfe_mir_available(tcx, def_id.index) } cross_crate_inlinable => { table_direct } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } @@ -418,6 +418,7 @@ provide! { tcx, def_id, other, cdata, } anon_const_kind => { table } const_of_item => { table } + is_rhs_type_const => { table } } pub(in crate::rmeta) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 471c19ed4d4e..3a85b0a05052 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; -use rustc_data_structures::sync::{join, par_for_each_in}; +use rustc_data_structures::sync::{par_for_each_in, par_join}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::thousands::usize_with_underscores; use rustc_feature::Features; @@ -1102,12 +1102,8 @@ fn should_encode_mir( def_id: LocalDefId, ) -> (bool, bool) { match tcx.def_kind(def_id) { - // Constructors - DefKind::Ctor(_, _) => { - let mir_opt_base = tcx.sess.opts.output_types.should_codegen() - || tcx.sess.opts.unstable_opts.always_encode_mir; - (true, mir_opt_base) - } + // instance_mir uses mir_for_ctfe rather than optimized_mir for constructors + DefKind::Ctor(_, _) => (true, false), // Constants DefKind::AnonConst | DefKind::InlineConst | DefKind::AssocConst | DefKind::Const => { (true, false) @@ -1117,11 +1113,10 @@ fn should_encode_mir( DefKind::SyntheticCoroutineBody => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { - let generics = tcx.generics_of(def_id); let opt = tcx.sess.opts.unstable_opts.always_encode_mir || (tcx.sess.opts.output_types.should_codegen() && reachable_set.contains(&def_id) - && (generics.requires_monomorphization(tcx) + && (tcx.generics_of(def_id).requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); // The function has a `const` modifier or is in a `const trait`. let is_const_fn = tcx.is_const_fn(def_id.to_def_id()); @@ -1444,7 +1439,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | hir::ConstArgKind::TupleCall(..) | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Path(..) - | hir::ConstArgKind::Literal(..) + | hir::ConstArgKind::Literal { .. } | hir::ConstArgKind::Infer(..) => true, hir::ConstArgKind::Anon(..) => false, }, @@ -1635,6 +1630,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let table = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id); record!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table); } + if let DefKind::AssocConst | DefKind::Const = def_kind { + record!(self.tables.is_rhs_type_const[def_id] <- self.tcx.is_rhs_type_const(def_id)); + } } for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls { @@ -2463,7 +2461,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // Prefetch some queries used by metadata encoding. // This is not necessary for correctness, but is only done for performance reasons. // It can be removed if it turns out to cause trouble or be detrimental to performance. - join( + par_join( || prefetch_mir(tcx), || { let _ = tcx.exported_non_generic_symbols(LOCAL_CRATE); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index af6df0cd6eb6..408b50ae48df 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -476,6 +476,7 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, + is_rhs_type_const: Table>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index fbcce16cedca..121e77614725 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" bitflags = "2.4.1" either = "1.5.0" gsgdt = "0.1.2" +parking_lot = "0.12" polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" @@ -18,7 +19,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_messages = { path = "../rustc_error_messages" } # Used for intra-doc links rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl deleted file mode 100644 index b46f43841c8e..000000000000 --- a/compiler/rustc_middle/messages.ftl +++ /dev/null @@ -1,133 +0,0 @@ -middle_assert_async_resume_after_drop = `async fn` resumed after async drop - -middle_assert_async_resume_after_panic = `async fn` resumed after panicking - -middle_assert_async_resume_after_return = `async fn` resumed after completion - -middle_assert_coroutine_resume_after_drop = coroutine resumed after async drop - -middle_assert_coroutine_resume_after_panic = coroutine resumed after panicking - -middle_assert_coroutine_resume_after_return = coroutine resumed after completion - -middle_assert_divide_by_zero = - attempt to divide `{$val}` by zero - -middle_assert_gen_resume_after_drop = `gen` fn or block cannot be further iterated on after it async dropped - -middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked - -middle_assert_invalid_enum_construction = - trying to construct an enum from an invalid value `{$source}` - -middle_assert_misaligned_ptr_deref = - misaligned pointer dereference: address must be a multiple of {$required} but is {$found} - -middle_assert_null_ptr_deref = - null pointer dereference occurred - -middle_assert_op_overflow = - attempt to compute `{$left} {$op} {$right}`, which would overflow - -middle_assert_overflow_neg = - attempt to negate `{$val}`, which would overflow - -middle_assert_remainder_by_zero = - attempt to calculate the remainder of `{$val}` with a divisor of zero - -middle_assert_shl_overflow = - attempt to shift left by `{$val}`, which would overflow - -middle_assert_shr_overflow = - attempt to shift right by `{$val}`, which would overflow - -middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe - -middle_bounds_check = - index out of bounds: the length is {$len} but the index is {$index} - -middle_conflict_types = - this expression supplies two conflicting concrete types for the same opaque type - -middle_consider_type_length_limit = - consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate - -middle_const_eval_non_int = - constant evaluation of enum discriminant resulted in non-integer - -middle_const_not_used_in_type_alias = - const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias - -middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_in_future = use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_suggestion = replace the use of the deprecated {$kind} - -middle_drop_check_overflow = - overflow while adding drop-check rules for `{$ty}` - .note = overflowed on `{$overflow_ty}` - -middle_erroneous_constant = erroneous constant encountered - -middle_failed_writing_file = - failed to write file {$path}: {$error}" - -# Note: We only mention patterns here since the error can only occur with references, and those -# are forbidden in const generics. -middle_invalid_const_in_valtree = constant {$global_const_id} cannot be used as pattern - .note = constants that reference mutable or external memory cannot be used as patterns - -middle_layout_cycle = - a cycle occurred during layout computation - -middle_layout_normalization_failure = - unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized - -middle_layout_references_error = - the type has an unknown layout - -middle_layout_simd_too_many = - the SIMD type `{$ty}` has more elements than the limit {$max_lanes} - -middle_layout_simd_zero_length = - the SIMD type `{$ty}` has zero elements - -middle_layout_size_overflow = - values of the type `{$ty}` are too big for the target architecture - -middle_layout_too_generic = the type `{$ty}` does not have a fixed layout - -middle_layout_unknown = - the type `{$ty}` has an unknown layout - -middle_max_num_nodes_in_valtree = maximum number of nodes exceeded in constant {$global_const_id} - -middle_opaque_hidden_type_mismatch = - concrete type differs from previous defining opaque type use - .label = expected `{$self_ty}`, got `{$other_ty}` - -middle_previous_use_here = - previous use here - -middle_recursion_limit_reached = - reached the recursion limit finding the struct tail for `{$ty}` - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` - -middle_requires_lang_item = requires `{$name}` lang_item - -middle_strict_coherence_needs_negative_coherence = - to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled - .label = due to this attribute - -middle_type_length_limit = reached the type-length limit while instantiating `{$instance}` - -middle_unsupported_union = we don't support unions yet: '{$ty_name}' diff --git a/compiler/rustc_query_system/src/dep_graph/README.md b/compiler/rustc_middle/src/dep_graph/README.md similarity index 100% rename from compiler/rustc_query_system/src/dep_graph/README.md rename to compiler/rustc_middle/src/dep_graph/README.md diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_middle/src/dep_graph/debug.rs similarity index 100% rename from compiler/rustc_query_system/src/dep_graph/debug.rs rename to compiler/rustc_middle/src/dep_graph/debug.rs diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index f5ed0570667c..0033a1cd2337 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -1,16 +1,333 @@ -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; +//! This module defines the [`DepNode`] type which the compiler uses to represent +//! nodes in the [dependency graph]. A `DepNode` consists of a [`DepKind`] (which +//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.) +//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which +//! depends on the node's `DepKind`. Together, the kind and the fingerprint +//! fully identify a dependency node, even across multiple compilation sessions. +//! In other words, the value of the fingerprint does not depend on anything +//! that is specific to a given compilation session, like an unpredictable +//! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a +//! pointer. The concept behind this could be compared to how git commit hashes +//! uniquely identify a given commit. The fingerprinting approach has +//! a few advantages: +//! +//! * A `DepNode` can simply be serialized to disk and loaded in another session +//! without the need to do any "rebasing" (like we have to do for Spans and +//! NodeIds) or "retracing" (like we had to do for `DefId` in earlier +//! implementations of the dependency graph). +//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to +//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. +//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into +//! memory without any post-processing (e.g., "abomination-style" pointer +//! reconstruction). +//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that +//! refer to things that do not exist anymore. In previous implementations +//! `DepNode` contained a `DefId`. A `DepNode` referring to something that +//! had been removed between the previous and the current compilation session +//! could not be instantiated because the current compilation session +//! contained no `DefId` for thing that had been removed. +//! +//! `DepNode` definition happens in `rustc_middle` with the +//! `define_dep_nodes!()` macro. This macro defines the `DepKind` enum. Each +//! `DepKind` has its own parameters that are needed at runtime in order to +//! construct a valid `DepNode` fingerprint. However, only `CompileCodegenUnit` +//! and `CompileMonoItem` are constructed explicitly (with +//! `make_compile_codegen_unit` and `make_compile_mono_item`). +//! +//! Because the macro sees what parameters a given `DepKind` requires, it can +//! "infer" some properties for each kind of `DepNode`: +//! +//! * Whether a `DepNode` of a given kind has any parameters at all. Some +//! `DepNode`s could represent global concepts with only one value. +//! * Whether it is possible, in principle, to reconstruct a query key from a +//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, +//! in which case it is possible to map the node's fingerprint back to the +//! `DefId` it was computed from. In other cases, too much information gets +//! lost during fingerprint computation. +//! +//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with +//! `DepNode::new()`, ensure that only valid `DepNode` instances can be +//! constructed. For example, the API does not allow for constructing +//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. +//! More generally speaking, it relieves the user of the `DepNode` API of +//! having to know how to compute the expected fingerprint for a given set of +//! node parameters. +//! +//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html + +use std::fmt; +use std::hash::Hash; + +use rustc_data_structures::AtomicRef; +use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; +use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; -use rustc_hir::{HirId, ItemLocalId, OwnerId}; -pub use rustc_query_system::dep_graph::DepNode; -use rustc_query_system::dep_graph::FingerprintStyle; -pub use rustc_query_system::dep_graph::dep_node::DepKind; -pub(crate) use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; +use rustc_macros::{Decodable, Encodable}; +use rustc_query_system::ich::StableHashingContext; use rustc_span::Symbol; +use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex}; use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; +/// 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 + } +} + +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 { + /// 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: DepKind) -> DepNode + where + Tcx: super::DepContext, + { + debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); + DepNode { kind, hash: Fingerprint::ZERO.into() } + } + + pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode + where + Tcx: super::DepContext, + Key: DepNodeKey, + { + let hash = arg.to_fingerprint(tcx); + let dep_node = DepNode { kind, hash: hash.into() }; + + #[cfg(debug_assertions)] + { + if !tcx.fingerprint_style(kind).reconstructible() + && (tcx.sess().opts.unstable_opts.incremental_info + || tcx.sess().opts.unstable_opts.query_dep_graph) + { + tcx.dep_graph().register_dep_node_debug_str(dep_node, || arg.to_debug_str(tcx)); + } + } + + dep_node + } + + /// 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: DepKind) -> Self + where + Tcx: super::DepContext, + { + debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); + DepNode { kind, hash: def_path_hash.0.into() } + } +} + +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 { + (*DEP_NODE_DEBUG)(*self, f) + } +} + +/// Trait for query keys as seen by dependency-node tracking. +pub trait DepNodeKey: fmt::Debug + Sized { + fn fingerprint_style() -> FingerprintStyle; + + /// This method turns a query key into an opaque `Fingerprint` to be used + /// in `DepNode`. + fn to_fingerprint(&self, _: Tcx) -> Fingerprint; + + fn to_debug_str(&self, tcx: Tcx) -> String; + + /// This method tries to recover the query key from the given `DepNode`, + /// something which is needed when forcing `DepNode`s during red-green + /// evaluation. The query system will only call this method if + /// `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; +} + +// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere. +impl DepNodeKey for T +where + T: for<'a> HashStable> + fmt::Debug, +{ + #[inline(always)] + default fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque + } + + #[inline(always)] + default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint { + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + }) + } + + #[inline(always)] + default fn to_debug_str(&self, tcx: Tcx) -> String { + // Make sure to print dep node params with reduced queries since printing + // may themselves call queries, which may lead to (possibly untracked!) + // query cycles. + tcx.with_reduced_queries(|| format!("{self:?}")) + } + + #[inline(always)] + default fn recover(_: Tcx, _: &DepNode) -> Option { + None + } +} + +/// This struct stores function pointers and other metadata for a particular DepKind. +/// +/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value +/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual +/// jump table instead of large matches. +pub struct DepKindVTable { + /// Anonymous queries cannot be replayed from one compiler invocation to the next. + /// When their result is needed, it is recomputed. They are useful for fine-grained + /// dependency tracking, and caching within one compiler invocation. + pub is_anon: bool, + + /// Eval-always queries do not track their dependencies, and are always recomputed, even if + /// their inputs have not changed since the last compiler invocation. The result is still + /// cached within one compiler invocation. + pub is_eval_always: bool, + + /// Indicates whether and how the query key can be recovered from its hashed fingerprint. + /// + /// The [`DepNodeKey`] trait determines the fingerprint style for each key type. + pub fingerprint_style: FingerprintStyle, + + /// The red/green evaluation system will try to mark a specific DepNode in the + /// dependency graph as green by recursively trying to mark the dependencies of + /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` + /// where we don't know if it is red or green and we therefore actually have + /// to recompute its value in order to find out. Since the only piece of + /// information that we have at that point is the `DepNode` we are trying to + /// re-evaluate, we need some way to re-run a query from just that. This is what + /// `force_from_dep_node()` implements. + /// + /// In the general case, a `DepNode` consists of a `DepKind` and an opaque + /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint + /// is usually constructed by computing a stable hash of the query-key that the + /// `DepNode` corresponds to. Consequently, it is not in general possible to go + /// back from hash to query-key (since hash functions are not reversible). For + /// this reason `force_from_dep_node()` is expected to fail from time to time + /// because we just cannot find out, from the `DepNode` alone, what the + /// corresponding query-key is and therefore cannot re-run the query. + /// + /// The system deals with this case letting `try_mark_green` fail which forces + /// the root query to be re-evaluated. + /// + /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. + /// Fortunately, we can use some contextual information that will allow us to + /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we + /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a + /// valid `DefPathHash`. Since we also always build a huge table that maps every + /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have + /// everything we need to re-run the query. + /// + /// Take the `mir_promoted` query as an example. Like many other queries, it + /// just has a single parameter: the `DefId` of the item it will compute the + /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` + /// 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>, + + /// Invoke a query to put the on-disk cached value in memory. + 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 +/// save in between runs. These IDs do not have a `DefId` but rather +/// some independent path or string that persists between runs without +/// the need to be mapped or unmapped. (This ensures we can serialize +/// them even in the absence of a tcx.) +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] +pub struct WorkProductId { + hash: Fingerprint, +} + +impl WorkProductId { + pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { + let mut hasher = StableHasher::new(); + cgu_name.hash(&mut hasher); + WorkProductId { hash: hasher.finish() } + } +} + +impl HashStable for WorkProductId { + #[inline] + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { + self.hash.hash_stable(hcx, hasher) + } +} +impl ToStableHashKey for WorkProductId { + type KeyType = Fingerprint; + #[inline] + fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { + self.hash + } +} +impl StableOrd for WorkProductId { + // Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well + const CAN_USE_UNSTABLE_SORT: bool = true; + + // `WorkProductId` sort order is not affected by (de)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); +} + macro_rules! define_dep_nodes { ( $( @@ -177,222 +494,17 @@ pub fn dep_kind_from_label(label: &str) -> DepKind { .unwrap_or_else(|_| panic!("Query label {label} does not exist")) } -impl<'tcx> DepNodeParams> for () { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::Unit - } +// Some types are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(target_pointer_width = "64")] +mod size_asserts { + use rustc_data_structures::static_assert_size; - #[inline(always)] - fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { - Fingerprint::ZERO - } - - #[inline(always)] - fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { - Some(()) - } -} - -impl<'tcx> DepNodeParams> for DefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - tcx.def_path_hash(*self).0 - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.def_path_str(*self) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx) - } -} - -impl<'tcx> DepNodeParams> for LocalDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.expect_local()) - } -} - -impl<'tcx> DepNodeParams> for OwnerId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) - } -} - -impl<'tcx> DepNodeParams> for CrateNum { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let def_id = self.as_def_id(); - def_id.to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.crate_name(*self).to_string() - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.krate) - } -} - -impl<'tcx> DepNodeParams> for (DefId, DefId) { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::Opaque - } - - // We actually would not need to specialize the implementation of this - // method but it's faster to combine the hashes than to instantiate a full - // hashing context and stable-hashing state. - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let (def_id_0, def_id_1) = *self; - - let def_path_hash_0 = tcx.def_path_hash(def_id_0); - let def_path_hash_1 = tcx.def_path_hash(def_id_1); - - def_path_hash_0.0.combine(def_path_hash_1.0) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let (def_id_0, def_id_1) = *self; - - format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) - } -} - -impl<'tcx> DepNodeParams> for HirId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::HirId - } - - // We actually would not need to specialize the implementation of this - // method but it's faster to combine the hashes than to instantiate a full - // hashing context and stable-hashing state. - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(owner.to_def_id()); - Fingerprint::new( - // `owner` is local, so is completely defined by the local hash - def_path_hash.local_hash(), - local_id.as_u32() as u64, - ) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let HirId { owner, local_id } = *self; - format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32()) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId { - let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split(); - let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash); - let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local(); - let local_id = local_id - .as_u64() - .try_into() - .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}")); - Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) }) - } else { - None - } - } -} - -impl<'tcx> DepNodeParams> for ModDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked) - } -} - -impl<'tcx> DepNodeParams> for LocalModDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked) - } + use super::*; + // tidy-alphabetical-start + static_assert_size!(DepKind, 2); + #[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); + // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs new file mode 100644 index 000000000000..b1dfc15539bf --- /dev/null +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -0,0 +1,227 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; +use rustc_hir::definitions::DefPathHash; +use rustc_hir::{HirId, ItemLocalId, OwnerId}; + +use crate::dep_graph::{DepContext, DepNode, DepNodeExt, DepNodeKey, FingerprintStyle}; +use crate::ty::TyCtxt; + +impl<'tcx> DepNodeKey> for () { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Unit + } + + #[inline(always)] + fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { + Fingerprint::ZERO + } + + #[inline(always)] + fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { + Some(()) + } +} + +impl<'tcx> DepNodeKey> for DefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + tcx.def_path_hash(*self).0 + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + tcx.def_path_str(*self) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx) + } +} + +impl<'tcx> DepNodeKey> for LocalDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.expect_local()) + } +} + +impl<'tcx> DepNodeKey> for OwnerId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) + } +} + +impl<'tcx> DepNodeKey> for CrateNum { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let def_id = self.as_def_id(); + def_id.to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + tcx.crate_name(*self).to_string() + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.krate) + } +} + +impl<'tcx> DepNodeKey> for (DefId, DefId) { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque + } + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let (def_id_0, def_id_1) = *self; + + let def_path_hash_0 = tcx.def_path_hash(def_id_0); + let def_path_hash_1 = tcx.def_path_hash(def_id_1); + + def_path_hash_0.0.combine(def_path_hash_1.0) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + let (def_id_0, def_id_1) = *self; + + format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) + } +} + +impl<'tcx> DepNodeKey> for HirId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::HirId + } + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let HirId { owner, local_id } = *self; + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); + Fingerprint::new( + // `owner` is local, so is completely defined by the local hash + def_path_hash.local_hash(), + local_id.as_u32() as u64, + ) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + let HirId { owner, local_id } = *self; + format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32()) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId { + let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split(); + let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash); + let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local(); + let local_id = local_id + .as_u64() + .try_into() + .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}")); + Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) }) + } else { + None + } + } +} + +impl<'tcx> DepNodeKey> for ModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked) + } +} + +impl<'tcx> DepNodeKey> for LocalModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked) + } +} diff --git a/compiler/rustc_query_system/src/dep_graph/edges.rs b/compiler/rustc_middle/src/dep_graph/edges.rs similarity index 100% rename from compiler/rustc_query_system/src/dep_graph/edges.rs rename to compiler/rustc_middle/src/dep_graph/edges.rs diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs similarity index 93% rename from compiler/rustc_query_system/src/dep_graph/graph.rs rename to compiler/rustc_middle/src/dep_graph/graph.rs index f0cc9636b75c..3ef0511795b9 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -15,6 +15,8 @@ use rustc_data_structures::{assert_matches, outline}; use rustc_errors::DiagInner; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable}; +use rustc_query_system::ich::StableHashingContext; +use rustc_query_system::query::QuerySideEffect; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::Session; use tracing::{debug, instrument}; @@ -25,8 +27,8 @@ use super::query::DepGraphQuery; use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex}; use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; -use crate::ich::StableHashingContext; -use crate::query::{QueryContext, QuerySideEffect}; +use crate::query::QueryContext; +use crate::verify_ich::incremental_verify_ich; pub struct DepGraph { data: Option>>, @@ -82,7 +84,7 @@ pub(super) enum DepNodeColor { Unknown, } -pub(crate) 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 @@ -171,7 +173,7 @@ impl DepGraph { } #[inline] - pub(crate) fn data(&self) -> Option<&DepGraphData> { + pub fn data(&self) -> Option<&DepGraphData> { self.data.as_deref() } @@ -323,7 +325,7 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub(crate) fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -336,13 +338,17 @@ impl DepGraphData { // in `DepGraph::try_mark_green()`. // 2. Two distinct query keys get mapped to the same `DepNode` // (see for example #48923). - self.assert_dep_node_not_yet_allocated_in_current_session(&key, || { - format!( - "forcing query with already existing `DepNode`\n\ + self.assert_dep_node_not_yet_allocated_in_current_session( + cx.dep_context().sess(), + &key, + || { + format!( + "forcing query with already existing `DepNode`\n\ - query-key: {arg:?}\n\ - dep-node: {key:?}" - ) - }); + ) + }, + ); 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) { @@ -373,7 +379,7 @@ impl DepGraphData { /// FIXME: This could perhaps return a `WithDepNode` to ensure that the /// user of this function actually performs the read; we'll have to see /// how to make that work with `anon` in `execute_job_incr`, though. - pub(crate) fn with_anon_task_inner, OP, R>( + pub fn with_anon_task_inner, OP, R>( &self, cx: Tcx, dep_kind: DepKind, @@ -519,7 +525,11 @@ impl DepGraph { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { + pub fn record_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) { if let Some(ref data) = self.data { D::read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, @@ -532,7 +542,7 @@ impl DepGraph { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - pub fn force_diagnostic_node( + pub fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -557,12 +567,13 @@ 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, R: Debug>( + pub fn with_feed_task, R>( &self, node: DepNode, cx: Ctxt, result: &R, hash_result: Option, &R) -> Fingerprint>, + format_value_fn: fn(&R) -> String, ) -> DepNodeIndex { if let Some(data) = self.data.as_ref() { // The caller query has more dependencies than the node we are creating. We may @@ -574,13 +585,13 @@ impl DepGraph { if let Some(prev_index) = data.previous.node_to_index_opt(&node) { let dep_node_index = data.colors.current(prev_index); if let Some(dep_node_index) = dep_node_index { - crate::query::incremental_verify_ich( + incremental_verify_ich( cx, data, result, prev_index, hash_result, - |value| format!("{value:?}"), + format_value_fn, ); #[cfg(debug_assertions)] @@ -622,12 +633,20 @@ impl DepGraph { impl DepGraphData { fn assert_dep_node_not_yet_allocated_in_current_session( &self, + sess: &Session, dep_node: &DepNode, msg: impl FnOnce() -> S, ) { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { - let current = self.colors.get(prev_index); - assert_matches!(current, DepNodeColor::Unknown, "{}", msg()) + let color = self.colors.get(prev_index); + let ok = match color { + DepNodeColor::Unknown => true, + DepNodeColor::Red => false, + DepNodeColor::Green(..) => sess.threads() > 1, // Other threads may mark this green + }; + if !ok { + panic!("{}", msg()) + } } else if let Some(nodes_in_current_session) = &self.current.nodes_in_current_session { outline(|| { let seen = nodes_in_current_session.lock().contains_key(dep_node); @@ -648,28 +667,28 @@ impl DepGraphData { /// Returns true if the given node has been marked as green during the /// current compilation session. Used in various assertions #[inline] - pub(crate) fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool { + pub fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool { matches!(self.colors.get(prev_index), DepNodeColor::Green(_)) } #[inline] - pub(crate) fn prev_fingerprint_of(&self, prev_index: SerializedDepNodeIndex) -> Fingerprint { + pub fn prev_fingerprint_of(&self, prev_index: SerializedDepNodeIndex) -> Fingerprint { self.previous.fingerprint_by_index(prev_index) } #[inline] - pub(crate) fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { + pub(crate) fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> &DepNode { self.previous.index_to_node(prev_index) } - pub(crate) 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); } /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - fn encode_diagnostic( + fn encode_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, diagnostic: &DiagInner, @@ -693,7 +712,7 @@ impl DepGraphData { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - fn force_diagnostic_node( + fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -771,17 +790,22 @@ impl DepGraphData { } } - fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex { + fn promote_node_and_deps_to_current( + &self, + prev_index: SerializedDepNodeIndex, + ) -> Option { self.current.debug_assert_not_in_new_nodes(&self.previous, prev_index); let dep_node_index = self.current.encoder.send_promoted(prev_index, &self.colors); #[cfg(debug_assertions)] - self.current.record_edge( - dep_node_index, - self.previous.index_to_node(prev_index), - self.previous.fingerprint_by_index(prev_index), - ); + if let Some(dep_node_index) = dep_node_index { + self.current.record_edge( + dep_node_index, + *self.previous.index_to_node(prev_index), + self.previous.fingerprint_by_index(prev_index), + ); + } dep_node_index } @@ -843,7 +867,7 @@ impl DepGraph { DepNodeColor::Unknown } - pub fn try_mark_green>( + pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -858,7 +882,7 @@ impl DepGraphData { /// 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(crate) fn try_mark_green>( + pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -868,6 +892,8 @@ impl DepGraphData { // Return None if the dep node didn't exist in the previous session let prev_index = self.previous.node_to_index_opt(dep_node)?; + debug_assert_eq!(self.previous.index_to_node(prev_index), dep_node); + match self.colors.get(prev_index) { DepNodeColor::Green(dep_node_index) => Some((prev_index, dep_node_index)), DepNodeColor::Red => None, @@ -876,14 +902,14 @@ impl DepGraphData { // in the previous compilation session too, so we can try to // mark it as green by recursively marking all of its // dependencies green. - self.try_mark_previous_green(qcx, prev_index, dep_node, None) + self.try_mark_previous_green(qcx, prev_index, None) .map(|dep_node_index| (prev_index, dep_node_index)) } } } #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, @@ -914,7 +940,7 @@ impl DepGraphData { DepNodeColor::Unknown => {} } - let dep_dep_node = &get_dep_dep_node(); + let dep_dep_node = get_dep_dep_node(); // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. @@ -924,8 +950,7 @@ impl DepGraphData { dep_dep_node, dep_dep_node.hash, ); - let node_index = - self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, Some(frame)); + let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, Some(frame)); if node_index.is_some() { debug!("managed to MARK dependency {dep_dep_node:?} as green"); @@ -973,19 +998,19 @@ 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<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option { let frame = MarkFrame { index: prev_dep_node_index, parent: frame }; // We never try to mark eval_always nodes as green - debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); - - debug_assert_eq!(self.previous.index_to_node(prev_dep_node_index), *dep_node); + debug_assert!( + !qcx.dep_context() + .is_eval_always(self.previous.index_to_node(prev_dep_node_index).kind) + ); let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); @@ -1000,13 +1025,18 @@ impl DepGraphData { // There may be multiple threads trying to mark the same dep node green concurrently // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index); + // adding all the appropriate edges imported from the previous graph. + // + // `no_hash` nodes may fail this promotion due to already being conservatively colored red. + let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index)?; // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here - debug!("successfully marked {dep_node:?} as green"); + debug!( + "successfully marked {:?} as green", + self.previous.index_to_node(prev_dep_node_index) + ); Some(dep_node_index) } } @@ -1026,11 +1056,12 @@ impl DepGraph { pub fn assert_dep_node_not_yet_allocated_in_current_session( &self, + sess: &Session, dep_node: &DepNode, msg: impl FnOnce() -> S, ) { if let Some(data) = &self.data { - data.assert_dep_node_not_yet_allocated_in_current_session(dep_node, msg) + data.assert_dep_node_not_yet_allocated_in_current_session(sess, dep_node, msg) } } @@ -1065,7 +1096,7 @@ impl DepGraph { if let Some(data) = &self.data { data.current.encoder.finish(&data.current) } else { Ok(0) } } - pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex { + pub fn next_virtual_depnode_index(&self) -> DepNodeIndex { debug_assert!(self.data.is_none()); let index = self.virtual_dep_node_index.fetch_add(1, Ordering::Relaxed); DepNodeIndex::from_u32(index) @@ -1368,26 +1399,27 @@ impl DepNodeColorMap { } /// This tries to atomically mark a node green and assign `index` as the new - /// index. This returns `Ok` if `index` gets assigned, otherwise it returns - /// the already allocated index in `Err`. - #[inline] - pub(super) fn try_mark_green( + /// index if `green` is true, otherwise it will try to atomicaly mark it red. + /// + /// This returns `Ok` if `index` gets assigned or the node is marked red, otherwise it returns + /// the already allocated index in `Err` if it is green already. If it was already + /// red, `Err(None)` is returned. + #[inline(always)] + pub(super) fn try_mark( &self, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, - ) -> Result<(), DepNodeIndex> { + green: bool, + ) -> Result<(), Option> { let value = &self.values[prev_index]; match value.compare_exchange( COMPRESSED_UNKNOWN, - index.as_u32(), + if green { index.as_u32() } else { COMPRESSED_RED }, Ordering::Relaxed, Ordering::Relaxed, ) { Ok(_) => Ok(()), - Err(v) => Err({ - assert_ne!(v, COMPRESSED_RED, "tried to mark a red node as green"); - DepNodeIndex::from_u32(v) - }), + Err(v) => Err(if v == COMPRESSED_RED { None } else { Some(DepNodeIndex::from_u32(v)) }), } } @@ -1410,7 +1442,7 @@ impl DepNodeColorMap { pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) { let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release); // Sanity check for duplicate nodes - assert_eq!(value, COMPRESSED_UNKNOWN, "trying to encode a dep node twice"); + assert_eq!(value, COMPRESSED_UNKNOWN, "tried to color an already colored node as red"); } } @@ -1446,7 +1478,7 @@ fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepN // previous session and has been marked green for prev_index in data.colors.values.indices() { if data.colors.current(prev_index) == Some(dep_node_index) { - dep_node = Some(data.previous.index_to_node(prev_index)); + dep_node = Some(*data.previous.index_to_node(prev_index)); break; } } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index f28ba10d52e2..723eed21f211 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,24 +1,187 @@ +use std::panic; + use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_data_structures::sync::DynSync; use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; +use tracing::instrument; +pub use self::dep_node::{ + DepKind, DepNode, DepNodeExt, DepNodeKey, WorkProductId, dep_kind_from_label, dep_kinds, + label_strs, +}; +pub use self::graph::{ + DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, +}; +use self::graph::{MarkFrame, print_markframe_trace}; +pub use self::query::DepGraphQuery; +pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; +pub use crate::dep_graph::debug::{DepNodeFilter, EdgeFilter}; use crate::ty::print::with_reduced_queries; use crate::ty::{self, TyCtxt}; -#[macro_use] -mod dep_node; +mod debug; +pub mod dep_node; +mod dep_node_key; +mod edges; +mod graph; +mod query; +mod serialized; -pub use dep_node::{DepKind, DepNode, DepNodeExt, dep_kind_from_label, dep_kinds, label_strs}; -pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata}; -pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -pub use rustc_query_system::dep_graph::{ - DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph, SerializedDepNodeIndex, - TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap, hash_result, -}; +pub trait DepContext: Copy { + type Deps: Deps; -pub type DepGraph = rustc_query_system::dep_graph::DepGraph; + /// Create a hashing context for hashing new results. + fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; -pub type DepKindVTable<'tcx> = rustc_query_system::dep_graph::DepKindVTable>; + /// Access the DepGraph. + fn dep_graph(&self) -> &graph::DepGraph; + + /// Access the profiler. + fn profiler(&self) -> &SelfProfilerRef; + + /// Access the compiler session. + fn sess(&self) -> &Session; + + fn dep_kind_vtable(&self, dep_node: DepKind) -> &dep_node::DepKindVTable; + + #[inline(always)] + fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { + self.dep_kind_vtable(kind).fingerprint_style + } + + #[inline(always)] + /// Return whether this kind always require evaluation. + fn is_eval_always(self, kind: DepKind) -> bool { + self.dep_kind_vtable(kind).is_eval_always + } + + /// Try to force a dep node to execute and see if it's green. + /// + /// Returns true if the query has actually been forced. It is valid that a query + /// fails to be forced, e.g. when the query key cannot be reconstructed from the + /// dep-node or when the query kind outright does not support it. + #[inline] + #[instrument(skip(self, frame), level = "debug")] + fn try_force_from_dep_node( + self, + dep_node: DepNode, + prev_index: SerializedDepNodeIndex, + frame: &MarkFrame<'_>, + ) -> bool { + if let Some(force_fn) = self.dep_kind_vtable(dep_node.kind).force_from_dep_node { + match panic::catch_unwind(panic::AssertUnwindSafe(|| { + force_fn(self, dep_node, prev_index) + })) { + Err(value) => { + if !value.is::() { + print_markframe_trace(self.dep_graph(), frame); + } + panic::resume_unwind(value) + } + Ok(query_has_been_forced) => query_has_been_forced, + } + } else { + false + } + } + + /// Load data from the on-disk cache. + fn try_load_from_on_disk_cache(self, dep_node: &DepNode) { + if let Some(try_load_fn) = self.dep_kind_vtable(dep_node.kind).try_load_from_on_disk_cache { + try_load_fn(self, *dep_node) + } + } + + fn with_reduced_queries(self, _: impl FnOnce() -> T) -> T; +} + +pub trait Deps: DynSync { + /// 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>); + + fn name(dep_kind: DepKind) -> &'static str; + + /// 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; + + /// We use this to create a side effect node. + const DEP_KIND_SIDE_EFFECT: DepKind; + + /// We use this to create the anon node with zero dependencies. + const DEP_KIND_ANON_ZERO_DEPS: 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 Deps: self::Deps; + type DepContext: self::DepContext; + + fn dep_context(&self) -> &Self::DepContext; +} + +impl HasDepContext for T { + type Deps = T::Deps; + type DepContext = Self; + + fn dep_context(&self) -> &Self::DepContext { + self + } +} + +impl HasDepContext for (T, Q) { + type Deps = T::Deps; + type DepContext = T::DepContext; + + fn dep_context(&self) -> &Self::DepContext { + self.0.dep_context() + } +} + +/// Describes the contents of the fingerprint generated by a given query. +/// +/// This is mainly for determining whether and how we can reconstruct a key +/// from the fingerprint. +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +pub enum FingerprintStyle { + /// The fingerprint is actually a DefPathHash. + DefPathHash, + /// The fingerprint is actually a HirId. + HirId, + /// Query key was `()` or equivalent, so fingerprint is just zero. + Unit, + /// The fingerprint is an opaque hash, and a key cannot be reconstructed from it. + Opaque, +} + +impl FingerprintStyle { + #[inline] + pub const fn reconstructible(self) -> bool { + match self { + FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => { + true + } + FingerprintStyle::Opaque => false, + } + } +} + +pub type DepGraph = graph::DepGraph; + +pub type DepKindVTable<'tcx> = dep_node::DepKindVTable>; pub struct DepsType; diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_middle/src/dep_graph/query.rs similarity index 95% rename from compiler/rustc_query_system/src/dep_graph/query.rs rename to compiler/rustc_middle/src/dep_graph/query.rs index 724a01327aba..f145e1cba2d7 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_middle/src/dep_graph/query.rs @@ -28,10 +28,9 @@ impl DepGraphQuery { self.indices.insert(node, source); for &target in edges.iter() { - let target = self.dep_index_to_index[target]; // We may miss the edges that are pushed while the `DepGraphQuery` is being accessed. // Skip them to issues. - if let Some(target) = target { + if let Some(&Some(target)) = self.dep_index_to_index.get(target) { self.graph.add_edge(source, target, ()); } } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs similarity index 97% rename from compiler/rustc_query_system/src/dep_graph/serialized.rs rename to compiler/rustc_middle/src/dep_graph/serialized.rs index 403394674a02..3b5954fc8f94 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -133,8 +133,8 @@ impl SerializedDepGraph { } #[inline] - pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { - self.nodes[dep_node_index] + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> &DepNode { + &self.nodes[dep_node_index] } #[inline] @@ -346,7 +346,7 @@ impl SerializedNodeHeader { #[inline] fn new( - node: DepNode, + node: &DepNode, index: DepNodeIndex, fingerprint: Fingerprint, edge_max_index: u32, @@ -379,7 +379,7 @@ impl SerializedNodeHeader { { let res = Self { bytes, _marker: PhantomData }; assert_eq!(fingerprint, res.fingerprint()); - assert_eq!(node, res.node()); + assert_eq!(*node, res.node()); if let Some(len) = res.len() { assert_eq!(edge_count, len as usize); } @@ -452,7 +452,7 @@ struct NodeInfo { impl NodeInfo { fn encode(&self, e: &mut MemEncoder, index: DepNodeIndex) { - let NodeInfo { node, fingerprint, ref edges } = *self; + let NodeInfo { ref node, fingerprint, ref edges } = *self; let header = SerializedNodeHeader::::new( node, index, @@ -482,7 +482,7 @@ impl NodeInfo { #[inline] fn encode_promoted( e: &mut MemEncoder, - node: DepNode, + node: &DepNode, index: DepNodeIndex, fingerprint: Fingerprint, prev_index: SerializedDepNodeIndex, @@ -604,7 +604,7 @@ impl EncoderState { #[inline] fn record( &self, - node: DepNode, + node: &DepNode, index: DepNodeIndex, edge_count: usize, edges: impl FnOnce(&Self) -> Vec, @@ -622,7 +622,7 @@ impl EncoderState { outline(move || { // Do not ICE when a query is called from within `with_query`. if let Some(record_graph) = &mut record_graph.try_lock() { - record_graph.push(index, node, &edges); + record_graph.push(index, *node, &edges); } }); } @@ -661,7 +661,7 @@ impl EncoderState { node.encode::(&mut local.encoder, index); self.flush_mem_encoder(&mut *local); self.record( - node.node, + &node.node, index, node.edges.len(), |_| node.edges[..].to_vec(), @@ -898,15 +898,12 @@ impl GraphEncoder { let index = self.status.next_index(&mut *local); - if is_green { - // Use `try_mark_green` to avoid racing when `send_promoted` is called concurrently - // on the same index. - match colors.try_mark_green(prev_index, index) { - Ok(()) => (), - Err(dep_node_index) => return dep_node_index, - } - } else { - colors.insert_red(prev_index); + // Use `try_mark` to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.try_mark(prev_index, index, is_green) { + Ok(()) => (), + Err(None) => panic!("dep node {:?} is unexpectedly red", prev_index), + Err(Some(dep_node_index)) => return dep_node_index, } self.status.bump_index(&mut *local); @@ -918,13 +915,13 @@ impl GraphEncoder { /// from the previous dep graph and expects all edges to already have a new dep node index /// assigned. /// - /// This will also ensure the dep node is marked green. + /// This will also ensure the dep node is marked green if `Some` is returned. #[inline] pub(crate) fn send_promoted( &self, prev_index: SerializedDepNodeIndex, colors: &DepNodeColorMap, - ) -> DepNodeIndex { + ) -> Option { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); let mut local = self.status.local.borrow_mut(); @@ -932,7 +929,7 @@ impl GraphEncoder { // Use `try_mark_green` to avoid racing when `send_promoted` or `send_and_color` // is called concurrently on the same index. - match colors.try_mark_green(prev_index, index) { + match colors.try_mark(prev_index, index, true) { Ok(()) => { self.status.bump_index(&mut *local); self.status.encode_promoted_node( @@ -942,7 +939,7 @@ impl GraphEncoder { colors, &mut *local, ); - index + Some(index) } Err(dep_node_index) => dep_node_index, } diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 3ff9eea8cc4b..dfb99fb98513 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -9,8 +9,8 @@ use rustc_span::{Span, Symbol}; use crate::ty::{Instance, Ty}; #[derive(Diagnostic)] -#[diag(middle_drop_check_overflow, code = E0320)] -#[note] +#[diag("overflow while adding drop-check rules for `{$ty}`", code = E0320)] +#[note("overflowed on `{$overflow_ty}`")] pub(crate) struct DropCheckOverflow<'tcx> { #[primary_span] pub span: Span, @@ -19,33 +19,33 @@ pub(crate) struct DropCheckOverflow<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_failed_writing_file)] +#[diag("failed to write file {$path}: {$error}\"")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(middle_opaque_hidden_type_mismatch)] +#[diag("concrete type differs from previous defining opaque type use")] pub(crate) struct OpaqueHiddenTypeMismatch<'tcx> { pub self_ty: Ty<'tcx>, pub other_ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("expected `{$self_ty}`, got `{$other_ty}`")] pub other_span: Span, #[subdiagnostic] pub sub: TypeMismatchReason, } #[derive(Diagnostic)] -#[diag(middle_unsupported_union)] +#[diag("we don't support unions yet: '{$ty_name}'")] pub struct UnsupportedUnion { pub ty_name: String, } // FIXME(autodiff): I should get used somewhere #[derive(Diagnostic)] -#[diag(middle_autodiff_unsafe_inner_const_ref)] +#[diag("reading from a `Duplicated` const {$ty} is unsafe")] pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[primary_span] pub span: Span, @@ -54,12 +54,12 @@ pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[derive(Subdiagnostic)] pub enum TypeMismatchReason { - #[label(middle_conflict_types)] + #[label("this expression supplies two conflicting concrete types for the same opaque type")] ConflictType { #[primary_span] span: Span, }, - #[note(middle_previous_use_here)] + #[note("previous use here")] PreviousUse { #[primary_span] span: Span, @@ -67,8 +67,10 @@ pub enum TypeMismatchReason { } #[derive(Diagnostic)] -#[diag(middle_recursion_limit_reached)] -#[help] +#[diag("reached the recursion limit finding the struct tail for `{$ty}`")] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]`" +)] pub(crate) struct RecursionLimitReached<'tcx> { #[primary_span] pub span: Span, @@ -77,23 +79,25 @@ pub(crate) struct RecursionLimitReached<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_const_eval_non_int)] +#[diag("constant evaluation of enum discriminant resulted in non-integer")] pub(crate) struct ConstEvalNonIntError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(middle_strict_coherence_needs_negative_coherence)] +#[diag( + "to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled" +)] pub(crate) struct StrictCoherenceNeedsNegativeCoherence { #[primary_span] pub span: Span, - #[label] - pub attr_span: Option, + #[label("due to this attribute")] + pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(middle_requires_lang_item)] +#[diag("requires `{$name}` lang_item")] pub(crate) struct RequiresLangItem { #[primary_span] pub span: Span, @@ -101,7 +105,9 @@ pub(crate) struct RequiresLangItem { } #[derive(Diagnostic)] -#[diag(middle_const_not_used_in_type_alias)] +#[diag( + "const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias" +)] pub(super) struct ConstNotUsedTraitAlias { pub ct: String, #[primary_span] @@ -133,41 +139,41 @@ impl fmt::Debug for CustomSubdiagnostic<'_> { #[derive(Diagnostic)] pub enum LayoutError<'tcx> { - #[diag(middle_layout_unknown)] + #[diag("the type `{$ty}` has an unknown layout")] Unknown { ty: Ty<'tcx> }, - #[diag(middle_layout_too_generic)] + #[diag("the type `{$ty}` does not have a fixed layout")] TooGeneric { ty: Ty<'tcx> }, - #[diag(middle_layout_size_overflow)] + #[diag("values of the type `{$ty}` are too big for the target architecture")] Overflow { ty: Ty<'tcx> }, - #[diag(middle_layout_simd_too_many)] + #[diag("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}")] SimdTooManyLanes { ty: Ty<'tcx>, max_lanes: u64 }, - #[diag(middle_layout_simd_zero_length)] + #[diag("the SIMD type `{$ty}` has zero elements")] SimdZeroLength { ty: Ty<'tcx> }, - #[diag(middle_layout_normalization_failure)] + #[diag("unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized")] NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, - #[diag(middle_layout_cycle)] + #[diag("a cycle occurred during layout computation")] Cycle, - #[diag(middle_layout_references_error)] + #[diag("the type has an unknown layout")] ReferencesError, } #[derive(Diagnostic)] -#[diag(middle_erroneous_constant)] +#[diag("erroneous constant encountered")] pub(crate) struct ErroneousConstant { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(middle_type_length_limit)] -#[help(middle_consider_type_length_limit)] +#[diag("reached the type-length limit while instantiating `{$instance}`")] +#[help("consider adding a `#![type_length_limit=\"{$type_length}\"]` attribute to your crate")] pub(crate) struct TypeLengthLimit<'tcx> { #[primary_span] pub span: Span, @@ -176,7 +182,7 @@ pub(crate) struct TypeLengthLimit<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_max_num_nodes_in_valtree)] +#[diag("maximum number of nodes exceeded in constant {$global_const_id}")] pub(crate) struct MaxNumNodesInValtree { #[primary_span] pub span: Span, @@ -184,10 +190,27 @@ pub(crate) struct MaxNumNodesInValtree { } #[derive(Diagnostic)] -#[diag(middle_invalid_const_in_valtree)] -#[note] +#[diag("constant {$global_const_id} cannot be used as pattern")] +#[note("constants that reference mutable or external memory cannot be used as patterns")] pub(crate) struct InvalidConstInValtree { #[primary_span] pub span: Span, pub global_const_id: String, } + +#[derive(Diagnostic)] +#[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] +pub(crate) struct Reentrant; + +#[derive(Diagnostic)] +#[diag("internal compiler error: encountered incremental compilation error with {$dep_node}")] +#[note("please follow the instructions below to create a bug report with the provided information")] +#[note("for incremental compilation bugs, having a reproduction is vital")] +#[note( + "an ideal reproduction consists of the code before and some patch that then triggers the bug when applied and compiled again" +)] +#[note("as a workaround, you can run {$run_cmd} to allow your project to compile")] +pub(crate) struct IncrementCompilation { + pub run_cmd: String, + pub dep_node: String, +} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index ba2d8febad7c..82f8eb4bbc4a 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -365,6 +365,33 @@ impl<'tcx> TyCtxt<'tcx> { } } } + + #[inline] + fn hir_owner_parent_impl(self, owner_id: OwnerId) -> HirId { + self.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| { + let parent_owner_id = self.local_def_id_to_hir_id(parent_def_id).owner; + HirId { + owner: parent_owner_id, + local_id: self.hir_crate(()).owners[parent_owner_id.def_id] + .unwrap() + .parenting + .get(&owner_id.def_id) + .copied() + .unwrap_or(ItemLocalId::ZERO), + } + }) + } + + /// Optimization of `hir_owner_parent` query as an inlined function + /// in case of non-incremental build. The query itself renamed to `hir_owner_parent_q`. + #[inline] + pub fn hir_owner_parent(self, owner_id: OwnerId) -> HirId { + if self.dep_graph.is_fully_enabled() { + self.hir_owner_parent_q(owner_id) + } else { + self.hir_owner_parent_impl(owner_id) + } + } } /// Hashes computed by [`TyCtxt::hash_owner_nodes`] if necessary. @@ -386,20 +413,7 @@ pub fn provide(providers: &mut Providers) { }; providers.opt_hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes); - providers.hir_owner_parent = |tcx, owner_id| { - tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| { - let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner; - HirId { - owner: parent_owner_id, - local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id] - .unwrap() - .parenting - .get(&owner_id.def_id) - .copied() - .unwrap_or(ItemLocalId::ZERO), - } - }) - }; + providers.hir_owner_parent_q = |tcx, owner_id| tcx.hir_owner_parent_impl(owner_id); providers.hir_attr_map = |tcx, id| { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5682c21e4353..1c4c987aee92 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,8 +27,9 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] +#![cfg_attr(bootstrap, feature(assert_matches))] +#![cfg_attr(doc, feature(intra_doc_pointers))] #![feature(allocator_api)] -#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_as_ptr)] #![feature(box_patterns)] @@ -43,7 +44,6 @@ #![feature(file_buffered)] #![feature(gen_blocks)] #![feature(if_let_guard)] -#![feature(intra_doc_pointers)] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] @@ -51,12 +51,12 @@ #![feature(range_bounds_is_empty)] #![feature(rustc_attrs)] #![feature(sized_hierarchy)] +#![feature(trait_alias)] #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(try_trait_v2_residual)] #![feature(try_trait_v2_yeet)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "256"] // tidy-alphabetical-end @@ -81,14 +81,14 @@ pub mod thir; pub mod traits; pub mod ty; pub mod util; -mod values; +pub mod verify_ich; #[macro_use] pub mod query; #[macro_use] +pub mod queries; +#[macro_use] pub mod dep_graph; // Allows macros to refer to this crate as `::rustc_middle` extern crate self as rustc_middle; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 51a079e8bc12..d625e9ea08cc 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -48,7 +48,7 @@ pub enum ObjectLifetimeDefault { /// Maps the id of each bound variable reference to the variable decl /// that it corresponds to. #[derive(Debug, Default, HashStable)] -pub struct ResolveBoundVars { +pub struct ResolveBoundVars<'tcx> { // Maps from every use of a named (not anonymous) bound var to a // `ResolvedArg` describing how that variable is bound. pub defs: SortedMap, @@ -59,7 +59,7 @@ pub struct ResolveBoundVars { // - closures // - trait refs // - bound types (like `T` in `for<'a> T<'a>: Foo`) - pub late_bound_vars: SortedMap>, + pub late_bound_vars: SortedMap>>, // List captured variables for each opaque type. pub opaque_captured_lifetimes: LocalDefIdMap>, diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fe2d4b9130ed..4f0073b93eba 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use rustc_ast::NodeId; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, msg}; use rustc_feature::GateIssue; use rustc_hir::attrs::{DeprecatedSince, Deprecation}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -103,7 +103,7 @@ fn deprecation_lint(is_in_effect: bool) -> &'static Lint { #[derive(Subdiagnostic)] #[suggestion( - middle_deprecated_suggestion, + "replace the use of the deprecated {$kind}", code = "{suggestion}", style = "verbose", applicability = "machine-applicable" @@ -128,10 +128,25 @@ pub struct Deprecated { impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { diag.primary_message(match &self.since_kind { - DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, - DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, + DeprecatedSinceKind::InEffect => msg!( + "use of deprecated {$kind} `{$path}`{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ), + DeprecatedSinceKind::InFuture => msg!( + "use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ), DeprecatedSinceKind::InVersion(_) => { - crate::fluent_generated::middle_deprecated_in_version + msg!( + "use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ) } }); diag.arg("kind", self.kind); diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 9762e0f21da9..0abc3aec7e00 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -13,7 +13,7 @@ use std::num::NonZero; use std::{fmt, io}; use rustc_abi::{AddressSpace, Align, Endian, HasDataLayout, Size}; -use rustc_ast::{LitKind, Mutability}; +use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::ShardedHashMap; use rustc_data_structures::sync::{AtomicU64, Lock}; @@ -73,17 +73,6 @@ impl<'tcx> GlobalId<'tcx> { } } -/// Input argument for `tcx.lit_to_const`. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)] -pub struct LitToConstInput<'tcx> { - /// The absolute value of the resultant constant. - pub lit: LitKind, - /// The type of the constant. - pub ty: Ty<'tcx>, - /// If the constant is negative. - pub neg: bool, -} - #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct AllocId(pub NonZero); diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index c7ced84a527f..577d226fc9d7 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -18,6 +18,7 @@ use rustc_span::{Span, Symbol}; use rustc_target::spec::SymbolVisibility; use tracing::debug; +use crate::dep_graph::dep_node::{make_compile_codegen_unit, make_compile_mono_item}; use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::{self, GenericArgs, Instance, InstanceKind, SymbolName, Ty, TyCtxt}; @@ -290,7 +291,7 @@ impl<'tcx> MonoItem<'tcx> { // Only used by rustc_codegen_cranelift pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { - crate::dep_graph::make_compile_mono_item(tcx, self) + make_compile_mono_item(tcx, self) } /// Returns the item's `CrateNum` @@ -576,7 +577,7 @@ impl<'tcx> CodegenUnit<'tcx> { } pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { - crate::dep_graph::make_compile_codegen_unit(tcx, self.name()) + make_compile_codegen_unit(tcx, self.name()) } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ded02595563c..2e6e96b4d8a8 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -157,13 +157,13 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { /// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name /// or `typeck` and `bar` both appear in the name. pub fn dump_mir(&self, body: &Body<'tcx>) { - let _: io::Result<()> = try { + let _ = try { let mut file = self.create_dump_file("mir", body)?; self.dump_mir_to_writer(body, &mut file)?; }; if self.tcx().sess.opts.unstable_opts.dump_mir_graphviz { - let _: io::Result<()> = try { + let _ = try { let mut file = self.create_dump_file("dot", body)?; write_mir_fn_graphviz(self.tcx(), body, false, &mut file)?; }; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 393e9c59c355..973ceccc67f9 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -441,6 +441,8 @@ impl<'tcx> Place<'tcx> { where D: ?Sized + HasLocalDecls<'tcx>, { + // If there's a field projection element in `projection`, we *could* skip everything + // before that, but on 2026-01-31 a perf experiment showed no benefit from doing so. PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection) } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cd447d4ed992..1e7729bd8d65 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -336,18 +336,26 @@ impl AssertKind { pub fn diagnostic_message(&self) -> DiagMessage { use AssertKind::*; - use crate::fluent_generated::*; - match self { - BoundsCheck { .. } => middle_bounds_check, - Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow, - Overflow(BinOp::Shr, _, _) => middle_assert_shr_overflow, - Overflow(_, _, _) => middle_assert_op_overflow, - OverflowNeg(_) => middle_assert_overflow_neg, - DivisionByZero(_) => middle_assert_divide_by_zero, - RemainderByZero(_) => middle_assert_remainder_by_zero, + BoundsCheck { .. } => { + msg!("index out of bounds: the length is {$len} but the index is {$index}") + } + Overflow(BinOp::Shl, _, _) => { + msg!("attempt to shift left by `{$val}`, which would overflow") + } + Overflow(BinOp::Shr, _, _) => { + msg!("attempt to shift right by `{$val}`, which would overflow") + } + Overflow(_, _, _) => { + msg!("attempt to compute `{$left} {$op} {$right}`, which would overflow") + } + OverflowNeg(_) => msg!("attempt to negate `{$val}`, which would overflow"), + DivisionByZero(_) => msg!("attempt to divide `{$val}` by zero"), + RemainderByZero(_) => { + msg!("attempt to calculate the remainder of `{$val}` with a divisor of zero") + } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_return + msg!("`async fn` resumed after completion") } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() @@ -356,36 +364,40 @@ impl AssertKind { bug!("gen blocks can be resumed after they return and will keep returning `None`") } ResumedAfterReturn(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_return + msg!("coroutine resumed after completion") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_panic + msg!("`async fn` resumed after panicking") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - middle_assert_gen_resume_after_panic + msg!("`gen` fn or block cannot be further iterated on after it panicked") } ResumedAfterPanic(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_panic + msg!("coroutine resumed after panicking") + } + NullPointerDereference => msg!("null pointer dereference occurred"), + InvalidEnumConstruction(_) => { + msg!("trying to construct an enum from an invalid value `{$source}`") } - NullPointerDereference => middle_assert_null_ptr_deref, - InvalidEnumConstruction(_) => middle_assert_invalid_enum_construction, ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_drop + msg!("`async fn` resumed after async drop") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - middle_assert_gen_resume_after_drop + msg!("`gen` fn or block cannot be further iterated on after it async dropped") } ResumedAfterDrop(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_drop + msg!("coroutine resumed after async drop") } - MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref, + MisalignedPointerDereference { .. } => msg!( + "misaligned pointer dereference: address must be a multiple of {$required} but is {$found}" + ), } } @@ -498,6 +510,7 @@ impl<'tcx> TerminatorKind<'tcx> { } pub use helper::*; +use rustc_errors::msg; mod helper { use super::*; @@ -695,28 +708,6 @@ impl<'tcx> TerminatorKind<'tcx> { _ => None, } } - - /// Returns true if the terminator can write to memory. - pub fn can_write_to_memory(&self) -> bool { - match self { - TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Assert { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Unreachable => false, - TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::TailCall { .. } - // Yield writes to the resume_arg place. - | TerminatorKind::Yield { .. } - | TerminatorKind::InlineAsm { .. } => true, - } - } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs new file mode 100644 index 000000000000..59171f2da4f2 --- /dev/null +++ b/compiler/rustc_middle/src/queries.rs @@ -0,0 +1,2779 @@ +//! +//! # The rustc Query System: Query Definitions and Modifiers +//! +//! The core processes in rustc are shipped as queries. Each query is a demand-driven function from some key to a value. +//! The execution result of the function is cached and directly read during the next request, thereby improving compilation efficiency. +//! Some results are saved locally and directly read during the next compilation, which are core of incremental compilation. +//! +//! ## How to Read This Module +//! +//! Each `query` block in this file defines a single query, specifying its key and value types, along with various modifiers. +//! These query definitions are processed by the [`rustc_macros`], which expands them into the necessary boilerplate code +//! for the query system—including the [`Providers`] struct (a function table for all query implementations, where each field is +//! a function pointer to the actual provider), caching, and dependency graph integration. +//! **Note:** The `Providers` struct is not a Rust trait, but a struct generated by the `rustc_macros` to hold all provider functions. +//! The `rustc_macros` also supports a set of **query modifiers** (see below) that control the behavior of each query. +//! +//! The actual provider functions are implemented in various modules and registered into the `Providers` struct +//! during compiler initialization (see [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]). +//! +//! [`rustc_macros`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/index.html +//! [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]: ../../rustc_interface/passes/static.DEFAULT_QUERY_PROVIDERS.html +//! +//! ## Query Modifiers +//! +//! Query modifiers are special flags that alter the behavior of a query. They are parsed and processed by the `rustc_macros` +//! The main modifiers are: +//! +//! - `desc { ... }`: Sets the human-readable description for diagnostics and profiling. Required for every query. +//! - `arena_cache`: Use an arena for in-memory caching of the query result. +//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to true. +//! - `cycle_fatal`: If a dependency cycle is detected, abort compilation with a fatal error. +//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. +//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. +//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. +//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). +//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. +//! - `depth_limit`: Impose a recursion depth limit on the query to prevent stack overflows. +//! - `separate_provide_extern`: Use separate provider functions for local and external crates. +//! - `feedable`: Allow the query result to be set from another query ("fed" externally). +//! - `return_result_from_ensure_ok`: When called via `tcx.ensure_ok()`, return `Result<(), ErrorGuaranteed>` instead of `()`. +//! If the query needs to be executed and returns an error, the error is returned to the caller. +//! Only valid for queries returning `Result<_, ErrorGuaranteed>`. +//! +//! For the up-to-date list, see the `QueryModifiers` struct in +//! [`rustc_macros/src/query.rs`](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_macros/src/query.rs) +//! and for more details in incremental compilation, see the +//! [Query modifiers in incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#query-modifiers) section of the rustc-dev-guide. +//! +//! ## Query Expansion and Code Generation +//! +//! The [`rustc_macros::rustc_queries`] macro expands each query definition into: +//! - A method on [`TyCtxt`] (and [`crate::query::TyCtxtAt`]) for invoking the query. +//! - Provider traits and structs for supplying the query's value. +//! - Caching and dependency graph integration. +//! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. +//! +//! [`rustc_macros::rustc_queries`]: ../../rustc_macros/macro.rustc_queries.html +//! +//! The macro-based approach allows the query system to be highly flexible and maintainable, while minimizing boilerplate. +//! +//! For more details, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). + +#![allow(unused_parens)] + +use std::ffi::OsStr; +use std::path::PathBuf; +use std::sync::Arc; + +use rustc_abi::Align; +use rustc_arena::TypedArena; +use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::tokenstream::TokenStream; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::svh::Svh; +use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::ErrorGuaranteed; +use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem}; +use rustc_hir::def::{DefKind, DocLinkResMap}; +use rustc_hir::def_id::{ + CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, +}; +use rustc_hir::lang_items::{LangItem, LanguageItems}; +use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; +use rustc_index::IndexVec; +use rustc_lint_defs::LintId; +use rustc_macros::rustc_queries; +use rustc_session::Limits; +use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::cstore::{ + CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, +}; +use rustc_session::lint::LintExpectationId; +use rustc_span::def_id::LOCAL_CRATE; +use rustc_span::source_map::Spanned; +use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; +use rustc_target::spec::PanicStrategy; +use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; + +use crate::infer::canonical::{self, Canonical}; +use crate::lint::LintExpectation; +use crate::metadata::ModChild; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; +use crate::middle::debugger_visualizer::DebuggerVisualizerFile; +use crate::middle::deduced_param_attrs::DeducedParamAttrs; +use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use crate::middle::lib_features::LibFeatures; +use crate::middle::privacy::EffectiveVisibilities; +use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; +use crate::middle::stability::DeprecationEntry; +use crate::mir::interpret::{ + EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, + EvalToValTreeResult, GlobalId, +}; +use crate::mir::mono::{ + CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, +}; +use crate::query::describe_as_module; +use crate::query::plumbing::CyclePlaceholder; +use crate::traits::query::{ + CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, + CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, + CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint, + DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult, + OutlivesBound, +}; +use crate::traits::{ + CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource, + ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph, +}; +use crate::ty::fast_reject::SimplifiedType; +use crate::ty::layout::ValidityRequirement; +use crate::ty::print::PrintTraitRefExt; +use crate::ty::util::AlwaysRequiresDrop; +use crate::ty::{ + self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput, + SizedTraitKind, Ty, TyCtxt, TyCtxtFeed, +}; +use crate::{dep_graph, mir, thir}; + +// Each of these queries corresponds to a function pointer field in the +// `Providers` struct for requesting a value of that type, and a method +// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way +// which memoizes and does dep-graph tracking, wrapping around the actual +// `Providers` that the driver creates (using several `rustc_*` crates). +// +// The result type of each query must implement `Clone`, and additionally +// `ty::query::values::Value`, which produces an appropriate placeholder +// (error) value if the query resulted in a query cycle. +// Queries marked with `cycle_fatal` do not need the latter implementation, +// as they will raise an fatal error on query cycles instead. +rustc_queries! { + /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`. + /// The key is: + /// - A unique key corresponding to the invocation of a macro. + /// - Token stream which serves as an input to the macro. + /// + /// The output is the token stream generated by the proc macro. + query derive_macro_expansion(key: (LocalExpnId, &'tcx TokenStream)) -> Result<&'tcx TokenStream, ()> { + desc { "expanding a derive (proc) macro" } + cache_on_disk_if { true } + } + + /// This exists purely for testing the interactions between delayed bugs and incremental. + query trigger_delayed_bug(key: DefId) { + desc { "triggering a delayed bug for testing incremental" } + } + + /// Collects the list of all tools registered using `#![register_tool]`. + query registered_tools(_: ()) -> &'tcx ty::RegisteredTools { + arena_cache + desc { "compute registered tools for crate" } + } + + query early_lint_checks(_: ()) { + desc { "perform lints prior to AST lowering" } + } + + /// Tracked access to environment variables. + /// + /// Useful for the implementation of `std::env!`, `proc-macro`s change + /// detection and other changes in the compiler's behaviour that is easier + /// to control with an environment variable than a flag. + /// + /// NOTE: This currently does not work with dependency info in the + /// analysis, codegen and linking passes, place extra code at the top of + /// `rustc_interface::passes::write_dep_info` to make that work. + query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { + // Environment variables are global state + eval_always + desc { "get the value of an environment variable" } + } + + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { + desc { "getting the resolver outputs" } + } + + query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc)>, &'tcx ty::ResolverGlobalCtxt) { + eval_always + no_hash + desc { "getting the resolver for lowering" } + } + + /// Return the span for a definition. + /// + /// Contrary to `def_span` below, this query returns the full absolute span of the definition. + /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside + /// of rustc_middle::hir::source_map. + query source_span(key: LocalDefId) -> Span { + // Accesses untracked data + eval_always + desc { "getting the source span" } + } + + /// Represents crate as a whole (as distinct from the top-level crate module). + /// + /// If you call `tcx.hir_crate(())` we will have to assume that any change + /// means that you need to be recompiled. This is because the `hir_crate` + /// query gives you access to all other items. To avoid this fate, do not + /// call `tcx.hir_crate(())`; instead, prefer wrappers like + /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. + query hir_crate(key: ()) -> &'tcx Crate<'tcx> { + arena_cache + eval_always + desc { "getting the crate HIR" } + } + + /// All items in the crate. + query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems { + arena_cache + eval_always + desc { "getting HIR crate items" } + } + + /// The items in a module. + /// + /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`. + /// Avoid calling this query directly. + query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { + arena_cache + desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + + /// Returns HIR ID for the given `LocalDefId`. + query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { + desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to the HIR node's parent for the HIR owner `key`. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query hir_owner_parent_q(key: hir::OwnerId) -> hir::HirId { + desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } + } + + /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { + desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to the HIR attributes inside the HIR owner `key`. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { + desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to lints emitted during ast lowering. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query opt_ast_lowering_delayed_lints(key: hir::OwnerId) -> Option<&'tcx hir::lints::DelayedLints> { + desc { |tcx| "getting AST lowering delayed lints in `{}`", tcx.def_path_str(key) } + } + + /// Returns the *default* of the const pararameter given by `DefId`. + /// + /// E.g., given `struct Ty;` this returns `3` for `N`. + query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + desc { |tcx| "computing the default for const parameter `{}`", tcx.def_path_str(param) } + cache_on_disk_if { param.is_local() } + separate_provide_extern + } + + /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`. + /// + /// When a const item is used in a type-level expression, like in equality for an assoc const + /// projection, this allows us to retrieve the typesystem-appropriate representation of the + /// const value. + /// + /// This query will ICE if given a const that is not marked with `type const`. + query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Returns the *type* of the definition given by `DefId`. + /// + /// For type aliases (whether eager or lazy) and associated types, this returns + /// the underlying aliased type (not the corresponding [alias type]). + /// + /// For opaque types, this returns and thus reveals the hidden type! If you + /// want to detect cycle errors use `type_of_opaque` instead. + /// + /// To clarify, for type definitions, this does *not* return the "type of a type" + /// (aka *kind* or *sort*) in the type-theoretical sense! It merely returns + /// the type primarily *associated with* it. + /// + /// # Panics + /// + /// This query will panic if the given definition doesn't (and can't + /// conceptually) have an (underlying) type. + /// + /// [alias type]: rustc_middle::ty::AliasTy + query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + desc { |tcx| + "{action} `{path}`", + action = match tcx.def_kind(key) { + DefKind::TyAlias => "expanding type alias", + DefKind::TraitAlias => "expanding trait alias", + _ => "computing type of", + }, + path = tcx.def_path_str(key), + } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. + /// + /// This is a specialized instance of [`Self::type_of`] that detects query cycles. + /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. + /// This is used to improve the error message in cases where revealing the hidden type + /// for auto-trait leakage cycles. + /// + /// # Panics + /// + /// This query will panic if the given definition is not an opaque type. + query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { + desc { |tcx| + "computing type of opaque `{path}`", + path = tcx.def_path_str(key), + } + cycle_stash + } + query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + desc { |tcx| + "computing type of opaque `{path}` via HIR typeck", + path = tcx.def_path_str(key), + } + } + + /// Returns whether the type alias given by `DefId` is lazy. + /// + /// I.e., if the type alias expands / ought to expand to a [free] [alias type] + /// instead of the underlying aliased type. + /// + /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. + /// + /// # Panics + /// + /// This query *may* panic if the given definition is not a type alias. + /// + /// [free]: rustc_middle::ty::Free + /// [alias type]: rustc_middle::ty::AliasTy + query type_alias_is_lazy(key: DefId) -> bool { + desc { |tcx| + "computing whether the type alias `{path}` is lazy", + path = tcx.def_path_str(key), + } + separate_provide_extern + } + + query collect_return_position_impl_trait_in_trait_tys(key: DefId) + -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> + { + desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin + { + desc { "determine where the opaque originates from" } + separate_provide_extern + } + + query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet + { + arena_cache + desc { |tcx| + "determining what parameters of `{}` can participate in unsizing", + tcx.def_path_str(key), + } + } + + /// The root query triggering all analysis passes like typeck or borrowck. + query analysis(key: ()) { + eval_always + desc { |tcx| + "running analysis passes on crate `{}`", + tcx.crate_name(LOCAL_CRATE), + } + } + + /// This query checks the fulfillment of collected lint expectations. + /// All lint emitting queries have to be done before this is executed + /// to ensure that all expectations can be fulfilled. + /// + /// This is an extra query to enable other drivers (like rustdoc) to + /// only execute a small subset of the `analysis` query, while allowing + /// lints to be expected. In rustc, this query will be executed as part of + /// the `analysis` query and doesn't have to be called a second time. + /// + /// Tools can additionally pass in a tool filter. That will restrict the + /// expectations to only trigger for lints starting with the listed tool + /// name. This is useful for cases were not all linting code from rustc + /// was called. With the default `None` all registered lints will also + /// be checked for expectation fulfillment. + query check_expectations(key: Option) { + eval_always + desc { "checking lint expectations (RFC 2383)" } + } + + /// Returns the *generics* of the definition given by `DefId`. + query generics_of(key: DefId) -> &'tcx ty::Generics { + desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } + arena_cache + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the (elaborated) *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). + /// + /// This is almost always *the* "predicates query" that you want. + /// + /// **Tip**: You can use `#[rustc_dump_predicates]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. + query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + } + + query opaque_types_defined_by( + key: LocalDefId + ) -> &'tcx ty::List { + desc { + |tcx| "computing the opaque types defined by `{}`", + tcx.def_path_str(key.to_def_id()) + } + } + + /// A list of all bodies inside of `key`, nested bodies are always stored + /// before their parent. + query nested_bodies_within( + key: LocalDefId + ) -> &'tcx ty::List { + desc { + |tcx| "computing the coroutines defined within `{}`", + tcx.def_path_str(key.to_def_id()) + } + } + + /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). + /// + /// For associated types, these must be satisfied for an implementation + /// to be well-formed, and for opaque types, these are required to be + /// satisfied by the hidden type of the opaque. + /// + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. + /// + /// Syntactially, these are the bounds written on associated types in trait + /// definitions, or those after the `impl` keyword for an opaque: + /// + /// ```ignore (illustrative) + /// trait Trait { type X: Bound + 'lt; } + /// // ^^^^^^^^^^^ + /// fn function() -> impl Debug + Display { /*...*/ } + /// // ^^^^^^^^^^^^^^^ + /// ``` + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the explicitly user-written *bounds* that share the `Self` type of the item. + /// + /// These are a subset of the [explicit item bounds] that may explicitly be used for things + /// like closure signature deduction. + /// + /// [explicit item bounds]: Self::explicit_item_bounds + query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the (elaborated) *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). + /// + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. + /// + /// **Tip**: You can use `#[rustc_dump_item_bounds]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples + /// + /// ``` + /// trait Trait { type Assoc: Eq + ?Sized; } + /// ``` + /// + /// While [`Self::explicit_item_bounds`] returns `[::Assoc: Eq]` + /// here, `item_bounds` returns: + /// + /// ```text + /// [ + /// ::Assoc: Eq, + /// ::Assoc: PartialEq<::Assoc> + /// ] + /// ``` + query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } + } + + query item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } + } + + query item_non_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } + } + + query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } + } + + /// Look up all native libraries this crate depends on. + /// These are assembled from the following places: + /// - `extern` blocks (depending on their `link` attributes) + /// - the `libs` (`-l`) option + query native_libraries(_: CrateNum) -> &'tcx Vec { + arena_cache + desc { "looking up the native libraries of a linked crate" } + separate_provide_extern + } + + query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap { + arena_cache + desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) } + } + + query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> { + arena_cache + desc { "computing `#[expect]`ed lints in this crate" } + } + + query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { + arena_cache + desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" } + } + + query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + query is_panic_runtime(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate is_panic_runtime" } + separate_provide_extern + } + + /// Checks whether a type is representable or infinitely sized + query representability(_: LocalDefId) -> rustc_middle::ty::Representability { + desc { "checking if `{}` is representable", tcx.def_path_str(key) } + // infinitely sized types will cause a cycle + cycle_delay_bug + // we don't want recursive representability calls to be forced with + // incremental compilation because, if a cycle occurs, we need the + // entire cycle to be in memory for diagnostics + anon + } + + /// An implementation detail for the `representability` query + query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability { + desc { "checking if `{}` is representable", key } + cycle_delay_bug + anon + } + + /// Set of param indexes for type params that are in the type's representation + query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet { + desc { "finding type parameters in the representation" } + arena_cache + no_hash + separate_provide_extern + } + + /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless + /// `-Zno-steal-thir` is on. + query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { + // Perf tests revealed that hashing THIR is inefficient (see #85729). + no_hash + desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) } + } + + /// Set of all the `DefId`s in this crate that have MIR associated with + /// them. This includes all the body owners, but also things like struct + /// constructors. + query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet { + arena_cache + desc { "getting a list of all mir_keys" } + } + + /// Maps DefId's that have an associated `mir::Body` to the result + /// of the MIR const-checking pass. This is the set of qualifs in + /// the final value of a `const`. + query mir_const_qualif(key: DefId) -> mir::ConstQualifs { + desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Build the MIR for a given `DefId` and prepare it for const qualification. + /// + /// See the [rustc dev guide] for more info. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html + query mir_built(key: LocalDefId) -> &'tcx Steal> { + desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } + feedable + } + + /// Try to build an abstract representation of the given constant. + query thir_abstract_const( + key: DefId + ) -> Result>>, ErrorGuaranteed> { + desc { + |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), + } + separate_provide_extern + } + + query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal> { + no_hash + desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) } + } + + query mir_for_ctfe( + key: DefId + ) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query mir_promoted(key: LocalDefId) -> ( + &'tcx Steal>, + &'tcx Steal>> + ) { + no_hash + desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } + } + + query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> { + desc { + |tcx| "finding symbols for captures of closure `{}`", + tcx.def_path_str(key) + } + } + + /// Returns names of captured upvars for closures and coroutines. + /// + /// Here are some examples: + /// - `name__field1__field2` when the upvar is captured by value. + /// - `_ref__name__field` when the upvar is captured by reference. + /// + /// For coroutines this only contains upvars that are shared by all states. + query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec { + arena_cache + desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { + arena_cache + desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that + /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck. + /// + /// However, we replace each free region in the MIR body with a unique region inference + /// variable. As we may rely on structural identity when proving goals this may cause a + /// goal to no longer hold. We store obligations for which this may happen during HIR + /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck + /// encounters an unexpected error. We expect this to result in an error when used and + /// delay a bug if it does not. + query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { + |tcx| "reproving potentially region dependent HIR typeck goals for `{}", + tcx.def_path_str(key) + } + } + + /// MIR after our optimization passes have run. This is MIR that is ready + /// for codegen. This is also the only query that can fetch non-local MIR, at present. + query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on + /// this def and any enclosing defs, up to the crate root. + /// + /// Returns `false` if `#[coverage(off)]` was found, or `true` if + /// either `#[coverage(on)]` or no coverage attribute was found. + query coverage_attr_on(key: LocalDefId) -> bool { + desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) } + feedable + } + + /// Scans through a function's MIR after MIR optimizations, to prepare the + /// information needed by codegen when `-Cinstrument-coverage` is active. + /// + /// This includes the details of where to insert `llvm.instrprof.increment` + /// intrinsics, and the expression tables to be embedded in the function's + /// coverage metadata. + /// + /// FIXME(Zalathar): This query's purpose has drifted a bit and should + /// probably be renamed, but that can wait until after the potential + /// follow-ups to #136053 have settled down. + /// + /// Returns `None` for functions that were not instrumented. + query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { + desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } + arena_cache + } + + /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own + /// `DefId`. This function returns all promoteds in the specified body. The body references + /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because + /// after inlining a body may refer to promoteds from other bodies. In that case you still + /// need to use the `DefId` of the original body. + query promoted_mir(key: DefId) -> &'tcx IndexVec> { + desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Erases regions from `ty` to yield a new type. + /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`, + /// however, which uses this query as a kind of cache. + query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { + // This query is not expected to have input -- as a result, it + // is not a good candidates for "replay" because it is essentially a + // pure function of its input (and hence the expectation is that + // no caller would be green **apart** from just these + // queries). Making it anonymous avoids hashing the result, which + // may save a bit of time. + anon + desc { "erasing regions from `{}`", ty } + } + + query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap { + arena_cache + desc { "getting wasm import module map" } + } + + /// Returns the explicitly user-written *predicates and bounds* of the trait given by `DefId`. + /// + /// Traits are unusual, because predicates on associated types are + /// converted into bounds on that type for backwards compatibility: + /// + /// ``` + /// trait X where Self::U: Copy { type U; } + /// ``` + /// + /// becomes + /// + /// ``` + /// trait X { type U: Copy; } + /// ``` + /// + /// [`Self::explicit_predicates_of`] and [`Self::explicit_item_bounds`] will + /// then take the appropriate subsets of the predicates here. + /// + /// # Panics + /// + /// This query will panic if the given definition is not a trait. + query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) } + } + + /// Returns the explicitly user-written *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). + /// + /// You should probably use [`Self::predicates_of`] unless you're looking for + /// predicates with explicit spans for diagnostics purposes. + query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the *inferred outlives-predicates* of the item given by `DefId`. + /// + /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. + /// + /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. + query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { + desc { |tcx| "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the explicitly user-written *super-predicates* of the trait given by `DefId`. + /// + /// These predicates are unelaborated and consequently don't contain transitive super-predicates. + /// + /// This is a subset of the full list of predicates. We store these in a separate map + /// because we must evaluate them even during type conversion, often before the full + /// predicates are available (note that super-predicates must not be cyclic). + query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// The predicates of the trait that are implied during elaboration. + /// + /// This is a superset of the super-predicates of the trait, but a subset of the predicates + /// of the trait. For regular traits, this includes all super-predicates and their + /// associated type bounds. For trait aliases, currently, this includes all of the + /// predicates of the trait alias. + query explicit_implied_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// The Ident is the name of an associated type.The query returns only the subset + /// of supertraits that define the given associated type. This is used to avoid + /// cycles in resolving type-dependent associated item paths like `T::Item`. + query explicit_supertraits_containing_assoc_item( + key: (DefId, rustc_span::Ident) + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", + tcx.def_path_str(key.0), + key.1 + } + } + + /// Compute the conditions that need to hold for a conditionally-const item to be const. + /// That is, compute the set of `[const]` where clauses for a given item. + /// + /// This can be thought of as the `[const]` equivalent of `predicates_of`. These are the + /// predicates that need to be proven at usage sites, and can be assumed at definition. + /// + /// This query also computes the `[const]` where clauses for associated types, which are + /// not "const", but which have item bounds which may be `[const]`. These must hold for + /// the `[const]` item bound to hold. + query const_conditions( + key: DefId + ) -> ty::ConstConditions<'tcx> { + desc { |tcx| "computing the conditions for `{}` to be considered const", + tcx.def_path_str(key) + } + separate_provide_extern + } + + /// Compute the const bounds that are implied for a conditionally-const item. + /// + /// This can be though of as the `[const]` equivalent of `explicit_item_bounds`. These + /// are the predicates that need to proven at definition sites, and can be assumed at + /// usage sites. + query explicit_implied_const_bounds( + key: DefId + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { + desc { |tcx| "computing the implied `[const]` bounds for `{}`", + tcx.def_path_str(key) + } + separate_provide_extern + } + + /// To avoid cycles within the predicates of a single item we compute + /// per-type-parameter predicates for resolving `T::AssocTy`. + query type_param_predicates( + key: (LocalDefId, LocalDefId, rustc_span::Ident) + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) } + } + + query trait_def(key: DefId) -> &'tcx ty::TraitDef { + desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } + arena_cache + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_def(key: DefId) -> ty::AdtDef<'tcx> { + desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_destructor(key: DefId) -> Option { + desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_async_destructor(key: DefId) -> Option { + desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_sizedness_constraint( + key: (DefId, SizedTraitKind) + ) -> Option>> { + desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) } + } + + query adt_dtorck_constraint( + key: DefId + ) -> &'tcx DropckConstraint<'tcx> { + desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } + } + + /// Returns the constness of the function-like[^1] definition given by `DefId`. + /// + /// Tuple struct/variant constructors are *always* const, foreign functions are + /// *never* const. The rest is const iff marked with keyword `const` (or rather + /// its parent in the case of associated functions). + /// + ///

+ /// + /// **Do not call this query** directly. It is only meant to cache the base data for the + /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. + /// + /// Also note that neither of them takes into account feature gates, stability and + /// const predicates/conditions! + /// + ///
+ /// + /// # Panics + /// + /// This query will panic if the given definition is not function-like[^1]. + /// + /// [^1]: Tuple struct/variant constructors, closures and free, associated and foreign functions. + query constness(key: DefId) -> hir::Constness { + desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } + separate_provide_extern + feedable + } + + query asyncness(key: DefId) -> ty::Asyncness { + desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + /// Returns `true` if calls to the function may be promoted. + /// + /// This is either because the function is e.g., a tuple-struct or tuple-variant + /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should + /// be removed in the future in favour of some form of check which figures out whether the + /// function does not inspect the bits of any of its arguments (so is essentially just a + /// constructor function). + query is_promotable_const_fn(key: DefId) -> bool { + desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } + } + + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { + desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. + query coroutine_kind(def_id: DefId) -> Option { + desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + query coroutine_for_closure(def_id: DefId) -> DefId { + desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } + separate_provide_extern + } + + query coroutine_hidden_types( + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + desc { "looking up the hidden types stored across await points in a coroutine" } + } + + /// Gets a map with the variances of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::variances_of`] instead. + /// + ///
+ query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { + arena_cache + desc { "computing the variances for items in this crate" } + } + + /// Returns the (inferred) variances of the item given by `DefId`. + /// + /// The list of variances corresponds to the list of (early-bound) generic + /// parameters of the item (including its parents). + /// + /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. + query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { + desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + cycle_delay_bug + } + + /// Gets a map with the inferred outlives-predicates of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::inferred_outlives_of`] instead. + /// + ///
+ query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> { + arena_cache + desc { "computing the inferred outlives-predicates for items in this crate" } + } + + /// Maps from an impl/trait or struct/variant `DefId` + /// to a list of the `DefId`s of its associated items or fields. + query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { + desc { |tcx| "collecting associated items or fields of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Maps from a trait/impl item to the trait/impl item "descriptor". + query associated_item(key: DefId) -> ty::AssocItem { + desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Collects the associated items defined on a trait or impl. + query associated_items(key: DefId) -> &'tcx ty::AssocItems { + arena_cache + desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } + } + + /// Maps from associated items on a trait to the corresponding associated + /// item on the impl specified by `impl_id`. + /// + /// For example, with the following code + /// + /// ``` + /// struct Type {} + /// // DefId + /// trait Trait { // trait_id + /// fn f(); // trait_f + /// fn g() {} // trait_g + /// } + /// + /// impl Trait for Type { // impl_id + /// fn f() {} // impl_f + /// fn g() {} // impl_g + /// } + /// ``` + /// + /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be + ///`{ trait_f: impl_f, trait_g: impl_g }` + query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap { + arena_cache + desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } + } + + /// Given the `item_def_id` of a trait or impl, return a mapping from associated fn def id + /// to its associated type items that correspond to the RPITITs in its signature. + query associated_types_for_impl_traits_in_trait_or_impl(item_def_id: DefId) -> &'tcx DefIdMap> { + arena_cache + desc { |tcx| "synthesizing RPITIT items for the opaque types for methods in `{}`", tcx.def_path_str(item_def_id) } + separate_provide_extern + } + + /// Given an `impl_id`, return the trait it implements along with some header information. + query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { + desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } + cache_on_disk_if { impl_id.is_local() } + separate_provide_extern + } + + /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due + /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct + /// whose tail is one of those types. + query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool { + desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) } + } + + /// Maps a `DefId` of a type to a list of its inherent impls. + /// Contains implementations of methods that are inherent to a type. + /// Methods in these implementations don't need to be exported. + query inherent_impls(key: DefId) -> &'tcx [DefId] { + desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + desc { |tcx| "collecting all inherent impls for `{:?}`", key } + } + + /// Unsafety-check this `LocalDefId`. + query check_transmutes(key: LocalDefId) { + desc { |tcx| "check transmute calls inside `{}`", tcx.def_path_str(key) } + } + + /// Unsafety-check this `LocalDefId`. + query check_unsafety(key: LocalDefId) { + desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } + } + + /// Checks well-formedness of tail calls (`become f()`). + query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { + desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Returns the types assumed to be well formed while "inside" of the given item. + /// + /// Note that we've liberated the late bound regions of function signatures, so + /// this can not be used to check whether these types are well formed. + query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { + desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } + } + + /// We need to store the assumed_wf_types for an RPITIT so that impls of foreign + /// traits with return-position impl trait in traits can inherit the right wf types. + query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { + desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + /// Computes the signature of the function. + query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + cycle_delay_bug + } + + /// Performs lint checking for the module. + query lint_mod(key: LocalModDefId) { + desc { |tcx| "linting {}", describe_as_module(key, tcx) } + } + + query check_unused_traits(_: ()) { + desc { "checking unused trait imports in crate" } + } + + /// Checks the attributes in the module. + query check_mod_attrs(key: LocalModDefId) { + desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } + } + + /// Checks for uses of unstable APIs in the module. + query check_mod_unstable_api_usage(key: LocalModDefId) { + desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } + } + + query check_mod_privacy(key: LocalModDefId) { + desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } + } + + query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet { + arena_cache + desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } + } + + /// Return the live symbols in the crate for dead code check. + /// + /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). + query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( + LocalDefIdSet, + LocalDefIdMap>, + ), ErrorGuaranteed> { + arena_cache + desc { "finding live symbols in crate" } + } + + query check_mod_deathness(key: LocalModDefId) { + desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } + } + + query check_type_wf(key: ()) -> Result<(), ErrorGuaranteed> { + desc { "checking that types are well-formed" } + return_result_from_ensure_ok + } + + /// Caches `CoerceUnsized` kinds for impls on custom types. + query coerce_unsized_info(key: DefId) -> Result { + desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + return_result_from_ensure_ok + } + + query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { + desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } + cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) } + } + + query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { + desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + + query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } + return_result_from_ensure_ok + } + + /// Borrow-checks the given typeck root, e.g. functions, const/static items, + /// and its children, e.g. closures, inline consts. + query mir_borrowck(key: LocalDefId) -> Result< + &'tcx FxIndexMap>, + ErrorGuaranteed + > { + desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } + } + + /// Gets a complete map from all types to their inherent impls. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) { + desc { "finding all inherent impls defined in crate" } + } + + /// Checks all types in the crate for overlap in their inherent impls. Reports errors. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { + desc { "check for inherent impls that should not be defined in crate" } + return_result_from_ensure_ok + } + + /// Checks all types in the crate for overlap in their inherent impls. Reports errors. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { + desc { "check for overlap between inherent impls defined in this crate" } + return_result_from_ensure_ok + } + + /// Checks whether all impls in the crate pass the overlap check, returning + /// which impls fail it. If all impls are correct, the returned slice is empty. + query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| + "checking whether impl `{}` follows the orphan rules", + tcx.def_path_str(key), + } + return_result_from_ensure_ok + } + + /// Return the set of (transitive) callees that may result in a recursive call to `key`, + /// if we were able to walk all callees. + query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option> { + cycle_fatal + arena_cache + desc { |tcx| + "computing (transitive) callees of `{}` that may recurse", + tcx.def_path_str(key), + } + cache_on_disk_if { true } + } + + /// Obtain all the calls into other local functions + query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { + cycle_fatal + desc { |tcx| + "computing all local function calls in `{}`", + tcx.def_path_str(key.def_id()), + } + } + + /// Computes the tag (if any) for a given type and variant. + /// + /// `None` means that the variant doesn't need a tag (because it is niched). + /// + /// # Panics + /// + /// This query will panic for uninhabited variants and if the passed type is not an enum. + query tag_for_variant( + key: PseudoCanonicalInput<'tcx, (Ty<'tcx>, abi::VariantIdx)>, + ) -> Option { + desc { "computing variant tag for enum" } + } + + /// Evaluates a constant and returns the computed allocation. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::eval_to_const_value_raw`] or + /// [`Self::eval_to_valtree`] instead. + /// + ///
+ query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) + -> EvalToAllocationRawResult<'tcx> { + desc { |tcx| + "const-evaluating + checking `{}`", + key.value.display(tcx) + } + cache_on_disk_if { true } + } + + /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + query eval_static_initializer(key: DefId) -> EvalStaticInitializerRawResult<'tcx> { + desc { |tcx| + "evaluating initializer of static `{}`", + tcx.def_path_str(key) + } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Evaluates const items or anonymous constants[^1] into a representation + /// suitable for the type system and const generics. + /// + ///
+ /// + /// **Do not call this** directly, use one of the following wrappers: + /// [`TyCtxt::const_eval_poly`], [`TyCtxt::const_eval_resolve`], + /// [`TyCtxt::const_eval_instance`], or [`TyCtxt::const_eval_global_id`]. + /// + ///
+ /// + /// [^1]: Such as enum variant explicit discriminants or array lengths. + query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) + -> EvalToConstValueResult<'tcx> { + desc { |tcx| + "simplifying constant for the type system `{}`", + key.value.display(tcx) + } + depth_limit + cache_on_disk_if { true } + } + + /// Evaluate a constant and convert it to a type level constant or + /// return `None` if that is not possible. + query eval_to_valtree( + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> + ) -> EvalToValTreeResult<'tcx> { + desc { "evaluating type-level constant" } + } + + /// Converts a type-level constant value into a MIR constant value. + query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue { + desc { "converting type-level constant value to MIR constant value"} + } + + // FIXME get rid of this with valtrees + query lit_to_const( + key: LitToConstInput<'tcx> + ) -> Option> { + desc { "converting literal to const" } + } + + query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { + desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Performs part of the privacy check and computes effective visibilities. + query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { + eval_always + desc { "checking effective visibilities" } + } + query check_private_in_public(module_def_id: LocalModDefId) { + desc { |tcx| + "checking for private elements in public interfaces for {}", + describe_as_module(module_def_id, tcx) + } + } + + query reachable_set(_: ()) -> &'tcx LocalDefIdSet { + arena_cache + desc { "reachability" } + cache_on_disk_if { true } + } + + /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body; + /// in the case of closures, this will be redirected to the enclosing function. + query region_scope_tree(def_id: DefId) -> &'tcx crate::middle::region::ScopeTree { + desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) } + } + + /// Generates a MIR body for the shim. + query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { + arena_cache + desc { + |tcx| "generating MIR shim for `{}`, instance={:?}", + tcx.def_path_str(key.def_id()), + key + } + } + + /// The `symbol_name` query provides the symbol name for calling a + /// given instance from the local crate. In particular, it will also + /// look up the correct symbol name of instances from upstream crates. + query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> { + desc { "computing the symbol for `{}`", key } + cache_on_disk_if { true } + } + + query def_kind(def_id: DefId) -> DefKind { + desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the definition. + query def_span(def_id: DefId) -> Span { + desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the identifier of the definition. + query def_ident_span(def_id: DefId) -> Option { + desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the type of the definition. + /// Panics if it is not a definition that has a single type. + query ty_span(def_id: LocalDefId) -> Span { + desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + query lookup_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + query lookup_const_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + query lookup_default_body_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up default body stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query should_inherit_track_caller(def_id: DefId) -> bool { + desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } + } + + query inherited_align(def_id: DefId) -> Option { + desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) } + } + + query lookup_deprecation_entry(def_id: DefId) -> Option { + desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Determines whether an item is annotated with `#[doc(hidden)]`. + query is_doc_hidden(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Determines whether an item is annotated with `#[doc(notable_trait)]`. + query is_doc_notable_trait(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } + } + + /// Returns the attributes on the item at `def_id`. + /// + /// Do not use this directly, use `tcx.get_attrs` instead. + query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] { + desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Returns the `CodegenFnAttrs` for the item at `def_id`. + /// + /// If possible, use `tcx.codegen_instance_attrs` instead. That function takes the + /// instance kind into account. + /// + /// For example, the `#[naked]` attribute should be applied for `InstanceKind::Item`, + /// but should not be applied if the instance kind is `InstanceKind::ReifyShim`. + /// Using this query would include the attribute regardless of the actual instance + /// kind at the call site. + query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs { + desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } + arena_cache + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { + desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } + } + + query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { + desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the rendered value of the specified constant or associated constant. + /// Used by rustdoc. + query rendered_const(def_id: DefId) -> &'tcx String { + arena_cache + desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the rendered precise capturing args for an opaque for use in rustdoc. + query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind]> { + desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query impl_parent(def_id: DefId) -> Option { + desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query is_mir_available(key: DefId) -> bool { + desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query own_existential_vtable_entries( + key: DefId + ) -> &'tcx [DefId] { + desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } + } + + query vtable_entries(key: ty::TraitRef<'tcx>) + -> &'tcx [ty::VtblEntry<'tcx>] { + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } + } + + query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { + desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() } + } + + query supertrait_vtable_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option { + desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable", + key.1, key.0 } + } + + query vtable_allocation(key: (Ty<'tcx>, Option>)) -> mir::interpret::AllocId { + desc { |tcx| "vtable const allocation for <{} as {}>", + key.0, + key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or_else(|| "_".to_owned()) + } + } + + query codegen_select_candidate( + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> + ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { + cache_on_disk_if { true } + desc { |tcx| "computing candidate for `{}`", key.value } + } + + /// Return all `impl` blocks in the current crate. + query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap> { + desc { "finding local trait impls" } + } + + /// Return all `impl` blocks of the given trait in the current crate. + query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { + desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } + } + + /// Given a trait `trait_id`, return all known `impl` blocks. + query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { + arena_cache + desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } + } + + query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { + desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } + cache_on_disk_if { true } + return_result_from_ensure_ok + } + query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { + desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } + } + query is_dyn_compatible(trait_id: DefId) -> bool { + desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) } + } + + /// Gets the ParameterEnvironment for a given item; this environment + /// will be in "user-facing" mode, meaning that it is suitable for + /// type-checking etc, and it does not normalize specializable + /// associated types. + /// + /// You should almost certainly not use this. If you already have an InferCtxt, then + /// you should also probably have a `ParamEnv` from when it was built. If you don't, + /// then you should take a `TypingEnv` to ensure that you handle opaque types correctly. + query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { + desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } + feedable + } + + /// Like `param_env`, but returns the `ParamEnv` after all opaque types have been + /// replaced with their hidden type. This is used in the old trait solver + /// when in `PostAnalysis` mode and should not be called directly. + query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> { + desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } + } + + /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, + /// `ty.is_copy()`, etc, since that will prune the environment where possible. + query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Copy`", env.value } + } + /// Trait selection queries. These are best used by invoking `ty.is_use_cloned_modulo_regions()`, + /// `ty.is_use_cloned()`, etc, since that will prune the environment where possible. + query is_use_cloned_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `UseCloned`", env.value } + } + /// Query backing `Ty::is_sized`. + query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Sized`", env.value } + } + /// Query backing `Ty::is_freeze`. + query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is freeze", env.value } + } + /// Query backing `Ty::is_unsafe_unpin`. + query is_unsafe_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `UnsafeUnpin`", env.value } + } + /// Query backing `Ty::is_unpin`. + query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Unpin`", env.value } + } + /// Query backing `Ty::is_async_drop`. + query is_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `AsyncDrop`", env.value } + } + /// Query backing `Ty::needs_drop`. + query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` needs drop", env.value } + } + /// Query backing `Ty::needs_async_drop`. + query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` needs async drop", env.value } + } + /// Query backing `Ty::has_significant_drop_raw`. + query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` has a significant drop", env.value } + } + + /// Query backing `Ty::is_structural_eq_shallow`. + /// + /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types + /// correctly. + query has_structural_eq_impl(ty: Ty<'tcx>) -> bool { + desc { + "computing whether `{}` implements `StructuralPartialEq`", + ty + } + } + + /// A list of types where the ADT requires drop if and only if any of + /// those types require drop. If the ADT is known to always need drop + /// then `Err(AlwaysRequiresDrop)` is returned. + query adt_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` needs drop", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + /// A list of types where the ADT requires async drop if and only if any of + /// those types require async drop. If the ADT is known to always need async drop + /// then `Err(AlwaysRequiresDrop)` is returned. + query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` needs async drop", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + /// A list of types where the ADT requires drop if and only if any of those types + /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor` + /// is considered to not be significant. A drop is significant if it is implemented + /// by the user or does anything that will have any observable behavior (other than + /// freeing up memory). If the ADT is known to have a significant destructor then + /// `Err(AlwaysRequiresDrop)` is returned. + query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } + } + + /// Returns a list of types which (a) have a potentially significant destructor + /// and (b) may be dropped as a result of dropping a value of some type `ty` + /// (in the given environment). + /// + /// The idea of "significant" drop is somewhat informal and is used only for + /// diagnostics and edition migrations. The idea is that a significant drop may have + /// some visible side-effect on execution; freeing memory is NOT considered a side-effect. + /// The rules are as follows: + /// * Type with no explicit drop impl do not have significant drop. + /// * Types with a drop impl are assumed to have significant drop unless they have a `#[rustc_insignificant_dtor]` annotation. + /// + /// Note that insignificant drop is a "shallow" property. A type like `Vec` does not + /// have significant drop but the type `LockGuard` does, and so if `ty = Vec` + /// then the return value would be `&[LockGuard]`. + /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, + /// because this query partially depends on that query. + /// Otherwise, there is a risk of query cycles. + query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { + desc { |tcx| "computing when `{}` has a significant destructor", ty.value } + } + + /// Computes the layout of a type. Note that this implicitly + /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. + query layout_of( + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> + ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { + depth_limit + desc { "computing layout of `{}`", key.value } + // we emit our own error during query cycle handling + cycle_delay_bug + } + + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceKind::Virtual`. + query fn_abi_of_fn_ptr( + key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}` function pointers", key.value.0 } + } + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceKind::Virtual` instance (of `::fn`). + query fn_abi_of_instance( + key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}`", key.value.0 } + } + + query dylib_dependency_formats(_: CrateNum) + -> &'tcx [(CrateNum, LinkagePreference)] { + desc { "getting dylib dependency formats of crate" } + separate_provide_extern + } + + query dependency_formats(_: ()) -> &'tcx Arc { + arena_cache + desc { "getting the linkage format of all dependencies" } + } + + query is_compiler_builtins(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate is_compiler_builtins" } + separate_provide_extern + } + query has_global_allocator(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always + cycle_fatal + desc { "checking if the crate has_global_allocator" } + separate_provide_extern + } + query has_alloc_error_handler(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always + cycle_fatal + desc { "checking if the crate has_alloc_error_handler" } + separate_provide_extern + } + query has_panic_handler(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate has_panic_handler" } + separate_provide_extern + } + query is_profiler_runtime(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if a crate is `#![profiler_runtime]`" } + separate_provide_extern + } + query has_ffi_unwind_calls(key: LocalDefId) -> bool { + desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + query required_panic_strategy(_: CrateNum) -> Option { + cycle_fatal + desc { "getting a crate's required panic strategy" } + separate_provide_extern + } + query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { + cycle_fatal + desc { "getting a crate's configured panic-in-drop strategy" } + separate_provide_extern + } + query is_no_builtins(_: CrateNum) -> bool { + cycle_fatal + desc { "getting whether a crate has `#![no_builtins]`" } + separate_provide_extern + } + query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { + cycle_fatal + desc { "getting a crate's symbol mangling version" } + separate_provide_extern + } + + query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> { + eval_always + desc { "getting crate's ExternCrateData" } + separate_provide_extern + } + + query specialization_enabled_in(cnum: CrateNum) -> bool { + desc { "checking whether the crate enabled `specialization`/`min_specialization`" } + separate_provide_extern + } + + query specializes(_: (DefId, DefId)) -> bool { + desc { "computing whether impls specialize one another" } + } + query in_scope_traits_map(_: hir::OwnerId) + -> Option<&'tcx ItemLocalMap>> { + desc { "getting traits in scope at a block" } + } + + /// Returns whether the impl or associated function has the `default` keyword. + /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`. + query defaultness(def_id: DefId) -> hir::Defaultness { + desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + /// Returns whether the field corresponding to the `DefId` has a default field value. + query default_field(def_id: DefId) -> Option { + desc { |tcx| "looking up the `const` corresponding to the default for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + // The `DefId`s of all non-generic functions and statics in the given crate + // that can be reached from outside the crate. + // + // We expect this items to be available for being linked to. + // + // This query can also be called for `LOCAL_CRATE`. In this case it will + // compute which items will be reachable to other crates, taking into account + // the kind of crate that is currently compiled. Crates with only a + // C interface have fewer reachable things. + // + // Does not include external symbols that don't have a corresponding DefId, + // like the compiler-generated `main` function and so on. + query reachable_non_generics(_: CrateNum) + -> &'tcx DefIdMap { + arena_cache + desc { "looking up the exported symbols of a crate" } + separate_provide_extern + } + query is_reachable_non_generic(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + query is_unreachable_local_definition(def_id: LocalDefId) -> bool { + desc { |tcx| + "checking whether `{}` is reachable from outside the crate", + tcx.def_path_str(def_id), + } + } + + /// The entire set of monomorphizations the local crate can safely + /// link to because they are exported from upstream crates. Do + /// not depend on this directly, as its value changes anytime + /// a monomorphization gets added or removed in any upstream + /// crate. Instead use the narrower `upstream_monomorphizations_for`, + /// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or, + /// even better, `Instance::upstream_monomorphization()`. + query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { + arena_cache + desc { "collecting available upstream monomorphizations" } + } + + /// Returns the set of upstream monomorphizations available for the + /// generic function identified by the given `def_id`. The query makes + /// sure to make a stable selection if the same monomorphization is + /// available in multiple upstream crates. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + query upstream_monomorphizations_for(def_id: DefId) + -> Option<&'tcx UnordMap, CrateNum>> + { + desc { |tcx| + "collecting available upstream monomorphizations for `{}`", + tcx.def_path_str(def_id), + } + separate_provide_extern + } + + /// Returns the upstream crate that exports drop-glue for the given + /// type (`args` is expected to be a single-item list containing the + /// type one wants drop-glue for). + /// + /// This is a subset of `upstream_monomorphizations_for` in order to + /// increase dep-tracking granularity. Otherwise adding or removing any + /// type with drop-glue in any upstream crate would invalidate all + /// functions calling drop-glue of an upstream type. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + /// + /// NOTE: This query could easily be extended to also support other + /// common functions that have are large set of monomorphizations + /// (like `Clone::clone` for example). + query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { + desc { "available upstream drop-glue for `{:?}`", args } + } + + /// Returns the upstream crate that exports async-drop-glue for + /// the given type (`args` is expected to be a single-item list + /// containing the type one wants async-drop-glue for). + /// + /// This is a subset of `upstream_monomorphizations_for` in order + /// to increase dep-tracking granularity. Otherwise adding or + /// removing any type with async-drop-glue in any upstream crate + /// would invalidate all functions calling async-drop-glue of an + /// upstream type. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + /// + /// NOTE: This query could easily be extended to also support other + /// common functions that have are large set of monomorphizations + /// (like `Clone::clone` for example). + query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { + desc { "available upstream async-drop-glue for `{:?}`", args } + } + + /// Returns a list of all `extern` blocks of a crate. + query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap { + arena_cache + desc { "looking up the foreign modules of a linked crate" } + separate_provide_extern + } + + /// Lint against `extern fn` declarations having incompatible types. + query clashing_extern_declarations(_: ()) { + desc { "checking `extern fn` declarations are compatible" } + } + + /// Identifies the entry-point (e.g., the `main` function) for a given + /// crate, returning `None` if there is no entry point (such as for library crates). + query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { + desc { "looking up the entry function of a crate" } + } + + /// Finds the `rustc_proc_macro_decls` item of a crate. + query proc_macro_decls_static(_: ()) -> Option { + desc { "looking up the proc macro declarations for a crate" } + } + + // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. + // Changing the name should cause a compiler error, but in case that changes, be aware. + // + // The hash should not be calculated before the `analysis` pass is complete, specifically + // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental + // compilation is enabled calculating this hash can freeze this structure too early in + // compilation and cause subsequent crashes when attempting to write to `definitions` + query crate_hash(_: CrateNum) -> Svh { + eval_always + desc { "looking up the hash a crate" } + separate_provide_extern + } + + /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. + query crate_host_hash(_: CrateNum) -> Option { + eval_always + desc { "looking up the hash of a host version of a crate" } + separate_provide_extern + } + + /// Gets the extra data to put in each output filename for a crate. + /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. + query extra_filename(_: CrateNum) -> &'tcx String { + arena_cache + eval_always + desc { "looking up the extra filename for a crate" } + separate_provide_extern + } + + /// Gets the paths where the crate came from in the file system. + query crate_extern_paths(_: CrateNum) -> &'tcx Vec { + arena_cache + eval_always + desc { "looking up the paths for extern crates" } + separate_provide_extern + } + + /// Given a crate and a trait, look up all impls of that trait in the crate. + /// Return `(impl_id, self_ty)`. + query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { + desc { "looking up implementations of a trait in a crate" } + separate_provide_extern + } + + /// Collects all incoherent impls for the given crate and type. + /// + /// Do not call this directly, but instead use the `incoherent_impls` query. + /// This query is only used to get the data necessary for that query. + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + desc { |tcx| "collecting all impls for a type in a crate" } + separate_provide_extern + } + + /// Get the corresponding native library from the `native_libraries` query + query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { + desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } + } + + query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] { + desc { "inheriting delegation signature" } + } + + /// Does lifetime resolution on items. Importantly, we can't resolve + /// lifetimes directly on things like trait methods, because of trait params. + /// See `rustc_resolve::late::lifetimes` for details. + query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars<'tcx> { + arena_cache + desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } + } + query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { + desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } + } + query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { + desc { |tcx| "testing if a region is late bound inside `{}`", tcx.def_path_str(owner_id) } + } + /// Returns the *default lifetime* to be used if a trait object type were to be passed for + /// the type parameter given by `DefId`. + /// + /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically + /// print the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples + /// + /// - For `T` in `struct Foo<'a, T: 'a>(&'a T);`, this would be `Param('a)` + /// - For `T` in `struct Bar<'a, T>(&'a T);`, this would be `Empty` + /// + /// # Panics + /// + /// This query will panic if the given definition is not a type parameter. + query object_lifetime_default(def_id: DefId) -> ObjectLifetimeDefault { + desc { "looking up lifetime defaults for type parameter `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + query late_bound_vars_map(owner_id: hir::OwnerId) + -> &'tcx SortedMap>> { + desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } + } + /// For an opaque type, return the list of (captured lifetime, inner generic param). + /// ```ignore (illustrative) + /// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into + 'b { ... } + /// ``` + /// + /// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound. + /// + /// After hir_ty_lowering, we get: + /// ```ignore (pseudo-code) + /// opaque foo::<'a>::opaque<'_a, '_b>: Into> + '_b; + /// ^^^^^^^^ inner generic params + /// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b> + /// ^^^^^^ captured lifetimes + /// ``` + query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] { + desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } + } + + /// Computes the visibility of the provided `def_id`. + /// + /// If the item from the `def_id` doesn't have a visibility, it will panic. For example + /// a generic type parameter will panic if you call this method on it: + /// + /// ``` + /// use std::fmt::Debug; + /// + /// pub trait Foo {} + /// ``` + /// + /// In here, if you call `visibility` on `T`, it'll panic. + query visibility(def_id: DefId) -> ty::Visibility { + desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { + desc { "computing the uninhabited predicate of `{:?}`", key } + } + + /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead. + query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> { + desc { "computing the uninhabited predicate of `{}`", key } + } + + query dep_kind(_: CrateNum) -> CrateDepKind { + eval_always + desc { "fetching what a dependency looks like" } + separate_provide_extern + } + + /// Gets the name of the crate. + query crate_name(_: CrateNum) -> Symbol { + feedable + desc { "fetching what a crate is named" } + separate_provide_extern + } + query module_children(def_id: DefId) -> &'tcx [ModChild] { + desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the number of definitions in a foreign crate. + /// + /// This allows external tools to iterate over all definitions in a foreign crate. + /// + /// This should never be used for the local crate, instead use `iter_local_def_id`. + query num_extern_def_ids(_: CrateNum) -> usize { + desc { "fetching the number of definitions in a crate" } + separate_provide_extern + } + + query lib_features(_: CrateNum) -> &'tcx LibFeatures { + desc { "calculating the lib features defined in a crate" } + separate_provide_extern + arena_cache + } + /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` + /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute + /// exists, then this map will have a `impliee -> implier` entry. + /// + /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should + /// specify their implications (both `implies` and `implied_by`). If only one of the two + /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this + /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is + /// reported, only the `#[stable]` attribute information is available, so the map is necessary + /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` + /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of + /// unstable feature" error for a feature that was implied. + query stability_implications(_: CrateNum) -> &'tcx UnordMap { + arena_cache + desc { "calculating the implications between `#[unstable]` features defined in a crate" } + separate_provide_extern + } + /// Whether the function is an intrinsic + query intrinsic_raw(def_id: DefId) -> Option { + desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) } + separate_provide_extern + } + /// Returns the lang items defined in another crate by loading it from metadata. + query get_lang_items(_: ()) -> &'tcx LanguageItems { + arena_cache + eval_always + desc { "calculating the lang items map" } + } + + /// Returns all diagnostic items defined in all crates. + query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { + arena_cache + eval_always + desc { "calculating the diagnostic items map" } + } + + /// Returns the lang items defined in another crate by loading it from metadata. + query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] { + desc { "calculating the lang items defined in a crate" } + separate_provide_extern + } + + /// Returns the diagnostic items defined in a crate. + query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { + arena_cache + desc { "calculating the diagnostic items map in a crate" } + separate_provide_extern + } + + query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { + desc { "calculating the missing lang items in a crate" } + separate_provide_extern + } + + /// The visible parent map is a map from every item to a visible parent. + /// It prefers the shortest visible path to an item. + /// Used for diagnostics, for example path trimming. + /// The parents are modules, enums or traits. + query visible_parent_map(_: ()) -> &'tcx DefIdMap { + arena_cache + desc { "calculating the visible parent map" } + } + /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. + /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. + query trimmed_def_paths(_: ()) -> &'tcx DefIdMap { + arena_cache + desc { "calculating trimmed def paths" } + } + query missing_extern_crate_item(_: CrateNum) -> bool { + eval_always + desc { "seeing if we're missing an `extern crate` item for this crate" } + separate_provide_extern + } + query used_crate_source(_: CrateNum) -> &'tcx Arc { + arena_cache + eval_always + desc { "looking at the source for a crate" } + separate_provide_extern + } + + /// Returns the debugger visualizers defined for this crate. + /// NOTE: This query has to be marked `eval_always` because it reads data + /// directly from disk that is not tracked anywhere else. I.e. it + /// represents a genuine input to the query system. + query debugger_visualizers(_: CrateNum) -> &'tcx Vec { + arena_cache + desc { "looking up the debugger visualizers for this crate" } + separate_provide_extern + eval_always + } + + query postorder_cnums(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "generating a postorder list of CrateNums" } + } + /// Returns whether or not the crate with CrateNum 'cnum' + /// is marked as a private dependency + query is_private_dep(c: CrateNum) -> bool { + eval_always + desc { "checking whether crate `{}` is a private dependency", c } + separate_provide_extern + } + query allocator_kind(_: ()) -> Option { + eval_always + desc { "getting the allocator kind for the current crate" } + } + query alloc_error_handler_kind(_: ()) -> Option { + eval_always + desc { "alloc error handler kind for the current crate" } + } + + query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { + desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } + } + + /// All available crates in the graph, including those that should not be user-facing + /// (such as private crates). + query crates(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "fetching all foreign CrateNum instances" } + } + + // Crates that are loaded non-speculatively (not for diagnostics or doc links). + // FIXME: This is currently only used for collecting lang items, but should be used instead of + // `crates` in most other cases too. + query used_crates(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } + } + + /// All crates that share the same name as crate `c`. + /// + /// This normally occurs when multiple versions of the same dependency are present in the + /// dependency tree. + query duplicate_crate_names(c: CrateNum) -> &'tcx [CrateNum] { + desc { "fetching `CrateNum`s with same name as `{c:?}`" } + } + + /// A list of all traits in a crate, used by rustdoc and error reporting. + query traits(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all traits in a crate" } + separate_provide_extern + } + + query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all trait impls in a crate" } + separate_provide_extern + } + + query stable_order_of_exportable_impls(_: CrateNum) -> &'tcx FxIndexMap { + desc { "fetching the stable impl's order" } + separate_provide_extern + } + + query exportable_items(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all exportable items in a crate" } + separate_provide_extern + } + + /// The list of non-generic symbols exported from the given crate. + /// + /// This is separate from exported_generic_symbols to avoid having + /// to deserialize all non-generic symbols too for upstream crates + /// in the upstream_monomorphizations query. + /// + /// - All names contained in `exported_non_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported non-generic symbols for crate `{}`", cnum} + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + /// The list of generic symbols exported from the given crate. + /// + /// - All names contained in `exported_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported generic symbols for crate `{}`", cnum} + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> { + eval_always + desc { "collect_and_partition_mono_items" } + } + + query is_codegened_item(def_id: DefId) -> bool { + desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } + } + + query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { + desc { "getting codegen unit `{sym}`" } + } + + query backend_optimization_level(_: ()) -> OptLevel { + desc { "optimization level used by backend" } + } + + /// Return the filenames where output artefacts shall be stored. + /// + /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` + /// has been destroyed. + query output_filenames(_: ()) -> &'tcx Arc { + feedable + desc { "getting output filenames" } + arena_cache + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_projection( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_free_alias( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_inherent_projection( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_generic_arg_after_erasing_regions( + goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> + ) -> Result, NoSolution> { + desc { "normalizing `{}`", goal.value } + } + + query implied_outlives_bounds( + key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool) + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, + > { + desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 } + } + + /// Do not call this query directly: + /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. + query dropck_outlives( + goal: CanonicalDropckOutlivesGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, + NoSolution, + > { + desc { "computing dropck types for `{}`", goal.canonical.value.value.dropped_ty } + } + + /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or + /// `infcx.predicate_must_hold()` instead. + query evaluate_obligation( + goal: CanonicalPredicateGoal<'tcx> + ) -> Result { + desc { "evaluating trait selection obligation `{}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `Eq` type-op + query type_op_ascribe_user_type( + goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, + NoSolution, + > { + desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `ProvePredicate` type-op + query type_op_prove_predicate( + goal: CanonicalTypeOpProvePredicateGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, + NoSolution, + > { + desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_ty( + goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_clause( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_poly_fn_sig( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_fn_sig( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { + desc { |tcx| + "checking impossible instantiated predicates: `{}`", + tcx.def_path_str(key.0) + } + } + + query is_impossible_associated_item(key: (DefId, DefId)) -> bool { + desc { |tcx| + "checking if `{}` is impossible to reference within `{}`", + tcx.def_path_str(key.1), + tcx.def_path_str(key.0), + } + } + + query method_autoderef_steps( + goal: CanonicalMethodAutoderefStepsGoal<'tcx> + ) -> MethodAutoderefStepsResult<'tcx> { + desc { "computing autoderef types for `{}`", goal.canonical.value.value.self_ty } + } + + /// Used by `-Znext-solver` to compute proof trees. + query evaluate_root_goal_for_proof_tree_raw( + goal: solve::CanonicalInput<'tcx>, + ) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe>) { + no_hash + desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate } + } + + /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! + query rust_target_features(_: CrateNum) -> &'tcx UnordMap { + arena_cache + eval_always + desc { "looking up Rust target features" } + } + + query implied_target_features(feature: Symbol) -> &'tcx Vec { + arena_cache + eval_always + desc { "looking up implied target features" } + } + + query features_query(_: ()) -> &'tcx rustc_feature::Features { + feedable + desc { "looking up enabled feature gates" } + } + + query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { + feedable + no_hash + desc { "the ast before macro expansion and name resolution" } + } + + /// Attempt to resolve the given `DefId` to an `Instance`, for the + /// given generics args (`GenericArgsRef`), returning one of: + /// * `Ok(Some(instance))` on success + /// * `Ok(None)` when the `GenericArgsRef` are still too generic, + /// and therefore don't allow finding the final `Instance` + /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process + /// couldn't complete due to errors elsewhere - this is distinct + /// from `Ok(None)` to avoid misleading diagnostics when an error + /// has already been/will be emitted, for the original cause. + query resolve_instance_raw( + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> + ) -> Result>, ErrorGuaranteed> { + desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) } + } + + query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + desc { "revealing opaque types in `{:?}`", key } + } + + query limits(key: ()) -> Limits { + desc { "looking up limits" } + } + + /// Performs an HIR-based well-formed check on the item with the given `HirId`. If + /// we get an `Unimplemented` error that matches the provided `Predicate`, return + /// the cause of the newly created obligation. + /// + /// This is only used by error-reporting code to get a better cause (in particular, a better + /// span) for an *existing* error. Therefore, it is best-effort, and may never handle + /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, + /// because the `ty::Ty`-based wfcheck is always run. + query diagnostic_hir_wf_check( + key: (ty::Predicate<'tcx>, WellFormedLoc) + ) -> Option<&'tcx ObligationCause<'tcx>> { + arena_cache + eval_always + no_hash + desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } + } + + /// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, + /// `--target` and similar). + query global_backend_features(_: ()) -> &'tcx Vec { + arena_cache + eval_always + desc { "computing the backend features for CLI flags" } + } + + query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { + desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } + } + + /// This takes the def-id of an associated item from a impl of a trait, + /// and checks its validity against the trait item it corresponds to. + /// + /// Any other def id will ICE. + query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + query deduced_param_attrs(def_id: DefId) -> &'tcx [DeducedParamAttrs] { + desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap { + eval_always + desc { "resolutions for documentation links for a module" } + separate_provide_extern + } + + query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] { + eval_always + desc { "traits in scope for documentation links for a module" } + separate_provide_extern + } + + /// Get all item paths that were stripped by a `#[cfg]` in a particular crate. + /// Should not be called for the local crate before the resolver outputs are created, as it + /// is only fed there. + query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { + desc { "getting cfg-ed out item names" } + separate_provide_extern + } + + query generics_require_sized_self(def_id: DefId) -> bool { + desc { "check whether the item has a `where Self: Sized` bound" } + } + + query cross_crate_inlinable(def_id: DefId) -> bool { + desc { "whether the item should be made inlinable across crates" } + separate_provide_extern + } + + /// Perform monomorphization-time checking on this item. + /// This is used for lints/errors that can only be checked once the instance is fully + /// monomorphized. + query check_mono_item(key: ty::Instance<'tcx>) { + desc { "monomorphization-time checking" } + } + + /// Builds the set of functions that should be skipped for the move-size check. + query skip_move_check_fns(_: ()) -> &'tcx FxIndexSet { + arena_cache + desc { "functions to skip for move-size check" } + } + + query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { + desc { "collecting items used by `{}`", key.0 } + cache_on_disk_if { true } + } + + query size_estimate(key: ty::Instance<'tcx>) -> usize { + desc { "estimating codegen size of `{}`", key } + cache_on_disk_if { true } + } + + query anon_const_kind(def_id: DefId) -> ty::AnonConstKind { + desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query trivial_const(def_id: DefId) -> Option<(mir::ConstValue, Ty<'tcx>)> { + desc { |tcx| "checking if `{}` is a trivial const", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Checks for the nearest `#[sanitize(xyz = "off")]` or + /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the + /// crate root. + /// + /// Returns the sanitizer settings for this def. + query sanitizer_settings_for(key: LocalDefId) -> SanitizerFnAttrs { + desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } + feedable + } + + query check_externally_implementable_items(_: ()) { + desc { "check externally implementable items" } + } + + /// Returns a list of all `externally implementable items` crate. + query externally_implementable_items(cnum: CrateNum) -> &'tcx FxIndexMap)> { + arena_cache + desc { "looking up the externally implementable items of a crate" } + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + query is_rhs_type_const(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is a rhs type const", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } +} + +rustc_with_all_queries! { define_callbacks! } +rustc_feedable_queries! { define_feedable! } diff --git a/compiler/rustc_middle/src/query/arena_cached.rs b/compiler/rustc_middle/src/query/arena_cached.rs index ec6e466ff688..7c7ad1262260 100644 --- a/compiler/rustc_middle/src/query/arena_cached.rs +++ b/compiler/rustc_middle/src/query/arena_cached.rs @@ -1,3 +1,9 @@ +use std::mem; + +use rustc_arena::TypedArena; + +use crate::ty::TyCtxt; + /// Helper trait that allows `arena_cache` queries to return `Option<&T>` /// instead of `&Option`, and avoid allocating `None` in the arena. /// @@ -11,10 +17,11 @@ pub trait ArenaCached<'tcx>: Sized { /// Type that is stored in the arena. type Allocated: 'tcx; - /// Takes a provided value, and allocates it in the arena (if appropriate) - /// with the help of the given `arena_alloc` closure. + /// Takes a provided value, and allocates it in an appropriate arena, + /// unless the particular value doesn't need allocation (e.g. `None`). fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, + tcx: TyCtxt<'tcx>, + typed_arena: &'tcx TypedArena, value: Self::Provided, ) -> Self; } @@ -23,12 +30,9 @@ impl<'tcx, T> ArenaCached<'tcx> for &'tcx T { type Provided = T; type Allocated = T; - fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, - value: Self::Provided, - ) -> Self { + fn alloc_in_arena(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena, value: T) -> Self { // Just allocate in the arena normally. - arena_alloc(value) + do_alloc(tcx, typed_arena, value) } } @@ -38,10 +42,17 @@ impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { type Allocated = T; fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, - value: Self::Provided, + tcx: TyCtxt<'tcx>, + typed_arena: &'tcx TypedArena, + value: Option, ) -> Self { // Don't store None in the arena, and wrap the allocated reference in Some. - value.map(arena_alloc) + try { do_alloc(tcx, typed_arena, value?) } } } + +/// Allocates a value in either its dedicated arena, or in the common dropless +/// arena, depending on whether it needs to be dropped. +fn do_alloc<'tcx, T>(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena, value: T) -> &'tcx T { + if mem::needs_drop::() { typed_arena.alloc(value) } else { tcx.arena.dropless.alloc(value) } +} diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_middle/src/query/caches.rs similarity index 89% rename from compiler/rustc_query_system/src/query/caches.rs rename to compiler/rustc_middle/src/query/caches.rs index 30b5d7e59549..7424492ddc1f 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_middle/src/query/caches.rs @@ -3,20 +3,25 @@ use std::hash::Hash; use std::sync::OnceLock; use rustc_data_structures::sharded::ShardedHashMap; +use rustc_data_structures::stable_hasher::HashStable; pub use rustc_data_structures::vec_cache::VecCache; use rustc_hir::def_id::LOCAL_CRATE; use rustc_index::Idx; +use rustc_query_system::ich::StableHashingContext; use rustc_span::def_id::{DefId, DefIndex}; use crate::dep_graph::DepNodeIndex; +/// Traits that all query keys must satisfy. +pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable>; + /// Trait for types that serve as an in-memory cache for query results, /// for a given key (argument) type and value (return) type. /// /// Types implementing this trait are associated with actual key/value types /// by the `Cache` associated type of the `rustc_middle::query::Key` trait. pub trait QueryCache: Sized { - type Key: Hash + Eq + Copy + Debug; + type Key: QueryCacheKey; type Value: Copy; /// Returns the cached value (and other information) associated with the @@ -30,6 +35,8 @@ pub trait QueryCache: Sized { fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex); fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)); + + fn len(&self) -> usize; } /// In-memory cache for queries whose keys aren't suitable for any of the @@ -46,7 +53,7 @@ impl Default for DefaultCache { impl QueryCache for DefaultCache where - K: Eq + Hash + Copy + Debug, + K: QueryCacheKey, V: Copy, { type Key = K; @@ -71,6 +78,10 @@ where } } } + + fn len(&self) -> usize { + self.cache.len() + } } /// In-memory cache for queries whose key type only has one value (e.g. `()`). @@ -107,6 +118,10 @@ where f(&(), &value.0, value.1) } } + + fn len(&self) -> usize { + self.cache.get().is_some().into() + } } /// In-memory cache for queries whose key is a [`DefId`]. @@ -157,11 +172,15 @@ where }); self.foreign.iter(f); } + + fn len(&self) -> usize { + self.local.len() + self.foreign.len() + } } impl QueryCache for VecCache where - K: Idx + Eq + Hash + Copy + Debug, + K: Idx + QueryCacheKey, V: Copy, { type Key = K; @@ -180,4 +199,8 @@ where fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { self.iter(f) } + + fn len(&self) -> usize { + self.len() + } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 940cc30c17e6..4d4833b4943e 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -1,3 +1,10 @@ +//! To improve compile times and code size for the compiler itself, query +//! values are "erased" in some contexts (e.g. inside in-memory cache types), +//! to reduce the number of generic instantiations created during codegen. +//! +//! See for some bootstrap-time +//! and performance benchmarks. + use std::ffi::OsStr; use std::intrinsics::transmute_unchecked; use std::mem::MaybeUninit; @@ -8,144 +15,175 @@ use rustc_span::source_map::Spanned; use crate::mir::interpret::EvalToValTreeResult; use crate::mir::mono::{MonoItem, NormalizationErrorInMono}; -use crate::query::CyclePlaceholder; +use crate::query::plumbing::CyclePlaceholder; use crate::traits::solve; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, traits}; +/// Internal implementation detail of [`Erased`]. #[derive(Copy, Clone)] -pub struct Erased { - // We use `MaybeUninit` here so we can store any value - // in `data` since we aren't actually storing a `T`. - data: MaybeUninit, +pub struct ErasedData { + /// We use `MaybeUninit` here to make sure it's legal to store a transmuted + /// value that isn't actually of type `Storage`. + data: MaybeUninit, } -pub trait EraseType: Copy { - type Result: Copy; +/// Trait for types that can be erased into [`Erased`]. +/// +/// Erasing and unerasing values is performed by [`erase_val`] and [`restore_val`]. +/// +/// FIXME: This whole trait could potentially be replaced by `T: Copy` and the +/// storage type `[u8; size_of::()]` when support for that is more mature. +pub trait Erasable: Copy { + /// Storage type to used for erased values of this type. + /// Should be `[u8; N]`, where N is equal to `size_of::`. + /// + /// [`ErasedData`] wraps this storage type in `MaybeUninit` to ensure that + /// transmutes to/from erased storage are well-defined. + type Storage: Copy; } -// Allow `type_alias_bounds` since compilation will fail without `EraseType`. -#[allow(type_alias_bounds)] -pub type Erase = Erased; +/// A value of `T` that has been "erased" into some opaque storage type. +/// +/// This is helpful for reducing the number of concrete instantiations needed +/// during codegen when building the compiler. +/// +/// Using an opaque type alias allows the type checker to enforce that +/// `Erased` and `Erased` are still distinct types, while allowing +/// monomorphization to see that they might actually use the same storage type. +pub type Erased = ErasedData; +/// Erases a value of type `T` into `Erased`. +/// +/// `Erased` and `Erased` are type-checked as distinct types, but codegen +/// can see whether they actually have the same storage type. +/// +/// FIXME: This might have soundness issues with erasable types that don't +/// implement the same auto-traits as `[u8; _]`; see +/// #[inline(always)] -#[define_opaque(Erase)] -pub fn erase(src: T) -> Erase { +#[define_opaque(Erased)] +pub fn erase_val(value: T) -> Erased { // Ensure the sizes match const { - if size_of::() != size_of::() { - panic!("size of T must match erased type T::Result") + if size_of::() != size_of::() { + panic!("size of T must match erased type ::Storage") } }; - Erased::<::Result> { + ErasedData::<::Storage> { // `transmute_unchecked` is needed here because it does not have `transmute`'s size check - // (and thus allows to transmute between `T` and `MaybeUninit`) (we do the size + // (and thus allows to transmute between `T` and `MaybeUninit`) (we do the size // check ourselves in the `const` block above). // // `transmute_copy` is also commonly used for this (and it would work here since - // `EraseType: Copy`), but `transmute_unchecked` better explains the intent. + // `Erasable: Copy`), but `transmute_unchecked` better explains the intent. // // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. - data: unsafe { transmute_unchecked::>(src) }, + data: unsafe { transmute_unchecked::>(value) }, } } -/// Restores an erased value. +/// Restores an erased value to its real type. +/// +/// This relies on the fact that `Erased` and `Erased` are type-checked +/// as distinct types, even if they use the same storage type. #[inline(always)] -#[define_opaque(Erase)] -pub fn restore(value: Erase) -> T { - let value: Erased<::Result> = value; - // See comment in `erase` for why we use `transmute_unchecked`. +#[define_opaque(Erased)] +pub fn restore_val(erased_value: Erased) -> T { + let ErasedData { data }: ErasedData<::Storage> = erased_value; + // See comment in `erase_val` for why we use `transmute_unchecked`. // - // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance - // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of - // the right size. - unsafe { transmute_unchecked::, T>(value.data) } + // SAFETY: Due to the use of impl Trait in `Erased` the only way to safely create an instance + // of `Erased` is to call `erase_val`, so we know that `erased_value.data` is a valid instance + // of `T` of the right size. + unsafe { transmute_unchecked::, T>(data) } } -impl EraseType for &'_ T { - type Result = [u8; size_of::<&'static ()>()]; +// FIXME(#151565): Using `T: ?Sized` here should let us remove the separate +// impls for fat reference types. +impl Erasable for &'_ T { + type Storage = [u8; size_of::<&'static ()>()]; } -impl EraseType for &'_ [T] { - type Result = [u8; size_of::<&'static [()]>()]; +impl Erasable for &'_ [T] { + type Storage = [u8; size_of::<&'static [()]>()]; } -impl EraseType for &'_ OsStr { - type Result = [u8; size_of::<&'static OsStr>()]; +impl Erasable for &'_ OsStr { + type Storage = [u8; size_of::<&'static OsStr>()]; } -impl EraseType for &'_ ty::List { - type Result = [u8; size_of::<&'static ty::List<()>>()]; +impl Erasable for &'_ ty::List { + type Storage = [u8; size_of::<&'static ty::List<()>>()]; } -impl EraseType for &'_ ty::ListWithCachedTypeInfo { - type Result = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()]; +impl Erasable for &'_ ty::ListWithCachedTypeInfo { + type Storage = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()]; } -impl EraseType for &'_ rustc_index::IndexSlice { - type Result = [u8; size_of::<&'static rustc_index::IndexSlice>()]; +impl Erasable for &'_ rustc_index::IndexSlice { + type Storage = [u8; size_of::<&'static rustc_index::IndexSlice>()]; } -impl EraseType for Result<&'_ T, traits::query::NoSolution> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, traits::query::NoSolution> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ [T], traits::query::NoSolution> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ [T], traits::query::NoSolution> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, traits::CodegenObligationError> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, traits::CodegenObligationError> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { - type Result = [u8; size_of::>>()]; +impl Erasable for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::< +impl Erasable for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::< Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>, >()]; } -impl EraseType for Result>, rustc_errors::ErrorGuaranteed> { - type Result = +impl Erasable for Result>, rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>, rustc_errors::ErrorGuaranteed>>()]; } -impl EraseType for Result { - type Result = [u8; size_of::>()]; +impl Erasable for Result { + type Storage = [u8; size_of::>()]; } -impl EraseType +impl Erasable for Result>>, rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::< + type Storage = [u8; size_of::< Result>>, rustc_errors::ErrorGuaranteed>, >()]; } -impl EraseType for Result, traits::query::NoSolution> { - type Result = [u8; size_of::, traits::query::NoSolution>>()]; +impl Erasable for Result, traits::query::NoSolution> { + type Storage = [u8; size_of::, traits::query::NoSolution>>()]; } -impl EraseType for Result> { - type Result = [u8; size_of::>>()]; +impl Erasable for Result> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for Result>, &ty::layout::LayoutError<'_>> { - type Result = [u8; size_of::< +impl Erasable for Result>, &ty::layout::LayoutError<'_>> { + type Storage = [u8; size_of::< Result< rustc_abi::TyAndLayout<'static, Ty<'static>>, &'static ty::layout::LayoutError<'static>, @@ -153,35 +191,36 @@ impl EraseType for Result>, &ty::layout::Layou >()]; } -impl EraseType for Result, mir::interpret::ErrorHandled> { - type Result = [u8; size_of::, mir::interpret::ErrorHandled>>()]; +impl Erasable for Result, mir::interpret::ErrorHandled> { + type Storage = + [u8; size_of::, mir::interpret::ErrorHandled>>()]; } -impl EraseType for Result { - type Result = [u8; size_of::>()]; +impl Erasable for Result { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<(mir::ConstValue, Ty<'_>)> { - type Result = [u8; size_of::)>>()]; +impl Erasable for Option<(mir::ConstValue, Ty<'_>)> { + type Storage = [u8; size_of::)>>()]; } -impl EraseType for EvalToValTreeResult<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for EvalToValTreeResult<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { - type Result = +impl Erasable for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { + type Storage = [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()]; } -impl EraseType for Result>, CyclePlaceholder> { - type Result = [u8; size_of::>, CyclePlaceholder>>()]; +impl Erasable for Result>, CyclePlaceholder> { + type Storage = [u8; size_of::>, CyclePlaceholder>>()]; } -impl EraseType +impl Erasable for Result<(&'_ [Spanned>], &'_ [Spanned>]), NormalizationErrorInMono> { - type Result = [u8; size_of::< + type Storage = [u8; size_of::< Result< (&'static [Spanned>], &'static [Spanned>]), NormalizationErrorInMono, @@ -189,86 +228,93 @@ impl EraseType >()]; } -impl EraseType for Result<&'_ TokenStream, ()> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ TokenStream, ()> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ T> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ T> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ [T]> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ [T]> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ OsStr> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ OsStr> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option> { - type Result = [u8; size_of::>>()]; +impl Erasable for Option> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for ty::ImplTraitHeader<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for ty::ImplTraitHeader<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl Erasable for Option>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for rustc_hir::MaybeOwner<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for Option> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for ty::EarlyBinder<'_, T> { - type Result = T::Result; +impl Erasable for rustc_hir::MaybeOwner<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for ty::Binder<'_, ty::FnSig<'_>> { - type Result = [u8; size_of::>>()]; +impl Erasable for ty::EarlyBinder<'_, T> { + type Storage = T::Storage; } -impl EraseType for ty::Binder<'_, ty::CoroutineWitnessTypes>> { - type Result = +impl Erasable for ty::Binder<'_, ty::FnSig<'_>> { + type Storage = [u8; size_of::>>()]; +} + +impl Erasable for ty::Binder<'_, ty::CoroutineWitnessTypes>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for ty::Binder<'_, &'_ ty::List>> { - type Result = [u8; size_of::>>>()]; +impl Erasable for ty::Binder<'_, &'_ ty::List>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for (&'_ T0, &'_ T1) { - type Result = [u8; size_of::<(&'static (), &'static ())>()]; +impl Erasable for (&'_ T0, &'_ T1) { + type Storage = [u8; size_of::<(&'static (), &'static ())>()]; } -impl EraseType for (solve::QueryResult<'_>, &'_ T0) { - type Result = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()]; +impl Erasable for (solve::QueryResult<'_>, &'_ T0) { + type Storage = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()]; } -impl EraseType for (&'_ T0, &'_ [T1]) { - type Result = [u8; size_of::<(&'static (), &'static [()])>()]; +impl Erasable for (&'_ T0, &'_ [T1]) { + type Storage = [u8; size_of::<(&'static (), &'static [()])>()]; } -impl EraseType for (&'_ [T0], &'_ [T1]) { - type Result = [u8; size_of::<(&'static [()], &'static [()])>()]; +impl Erasable for (&'_ [T0], &'_ [T1]) { + type Storage = [u8; size_of::<(&'static [()], &'static [()])>()]; } -impl EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) { - type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; +impl Erasable for (&'_ T0, Result<(), ErrorGuaranteed>) { + type Storage = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; } -macro_rules! trivial { +macro_rules! impl_erasable_for_simple_types { ($($ty:ty),+ $(,)?) => { $( - impl EraseType for $ty { - type Result = [u8; size_of::<$ty>()]; + impl Erasable for $ty { + type Storage = [u8; size_of::<$ty>()]; } )* } } -trivial! { +// For concrete types with no lifetimes, the erased storage for `Foo` is +// `[u8; size_of::()]`. +impl_erasable_for_simple_types! { + // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this. (), bool, Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, @@ -346,7 +392,6 @@ trivial! { rustc_middle::ty::AssocContainer, rustc_middle::ty::Asyncness, rustc_middle::ty::AsyncDestructor, - rustc_middle::ty::BoundVariableKind, rustc_middle::ty::AnonConstKind, rustc_middle::ty::Destructor, rustc_middle::ty::fast_reject::SimplifiedType, @@ -378,23 +423,28 @@ trivial! { usize, } -macro_rules! tcx_lifetime { +macro_rules! impl_erasable_for_single_lifetime_types { ($($($fake_path:ident)::+),+ $(,)?) => { $( - impl<'tcx> EraseType for $($fake_path)::+<'tcx> { - type Result = [u8; size_of::<$($fake_path)::+<'static>>()]; + impl<'tcx> Erasable for $($fake_path)::+<'tcx> { + type Storage = [u8; size_of::<$($fake_path)::+<'static>>()]; } )* } } -tcx_lifetime! { +// For types containing a single lifetime and no other generics, e.g. +// `Foo<'tcx>`, the erased storage is `[u8; size_of::>()]`. +// +// FIXME(#151565): Some of the hand-written impls above that only use one +// lifetime can probably be migrated here. +impl_erasable_for_single_lifetime_types! { + // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this. rustc_middle::middle::exported_symbols::ExportedSymbol, rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, rustc_middle::mir::ConstAlloc, rustc_middle::mir::interpret::GlobalId, - rustc_middle::mir::interpret::LitToConstInput, rustc_middle::mir::interpret::EvalStaticInitializerRawResult, rustc_middle::mir::mono::MonoItemPartitions, rustc_middle::traits::query::MethodAutoderefStepsResult, @@ -415,9 +465,11 @@ tcx_lifetime! { rustc_middle::ty::ConstConditions, rustc_middle::ty::inhabitedness::InhabitedPredicate, rustc_middle::ty::Instance, + rustc_middle::ty::BoundVariableKind, rustc_middle::ty::InstanceKind, rustc_middle::ty::layout::FnAbiError, rustc_middle::ty::layout::LayoutError, + rustc_middle::ty::LitToConstInput, rustc_middle::ty::ParamEnv, rustc_middle::ty::TypingEnv, rustc_middle::ty::Predicate, diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index ee828ae55f7a..b977172fcf9d 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -1,19 +1,34 @@ //! Helper functions that serve as the immediate implementation of //! `tcx.$query(..)` and its variations. -use std::fmt::Debug; - -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_query_system::dep_graph::{DepKind, DepNodeParams}; -use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; -use crate::query::IntoQueryParam; -use crate::query::erase::{self, Erase, EraseType}; +use crate::dep_graph::{DepKind, DepNodeKey}; +use crate::query::erase::{self, Erasable, Erased}; +use crate::query::plumbing::QueryVTable; +use crate::query::{QueryCache, QueryMode}; use crate::ty::TyCtxt; +/// Checks whether there is already a value for this key in the in-memory +/// query cache, returning that value if present. +/// +/// (Also performs some associated bookkeeping, if a value was found.) +#[inline(always)] +fn try_get_cached<'tcx, C>(tcx: TyCtxt<'tcx>, cache: &C, key: &C::Key) -> Option +where + C: QueryCache, +{ + match cache.lookup(key) { + Some((value, index)) => { + tcx.prof.query_cache_hit(index.into()); + tcx.dep_graph.read_index(index); + Some(value) + } + None => None, + } +} + /// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)` /// for all queries. #[inline(always)] @@ -27,7 +42,6 @@ pub(crate) fn query_get_at<'tcx, Cache>( where Cache: QueryCache, { - let key = key.into_query_param(); match try_get_cached(tcx, query_cache, &key) { Some(value) => value, None => execute_query(tcx, span, key, QueryMode::Get).unwrap(), @@ -46,7 +60,6 @@ pub(crate) fn query_ensure<'tcx, Cache>( ) where Cache: QueryCache, { - let key = key.into_query_param(); if try_get_cached(tcx, query_cache, &key).is_none() { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }); } @@ -63,15 +76,14 @@ pub(crate) fn query_ensure_error_guaranteed<'tcx, Cache, T>( check_cache: bool, ) -> Result<(), ErrorGuaranteed> where - Cache: QueryCache>>, - Result: EraseType, + Cache: QueryCache>>, + Result: Erasable, { - let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { - erase::restore(res).map(drop) + erase::restore_val(res).map(drop) } else { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }) - .map(erase::restore) + .map(erase::restore_val) .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, // or we can just assume the query succeeded, because it was green in the @@ -84,35 +96,38 @@ where } /// Common implementation of query feeding, used by `define_feedable!`. -pub(crate) fn query_feed<'tcx, Cache, Value>( +pub(crate) fn query_feed<'tcx, Cache>( tcx: TyCtxt<'tcx>, dep_kind: DepKind, - hasher: Option, &Value) -> Fingerprint>, + query_vtable: &QueryVTable<'tcx, Cache>, cache: &Cache, key: Cache::Key, - erased: Erase, + value: Cache::Value, ) where - Cache: QueryCache>, - Cache::Key: DepNodeParams>, - Value: EraseType + Debug, + Cache: QueryCache, + Cache::Key: DepNodeKey>, { - let value = erase::restore::(erased); + let format_value = query_vtable.format_value; + // Check whether the in-memory cache already has a value for this key. match try_get_cached(tcx, cache, &key) { Some(old) => { - let old = erase::restore::(old); - if let Some(hasher) = hasher { - let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx - .with_stable_hashing_context(|mut hcx| { - (hasher(&mut hcx, &value), hasher(&mut hcx, &old)) - }); + // The query already has a cached value for this key. + // That's OK if both values are the same, i.e. they have the same hash, + // so now we check their hashes. + if let Some(hasher_fn) = query_vtable.hash_result { + let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| { + (hasher_fn(hcx, &old), hasher_fn(hcx, &value)) + }); if old_hash != value_hash { // We have an inconsistency. This can happen if one of the two // results is tainted by errors. In this case, delay a bug to // ensure compilation is doomed, and keep the `old` value. tcx.dcx().delayed_bug(format!( "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\ - old value: {old:?}\nnew value: {value:?}", + old value: {old}\nnew value: {value}", + old = format_value(&old), + value = format_value(&value), )); } } else { @@ -121,14 +136,24 @@ pub(crate) fn query_feed<'tcx, Cache, Value>( // the query should not be marked `no_hash`. bug!( "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\ - old value: {old:?}\nnew value: {value:?}", + old value: {old}\nnew value: {value}", + old = format_value(&old), + value = format_value(&value), ) } } None => { + // There is no cached value for this key, so feed the query by + // adding the provided value to the cache. let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key); - let dep_node_index = tcx.dep_graph.with_feed_task(dep_node, tcx, &value, hasher); - cache.complete(key, erased, dep_node_index); + let dep_node_index = tcx.dep_graph.with_feed_task( + dep_node, + tcx, + &value, + query_vtable.hash_result, + query_vtable.format_value, + ); + cache.complete(key, value, dep_node_index); } } } diff --git a/compiler/rustc_middle/src/query/job.rs b/compiler/rustc_middle/src/query/job.rs new file mode 100644 index 000000000000..f1a2b3a34d0e --- /dev/null +++ b/compiler/rustc_middle/src/query/job.rs @@ -0,0 +1,160 @@ +use std::fmt::Debug; +use std::hash::Hash; +use std::num::NonZero; +use std::sync::Arc; + +use parking_lot::{Condvar, Mutex}; +use rustc_span::Span; + +use crate::query::plumbing::CycleError; +use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; +use crate::ty::TyCtxt; + +/// Represents a span and a query key. +#[derive(Clone, Debug)] +pub struct QueryInfo { + /// The span corresponding to the reason for which this query was required. + pub span: Span, + pub frame: QueryStackFrame, +} + +impl<'tcx> QueryInfo> { + pub(crate) fn lift(&self) -> QueryInfo { + QueryInfo { span: self.span, frame: self.frame.lift() } + } +} + +/// A value uniquely identifying an active query job. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +pub struct QueryJobId(pub NonZero); + +/// Represents an active query job. +#[derive(Clone, Debug)] +pub struct QueryJob<'tcx> { + pub id: QueryJobId, + + /// The span corresponding to the reason for which this query was required. + pub span: Span, + + /// The parent query job which created this job and is implicitly waiting on it. + pub parent: Option, + + /// The latch that is used to wait on this job. + pub latch: Option>, +} + +impl<'tcx> QueryJob<'tcx> { + /// Creates a new query job. + #[inline] + pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { + QueryJob { id, span, parent, latch: None } + } + + pub fn latch(&mut self) -> QueryLatch<'tcx> { + if self.latch.is_none() { + self.latch = Some(QueryLatch::new()); + } + self.latch.as_ref().unwrap().clone() + } + + /// Signals to waiters that the query is complete. + /// + /// This does nothing for single threaded rustc, + /// as there are no concurrent jobs which could be waiting on us + #[inline] + pub fn signal_complete(self) { + if let Some(latch) = self.latch { + latch.set(); + } + } +} + +#[derive(Debug)] +pub struct QueryWaiter<'tcx> { + pub query: Option, + pub condvar: Condvar, + pub span: Span, + pub cycle: Mutex>>>, +} + +#[derive(Debug)] +pub struct QueryLatchInfo<'tcx> { + pub complete: bool, + pub waiters: Vec>>, +} + +#[derive(Clone, Debug)] +pub struct QueryLatch<'tcx> { + pub info: Arc>>, +} + +impl<'tcx> QueryLatch<'tcx> { + fn new() -> Self { + QueryLatch { + info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), + } + } + + /// Awaits for the query job to complete. + pub fn wait_on( + &self, + tcx: TyCtxt<'tcx>, + query: Option, + span: Span, + ) -> Result<(), CycleError>> { + let waiter = + Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); + self.wait_on_inner(tcx, &waiter); + // FIXME: Get rid of this lock. We have ownership of the QueryWaiter + // although another thread may still have a Arc reference so we cannot + // use Arc::get_mut + let mut cycle = waiter.cycle.lock(); + match cycle.take() { + None => Ok(()), + Some(cycle) => Err(cycle), + } + } + + /// Awaits the caller on this latch by blocking the current thread. + fn wait_on_inner(&self, tcx: TyCtxt<'tcx>, 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 + // the `wait` call below, by 1) the `set` method or 2) by deadlock detection. + // Both of these will remove it from the `waiters` list before resuming + // this thread. + info.waiters.push(Arc::clone(waiter)); + + // If this detects a deadlock and the deadlock handler wants to resume this thread + // we have to be in the `wait` call. This is ensured by the deadlock handler + // getting the self.info lock. + rustc_thread_pool::mark_blocked(); + tcx.jobserver_proxy.release_thread(); + waiter.condvar.wait(&mut info); + // Release the lock before we potentially block in `acquire_thread` + drop(info); + tcx.jobserver_proxy.acquire_thread(); + } + } + + /// Sets the latch and resumes all waiters on it + fn set(&self) { + let mut info = self.info.lock(); + debug_assert!(!info.complete); + info.complete = true; + let registry = rustc_thread_pool::Registry::current(); + for waiter in info.waiters.drain(..) { + rustc_thread_pool::mark_unblocked(®istry); + waiter.condvar.notify_one(); + } + } + + /// Removes a single waiter from the list of waiters. + /// This is used to break query cycles. + pub 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 + info.waiters.remove(waiter) + } +} diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index cccb7d51bd3e..6652e6e78e76 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -5,12 +5,12 @@ use std::ffi::OsStr; use rustc_ast::tokenstream::TokenStream; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::hir_id::OwnerId; -use rustc_query_system::dep_graph::DepNodeIndex; -use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; +use crate::dep_graph::DepNodeIndex; use crate::infer::canonical::CanonicalQueryInput; use crate::mir::mono::CollectionMode; +use crate::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; @@ -28,7 +28,7 @@ pub trait Key: Sized { /// In practice the cache type must implement [`QueryCache`], though that /// constraint is not enforced here. /// - /// [`QueryCache`]: rustc_query_system::query::QueryCache + /// [`QueryCache`]: rustc_middle::query::QueryCache type Cache = DefaultCache; /// In the event that a cycle occurs, if no explicit span has been @@ -87,7 +87,7 @@ impl<'tcx> Key for (Ty<'tcx>, Option>) { } } -impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { +impl<'tcx> Key for ty::LitToConstInput<'tcx> { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 901a023c4f30..d16ca3c401d2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,2792 +1,34 @@ -//! -//! # The rustc Query System: Query Definitions and Modifiers -//! -//! The core processes in rustc are shipped as queries. Each query is a demand-driven function from some key to a value. -//! The execution result of the function is cached and directly read during the next request, thereby improving compilation efficiency. -//! Some results are saved locally and directly read during the next compilation, which are core of incremental compilation. -//! -//! ## How to Read This Module -//! -//! Each `query` block in this file defines a single query, specifying its key and value types, along with various modifiers. -//! These query definitions are processed by the [`rustc_macros`], which expands them into the necessary boilerplate code -//! for the query system—including the [`Providers`] struct (a function table for all query implementations, where each field is -//! a function pointer to the actual provider), caching, and dependency graph integration. -//! **Note:** The `Providers` struct is not a Rust trait, but a struct generated by the `rustc_macros` to hold all provider functions. -//! The `rustc_macros` also supports a set of **query modifiers** (see below) that control the behavior of each query. -//! -//! The actual provider functions are implemented in various modules and registered into the `Providers` struct -//! during compiler initialization (see [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]). -//! -//! [`rustc_macros`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/index.html -//! [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]: ../../rustc_interface/passes/static.DEFAULT_QUERY_PROVIDERS.html -//! -//! ## Query Modifiers -//! -//! Query modifiers are special flags that alter the behavior of a query. They are parsed and processed by the `rustc_macros` -//! The main modifiers are: -//! -//! - `desc { ... }`: Sets the human-readable description for diagnostics and profiling. Required for every query. -//! - `arena_cache`: Use an arena for in-memory caching of the query result. -//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to true. -//! - `cycle_fatal`: If a dependency cycle is detected, abort compilation with a fatal error. -//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. -//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. -//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. -//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). -//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. -//! - `depth_limit`: Impose a recursion depth limit on the query to prevent stack overflows. -//! - `separate_provide_extern`: Use separate provider functions for local and external crates. -//! - `feedable`: Allow the query result to be set from another query ("fed" externally). -//! - `return_result_from_ensure_ok`: When called via `tcx.ensure_ok()`, return `Result<(), ErrorGuaranteed>` instead of `()`. -//! If the query needs to be executed and returns an error, the error is returned to the caller. -//! Only valid for queries returning `Result<_, ErrorGuaranteed>`. -//! -//! For the up-to-date list, see the `QueryModifiers` struct in -//! [`rustc_macros/src/query.rs`](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_macros/src/query.rs) -//! and for more details in incremental compilation, see the -//! [Query modifiers in incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#query-modifiers) section of the rustc-dev-guide. -//! -//! ## Query Expansion and Code Generation -//! -//! The [`rustc_macros::rustc_queries`] macro expands each query definition into: -//! - A method on [`TyCtxt`] (and [`TyCtxtAt`]) for invoking the query. -//! - Provider traits and structs for supplying the query's value. -//! - Caching and dependency graph integration. -//! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. -//! -//! [`rustc_macros::rustc_queries`]: ../../rustc_macros/macro.rustc_queries.html -//! -//! The macro-based approach allows the query system to be highly flexible and maintainable, while minimizing boilerplate. -//! -//! For more details, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). +use rustc_data_structures::jobserver::Proxy; +use rustc_hir::def_id::LocalDefId; +use rustc_query_system::query::QuerySideEffect; -#![allow(unused_parens)] - -use std::ffi::OsStr; -use std::mem; -use std::path::PathBuf; -use std::sync::Arc; - -use rustc_abi::Align; -use rustc_arena::TypedArena; -use rustc_ast::expand::allocator::AllocatorKind; -use rustc_ast::tokenstream::TokenStream; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_data_structures::sorted_map::SortedMap; -use rustc_data_structures::steal::Steal; -use rustc_data_structures::svh::Svh; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem}; -use rustc_hir::def::{DefKind, DocLinkResMap}; -use rustc_hir::def_id::{ - CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, +pub use self::caches::{ + DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -use rustc_hir::lang_items::{LangItem, LanguageItems}; -use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; -use rustc_index::IndexVec; -use rustc_lint_defs::LintId; -use rustc_macros::rustc_queries; -use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState}; -use rustc_session::Limits; -use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; -use rustc_session::cstore::{ - CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, -}; -use rustc_session::lint::LintExpectationId; -use rustc_span::def_id::LOCAL_CRATE; -use rustc_span::source_map::Spanned; -use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; -use rustc_target::spec::PanicStrategy; -use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; - +pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; -pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; -use crate::infer::canonical::{self, Canonical}; -use crate::lint::LintExpectation; -use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; -use crate::middle::debugger_visualizer::DebuggerVisualizerFile; -use crate::middle::deduced_param_attrs::DeducedParamAttrs; -use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; -use crate::middle::lib_features::LibFeatures; -use crate::middle::privacy::EffectiveVisibilities; -use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; -use crate::middle::stability::DeprecationEntry; -use crate::mir::interpret::{ - EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, - EvalToValTreeResult, GlobalId, LitToConstInput, +pub use self::plumbing::{ + ActiveKeyStatus, CycleError, CycleErrorHandling, IntoQueryParam, QueryMode, QueryState, + TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, }; -use crate::mir::mono::{ - CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, -}; -use crate::query::erase::{Erase, erase, restore}; -use crate::query::plumbing::CyclePlaceholder; -use crate::traits::query::{ - CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, - CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, - CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint, - DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult, - OutlivesBound, -}; -use crate::traits::{ - CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource, - ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph, -}; -use crate::ty::fast_reject::SimplifiedType; -use crate::ty::layout::ValidityRequirement; -use crate::ty::print::PrintTraitRefExt; -use crate::ty::util::AlwaysRequiresDrop; -use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty, - TyCtxt, TyCtxtFeed, -}; -use crate::{dep_graph, mir, thir}; +pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; +use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; +pub use crate::queries::Providers; +use crate::ty::TyCtxt; -mod arena_cached; +pub(crate) mod arena_cached; +mod caches; pub mod erase; pub(crate) mod inner; +mod job; mod keys; pub mod on_disk_cache; #[macro_use] pub mod plumbing; +pub(crate) mod modifiers; +mod stack; -// Each of these queries corresponds to a function pointer field in the -// `Providers` struct for requesting a value of that type, and a method -// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way -// which memoizes and does dep-graph tracking, wrapping around the actual -// `Providers` that the driver creates (using several `rustc_*` crates). -// -// The result type of each query must implement `Clone`, and additionally -// `ty::query::values::Value`, which produces an appropriate placeholder -// (error) value if the query resulted in a query cycle. -// Queries marked with `cycle_fatal` do not need the latter implementation, -// as they will raise an fatal error on query cycles instead. -rustc_queries! { - /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`. - /// The key is: - /// - A unique key corresponding to the invocation of a macro. - /// - Token stream which serves as an input to the macro. - /// - /// The output is the token stream generated by the proc macro. - query derive_macro_expansion(key: (LocalExpnId, &'tcx TokenStream)) -> Result<&'tcx TokenStream, ()> { - desc { "expanding a derive (proc) macro" } - cache_on_disk_if { true } - } - - /// This exists purely for testing the interactions between delayed bugs and incremental. - query trigger_delayed_bug(key: DefId) { - desc { "triggering a delayed bug for testing incremental" } - } - - /// Collects the list of all tools registered using `#![register_tool]`. - query registered_tools(_: ()) -> &'tcx ty::RegisteredTools { - arena_cache - desc { "compute registered tools for crate" } - } - - query early_lint_checks(_: ()) { - desc { "perform lints prior to AST lowering" } - } - - /// Tracked access to environment variables. - /// - /// Useful for the implementation of `std::env!`, `proc-macro`s change - /// detection and other changes in the compiler's behaviour that is easier - /// to control with an environment variable than a flag. - /// - /// NOTE: This currently does not work with dependency info in the - /// analysis, codegen and linking passes, place extra code at the top of - /// `rustc_interface::passes::write_dep_info` to make that work. - query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { - // Environment variables are global state - eval_always - desc { "get the value of an environment variable" } - } - - query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - desc { "getting the resolver outputs" } - } - - query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc)>, &'tcx ty::ResolverGlobalCtxt) { - eval_always - no_hash - desc { "getting the resolver for lowering" } - } - - /// Return the span for a definition. - /// - /// Contrary to `def_span` below, this query returns the full absolute span of the definition. - /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside - /// of rustc_middle::hir::source_map. - query source_span(key: LocalDefId) -> Span { - // Accesses untracked data - eval_always - desc { "getting the source span" } - } - - /// Represents crate as a whole (as distinct from the top-level crate module). - /// - /// If you call `tcx.hir_crate(())` we will have to assume that any change - /// means that you need to be recompiled. This is because the `hir_crate` - /// query gives you access to all other items. To avoid this fate, do not - /// call `tcx.hir_crate(())`; instead, prefer wrappers like - /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { - arena_cache - eval_always - desc { "getting the crate HIR" } - } - - /// All items in the crate. - query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems { - arena_cache - eval_always - desc { "getting HIR crate items" } - } - - /// The items in a module. - /// - /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`. - /// Avoid calling this query directly. - query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { - arena_cache - desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - - /// Returns HIR ID for the given `LocalDefId`. - query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { - desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to the HIR node's parent for the HIR owner `key`. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { - desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } - } - - /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { - desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to the HIR attributes inside the HIR owner `key`. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { - desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to lints emitted during ast lowering. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query opt_ast_lowering_delayed_lints(key: hir::OwnerId) -> Option<&'tcx hir::lints::DelayedLints> { - desc { |tcx| "getting AST lowering delayed lints in `{}`", tcx.def_path_str(key) } - } - - /// Returns the *default* of the const pararameter given by `DefId`. - /// - /// E.g., given `struct Ty;` this returns `3` for `N`. - query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { - desc { |tcx| "computing the default for const parameter `{}`", tcx.def_path_str(param) } - cache_on_disk_if { param.is_local() } - separate_provide_extern - } - - /// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`. - /// - /// When a const item is used in a type-level expression, like in equality for an assoc const - /// projection, this allows us to retrieve the typesystem-appropriate representation of the - /// const value. - /// - /// This query will ICE if given a const that is not marked with `#[type_const]`. - query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { - desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Returns the *type* of the definition given by `DefId`. - /// - /// For type aliases (whether eager or lazy) and associated types, this returns - /// the underlying aliased type (not the corresponding [alias type]). - /// - /// For opaque types, this returns and thus reveals the hidden type! If you - /// want to detect cycle errors use `type_of_opaque` instead. - /// - /// To clarify, for type definitions, this does *not* return the "type of a type" - /// (aka *kind* or *sort*) in the type-theoretical sense! It merely returns - /// the type primarily *associated with* it. - /// - /// # Panics - /// - /// This query will panic if the given definition doesn't (and can't - /// conceptually) have an (underlying) type. - /// - /// [alias type]: rustc_middle::ty::AliasTy - query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - desc { |tcx| - "{action} `{path}`", - action = match tcx.def_kind(key) { - DefKind::TyAlias => "expanding type alias", - DefKind::TraitAlias => "expanding trait alias", - _ => "computing type of", - }, - path = tcx.def_path_str(key), - } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. - /// - /// This is a specialized instance of [`Self::type_of`] that detects query cycles. - /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. - /// This is used to improve the error message in cases where revealing the hidden type - /// for auto-trait leakage cycles. - /// - /// # Panics - /// - /// This query will panic if the given definition is not an opaque type. - query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { - desc { |tcx| - "computing type of opaque `{path}`", - path = tcx.def_path_str(key), - } - cycle_stash - } - query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - desc { |tcx| - "computing type of opaque `{path}` via HIR typeck", - path = tcx.def_path_str(key), - } - } - - /// Returns whether the type alias given by `DefId` is lazy. - /// - /// I.e., if the type alias expands / ought to expand to a [free] [alias type] - /// instead of the underlying aliased type. - /// - /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. - /// - /// # Panics - /// - /// This query *may* panic if the given definition is not a type alias. - /// - /// [free]: rustc_middle::ty::Free - /// [alias type]: rustc_middle::ty::AliasTy - query type_alias_is_lazy(key: DefId) -> bool { - desc { |tcx| - "computing whether the type alias `{path}` is lazy", - path = tcx.def_path_str(key), - } - separate_provide_extern - } - - query collect_return_position_impl_trait_in_trait_tys(key: DefId) - -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> - { - desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin - { - desc { "determine where the opaque originates from" } - separate_provide_extern - } - - query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet - { - arena_cache - desc { |tcx| - "determining what parameters of `{}` can participate in unsizing", - tcx.def_path_str(key), - } - } - - /// The root query triggering all analysis passes like typeck or borrowck. - query analysis(key: ()) { - eval_always - desc { |tcx| - "running analysis passes on crate `{}`", - tcx.crate_name(LOCAL_CRATE), - } - } - - /// This query checks the fulfillment of collected lint expectations. - /// All lint emitting queries have to be done before this is executed - /// to ensure that all expectations can be fulfilled. - /// - /// This is an extra query to enable other drivers (like rustdoc) to - /// only execute a small subset of the `analysis` query, while allowing - /// lints to be expected. In rustc, this query will be executed as part of - /// the `analysis` query and doesn't have to be called a second time. - /// - /// Tools can additionally pass in a tool filter. That will restrict the - /// expectations to only trigger for lints starting with the listed tool - /// name. This is useful for cases were not all linting code from rustc - /// was called. With the default `None` all registered lints will also - /// be checked for expectation fulfillment. - query check_expectations(key: Option) { - eval_always - desc { "checking lint expectations (RFC 2383)" } - } - - /// Returns the *generics* of the definition given by `DefId`. - query generics_of(key: DefId) -> &'tcx ty::Generics { - desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } - arena_cache - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the (elaborated) *predicates* of the definition given by `DefId` - /// that must be proven true at usage sites (and which can be assumed at definition site). - /// - /// This is almost always *the* "predicates query" that you want. - /// - /// **Tip**: You can use `#[rustc_dump_predicates]` on an item to basically print - /// the result of this query for use in UI tests or for debugging purposes. - query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - } - - query opaque_types_defined_by( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the opaque types defined by `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - - /// A list of all bodies inside of `key`, nested bodies are always stored - /// before their parent. - query nested_bodies_within( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the coroutines defined within `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - - /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId` - /// that must be proven true at definition site (and which can be assumed at usage sites). - /// - /// For associated types, these must be satisfied for an implementation - /// to be well-formed, and for opaque types, these are required to be - /// satisfied by the hidden type of the opaque. - /// - /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. - /// - /// Syntactially, these are the bounds written on associated types in trait - /// definitions, or those after the `impl` keyword for an opaque: - /// - /// ```ignore (illustrative) - /// trait Trait { type X: Bound + 'lt; } - /// // ^^^^^^^^^^^ - /// fn function() -> impl Debug + Display { /*...*/ } - /// // ^^^^^^^^^^^^^^^ - /// ``` - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the explicitly user-written *bounds* that share the `Self` type of the item. - /// - /// These are a subset of the [explicit item bounds] that may explicitly be used for things - /// like closure signature deduction. - /// - /// [explicit item bounds]: Self::explicit_item_bounds - query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the (elaborated) *bounds* on the associated or opaque type given by `DefId` - /// that must be proven true at definition site (and which can be assumed at usage sites). - /// - /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. - /// - /// **Tip**: You can use `#[rustc_dump_item_bounds]` on an item to basically print - /// the result of this query for use in UI tests or for debugging purposes. - /// - /// # Examples - /// - /// ``` - /// trait Trait { type Assoc: Eq + ?Sized; } - /// ``` - /// - /// While [`Self::explicit_item_bounds`] returns `[::Assoc: Eq]` - /// here, `item_bounds` returns: - /// - /// ```text - /// [ - /// ::Assoc: Eq, - /// ::Assoc: PartialEq<::Assoc> - /// ] - /// ``` - query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } - } - - query item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } - } - - query item_non_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } - } - - query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } - } - - /// Look up all native libraries this crate depends on. - /// These are assembled from the following places: - /// - `extern` blocks (depending on their `link` attributes) - /// - the `libs` (`-l`) option - query native_libraries(_: CrateNum) -> &'tcx Vec { - arena_cache - desc { "looking up the native libraries of a linked crate" } - separate_provide_extern - } - - query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap { - arena_cache - desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) } - } - - query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> { - arena_cache - desc { "computing `#[expect]`ed lints in this crate" } - } - - query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { - arena_cache - desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" } - } - - query expn_that_defined(key: DefId) -> rustc_span::ExpnId { - desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - query is_panic_runtime(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate is_panic_runtime" } - separate_provide_extern - } - - /// Checks whether a type is representable or infinitely sized - query representability(_: LocalDefId) -> rustc_middle::ty::Representability { - desc { "checking if `{}` is representable", tcx.def_path_str(key) } - // infinitely sized types will cause a cycle - cycle_delay_bug - // we don't want recursive representability calls to be forced with - // incremental compilation because, if a cycle occurs, we need the - // entire cycle to be in memory for diagnostics - anon - } - - /// An implementation detail for the `representability` query - query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability { - desc { "checking if `{}` is representable", key } - cycle_delay_bug - anon - } - - /// Set of param indexes for type params that are in the type's representation - query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet { - desc { "finding type parameters in the representation" } - arena_cache - no_hash - separate_provide_extern - } - - /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless - /// `-Zno-steal-thir` is on. - query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { - // Perf tests revealed that hashing THIR is inefficient (see #85729). - no_hash - desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) } - } - - /// Set of all the `DefId`s in this crate that have MIR associated with - /// them. This includes all the body owners, but also things like struct - /// constructors. - query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet { - arena_cache - desc { "getting a list of all mir_keys" } - } - - /// Maps DefId's that have an associated `mir::Body` to the result - /// of the MIR const-checking pass. This is the set of qualifs in - /// the final value of a `const`. - query mir_const_qualif(key: DefId) -> mir::ConstQualifs { - desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Build the MIR for a given `DefId` and prepare it for const qualification. - /// - /// See the [rustc dev guide] for more info. - /// - /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html - query mir_built(key: LocalDefId) -> &'tcx Steal> { - desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } - feedable - } - - /// Try to build an abstract representation of the given constant. - query thir_abstract_const( - key: DefId - ) -> Result>>, ErrorGuaranteed> { - desc { - |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), - } - separate_provide_extern - } - - query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal> { - no_hash - desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) } - } - - query mir_for_ctfe( - key: DefId - ) -> &'tcx mir::Body<'tcx> { - desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query mir_promoted(key: LocalDefId) -> ( - &'tcx Steal>, - &'tcx Steal>> - ) { - no_hash - desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } - } - - query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> { - desc { - |tcx| "finding symbols for captures of closure `{}`", - tcx.def_path_str(key) - } - } - - /// Returns names of captured upvars for closures and coroutines. - /// - /// Here are some examples: - /// - `name__field1__field2` when the upvar is captured by value. - /// - `_ref__name__field` when the upvar is captured by reference. - /// - /// For coroutines this only contains upvars that are shared by all states. - query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec { - arena_cache - desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { - arena_cache - desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that - /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck. - /// - /// However, we replace each free region in the MIR body with a unique region inference - /// variable. As we may rely on structural identity when proving goals this may cause a - /// goal to no longer hold. We store obligations for which this may happen during HIR - /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck - /// encounters an unexpected error. We expect this to result in an error when used and - /// delay a bug if it does not. - query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { - |tcx| "reproving potentially region dependent HIR typeck goals for `{}", - tcx.def_path_str(key) - } - } - - /// MIR after our optimization passes have run. This is MIR that is ready - /// for codegen. This is also the only query that can fetch non-local MIR, at present. - query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { - desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on - /// this def and any enclosing defs, up to the crate root. - /// - /// Returns `false` if `#[coverage(off)]` was found, or `true` if - /// either `#[coverage(on)]` or no coverage attribute was found. - query coverage_attr_on(key: LocalDefId) -> bool { - desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) } - feedable - } - - /// Scans through a function's MIR after MIR optimizations, to prepare the - /// information needed by codegen when `-Cinstrument-coverage` is active. - /// - /// This includes the details of where to insert `llvm.instrprof.increment` - /// intrinsics, and the expression tables to be embedded in the function's - /// coverage metadata. - /// - /// FIXME(Zalathar): This query's purpose has drifted a bit and should - /// probably be renamed, but that can wait until after the potential - /// follow-ups to #136053 have settled down. - /// - /// Returns `None` for functions that were not instrumented. - query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { - desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } - arena_cache - } - - /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own - /// `DefId`. This function returns all promoteds in the specified body. The body references - /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because - /// after inlining a body may refer to promoteds from other bodies. In that case you still - /// need to use the `DefId` of the original body. - query promoted_mir(key: DefId) -> &'tcx IndexVec> { - desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Erases regions from `ty` to yield a new type. - /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`, - /// however, which uses this query as a kind of cache. - query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { - // This query is not expected to have input -- as a result, it - // is not a good candidates for "replay" because it is essentially a - // pure function of its input (and hence the expectation is that - // no caller would be green **apart** from just these - // queries). Making it anonymous avoids hashing the result, which - // may save a bit of time. - anon - desc { "erasing regions from `{}`", ty } - } - - query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap { - arena_cache - desc { "getting wasm import module map" } - } - - /// Returns the explicitly user-written *predicates and bounds* of the trait given by `DefId`. - /// - /// Traits are unusual, because predicates on associated types are - /// converted into bounds on that type for backwards compatibility: - /// - /// ``` - /// trait X where Self::U: Copy { type U; } - /// ``` - /// - /// becomes - /// - /// ``` - /// trait X { type U: Copy; } - /// ``` - /// - /// [`Self::explicit_predicates_of`] and [`Self::explicit_item_bounds`] will - /// then take the appropriate subsets of the predicates here. - /// - /// # Panics - /// - /// This query will panic if the given definition is not a trait. - query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) } - } - - /// Returns the explicitly user-written *predicates* of the definition given by `DefId` - /// that must be proven true at usage sites (and which can be assumed at definition site). - /// - /// You should probably use [`Self::predicates_of`] unless you're looking for - /// predicates with explicit spans for diagnostics purposes. - query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the *inferred outlives-predicates* of the item given by `DefId`. - /// - /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. - /// - /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the - /// result of this query for use in UI tests or for debugging purposes. - query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { - desc { |tcx| "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the explicitly user-written *super-predicates* of the trait given by `DefId`. - /// - /// These predicates are unelaborated and consequently don't contain transitive super-predicates. - /// - /// This is a subset of the full list of predicates. We store these in a separate map - /// because we must evaluate them even during type conversion, often before the full - /// predicates are available (note that super-predicates must not be cyclic). - query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// The predicates of the trait that are implied during elaboration. - /// - /// This is a superset of the super-predicates of the trait, but a subset of the predicates - /// of the trait. For regular traits, this includes all super-predicates and their - /// associated type bounds. For trait aliases, currently, this includes all of the - /// predicates of the trait alias. - query explicit_implied_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// The Ident is the name of an associated type.The query returns only the subset - /// of supertraits that define the given associated type. This is used to avoid - /// cycles in resolving type-dependent associated item paths like `T::Item`. - query explicit_supertraits_containing_assoc_item( - key: (DefId, rustc_span::Ident) - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", - tcx.def_path_str(key.0), - key.1 - } - } - - /// Compute the conditions that need to hold for a conditionally-const item to be const. - /// That is, compute the set of `[const]` where clauses for a given item. - /// - /// This can be thought of as the `[const]` equivalent of `predicates_of`. These are the - /// predicates that need to be proven at usage sites, and can be assumed at definition. - /// - /// This query also computes the `[const]` where clauses for associated types, which are - /// not "const", but which have item bounds which may be `[const]`. These must hold for - /// the `[const]` item bound to hold. - query const_conditions( - key: DefId - ) -> ty::ConstConditions<'tcx> { - desc { |tcx| "computing the conditions for `{}` to be considered const", - tcx.def_path_str(key) - } - separate_provide_extern - } - - /// Compute the const bounds that are implied for a conditionally-const item. - /// - /// This can be though of as the `[const]` equivalent of `explicit_item_bounds`. These - /// are the predicates that need to proven at definition sites, and can be assumed at - /// usage sites. - query explicit_implied_const_bounds( - key: DefId - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { - desc { |tcx| "computing the implied `[const]` bounds for `{}`", - tcx.def_path_str(key) - } - separate_provide_extern - } - - /// To avoid cycles within the predicates of a single item we compute - /// per-type-parameter predicates for resolving `T::AssocTy`. - query type_param_predicates( - key: (LocalDefId, LocalDefId, rustc_span::Ident) - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) } - } - - query trait_def(key: DefId) -> &'tcx ty::TraitDef { - desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } - arena_cache - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_def(key: DefId) -> ty::AdtDef<'tcx> { - desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_destructor(key: DefId) -> Option { - desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_async_destructor(key: DefId) -> Option { - desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_sizedness_constraint( - key: (DefId, SizedTraitKind) - ) -> Option>> { - desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) } - } - - query adt_dtorck_constraint( - key: DefId - ) -> &'tcx DropckConstraint<'tcx> { - desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } - } - - /// Returns the constness of the function-like[^1] definition given by `DefId`. - /// - /// Tuple struct/variant constructors are *always* const, foreign functions are - /// *never* const. The rest is const iff marked with keyword `const` (or rather - /// its parent in the case of associated functions). - /// - ///
- /// - /// **Do not call this query** directly. It is only meant to cache the base data for the - /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. - /// - /// Also note that neither of them takes into account feature gates, stability and - /// const predicates/conditions! - /// - ///
- /// - /// # Panics - /// - /// This query will panic if the given definition is not function-like[^1]. - /// - /// [^1]: Tuple struct/variant constructors, closures and free, associated and foreign functions. - query constness(key: DefId) -> hir::Constness { - desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } - separate_provide_extern - feedable - } - - query asyncness(key: DefId) -> ty::Asyncness { - desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - /// Returns `true` if calls to the function may be promoted. - /// - /// This is either because the function is e.g., a tuple-struct or tuple-variant - /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should - /// be removed in the future in favour of some form of check which figures out whether the - /// function does not inspect the bits of any of its arguments (so is essentially just a - /// constructor function). - query is_promotable_const_fn(key: DefId) -> bool { - desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } - } - - /// The body of the coroutine, modified to take its upvars by move rather than by ref. - /// - /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which - /// is run right after building the initial MIR, and will only be populated for coroutines - /// which come out of the async closure desugaring. - query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { - desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. - query coroutine_kind(def_id: DefId) -> Option { - desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - query coroutine_for_closure(def_id: DefId) -> DefId { - desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } - separate_provide_extern - } - - query coroutine_hidden_types( - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { - desc { "looking up the hidden types stored across await points in a coroutine" } - } - - /// Gets a map with the variances of every item in the local crate. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::variances_of`] instead. - /// - ///
- query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { - arena_cache - desc { "computing the variances for items in this crate" } - } - - /// Returns the (inferred) variances of the item given by `DefId`. - /// - /// The list of variances corresponds to the list of (early-bound) generic - /// parameters of the item (including its parents). - /// - /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the - /// result of this query for use in UI tests or for debugging purposes. - query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { - desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - cycle_delay_bug - } - - /// Gets a map with the inferred outlives-predicates of every item in the local crate. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::inferred_outlives_of`] instead. - /// - ///
- query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> { - arena_cache - desc { "computing the inferred outlives-predicates for items in this crate" } - } - - /// Maps from an impl/trait or struct/variant `DefId` - /// to a list of the `DefId`s of its associated items or fields. - query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { - desc { |tcx| "collecting associated items or fields of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Maps from a trait/impl item to the trait/impl item "descriptor". - query associated_item(key: DefId) -> ty::AssocItem { - desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> &'tcx ty::AssocItems { - arena_cache - desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } - } - - /// Maps from associated items on a trait to the corresponding associated - /// item on the impl specified by `impl_id`. - /// - /// For example, with the following code - /// - /// ``` - /// struct Type {} - /// // DefId - /// trait Trait { // trait_id - /// fn f(); // trait_f - /// fn g() {} // trait_g - /// } - /// - /// impl Trait for Type { // impl_id - /// fn f() {} // impl_f - /// fn g() {} // impl_g - /// } - /// ``` - /// - /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be - ///`{ trait_f: impl_f, trait_g: impl_g }` - query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap { - arena_cache - desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } - } - - /// Given the `item_def_id` of a trait or impl, return a mapping from associated fn def id - /// to its associated type items that correspond to the RPITITs in its signature. - query associated_types_for_impl_traits_in_trait_or_impl(item_def_id: DefId) -> &'tcx DefIdMap> { - arena_cache - desc { |tcx| "synthesizing RPITIT items for the opaque types for methods in `{}`", tcx.def_path_str(item_def_id) } - separate_provide_extern - } - - /// Given an `impl_id`, return the trait it implements along with some header information. - query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { - desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } - cache_on_disk_if { impl_id.is_local() } - separate_provide_extern - } - - /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due - /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct - /// whose tail is one of those types. - query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool { - desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) } - } - - /// Maps a `DefId` of a type to a list of its inherent impls. - /// Contains implementations of methods that are inherent to a type. - /// Methods in these implementations don't need to be exported. - query inherent_impls(key: DefId) -> &'tcx [DefId] { - desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { - desc { |tcx| "collecting all inherent impls for `{:?}`", key } - } - - /// Unsafety-check this `LocalDefId`. - query check_transmutes(key: LocalDefId) { - desc { |tcx| "check transmute calls inside `{}`", tcx.def_path_str(key) } - } - - /// Unsafety-check this `LocalDefId`. - query check_unsafety(key: LocalDefId) { - desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } - } - - /// Checks well-formedness of tail calls (`become f()`). - query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { - desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Returns the types assumed to be well formed while "inside" of the given item. - /// - /// Note that we've liberated the late bound regions of function signatures, so - /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { - desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } - } - - /// We need to store the assumed_wf_types for an RPITIT so that impls of foreign - /// traits with return-position impl trait in traits can inherit the right wf types. - query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { - desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - /// Computes the signature of the function. - query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { - desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - cycle_delay_bug - } - - /// Performs lint checking for the module. - query lint_mod(key: LocalModDefId) { - desc { |tcx| "linting {}", describe_as_module(key, tcx) } - } - - query check_unused_traits(_: ()) { - desc { "checking unused trait imports in crate" } - } - - /// Checks the attributes in the module. - query check_mod_attrs(key: LocalModDefId) { - desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } - } - - /// Checks for uses of unstable APIs in the module. - query check_mod_unstable_api_usage(key: LocalModDefId) { - desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } - } - - query check_mod_privacy(key: LocalModDefId) { - desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } - } - - query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet { - arena_cache - desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } - cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } - } - - /// Return the live symbols in the crate for dead code check. - /// - /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). - query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( - LocalDefIdSet, - LocalDefIdMap>, - ), ErrorGuaranteed> { - arena_cache - desc { "finding live symbols in crate" } - } - - query check_mod_deathness(key: LocalModDefId) { - desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } - } - - query check_type_wf(key: ()) -> Result<(), ErrorGuaranteed> { - desc { "checking that types are well-formed" } - return_result_from_ensure_ok - } - - /// Caches `CoerceUnsized` kinds for impls on custom types. - query coerce_unsized_info(key: DefId) -> Result { - desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - return_result_from_ensure_ok - } - - query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { - desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) } - } - - query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { - desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - - query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } - return_result_from_ensure_ok - } - - /// Borrow-checks the given typeck root, e.g. functions, const/static items, - /// and its children, e.g. closures, inline consts. - query mir_borrowck(key: LocalDefId) -> Result< - &'tcx FxIndexMap>, - ErrorGuaranteed - > { - desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } - } - - /// Gets a complete map from all types to their inherent impls. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) { - desc { "finding all inherent impls defined in crate" } - } - - /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { - desc { "check for inherent impls that should not be defined in crate" } - return_result_from_ensure_ok - } - - /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { - desc { "check for overlap between inherent impls defined in this crate" } - return_result_from_ensure_ok - } - - /// Checks whether all impls in the crate pass the overlap check, returning - /// which impls fail it. If all impls are correct, the returned slice is empty. - query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| - "checking whether impl `{}` follows the orphan rules", - tcx.def_path_str(key), - } - return_result_from_ensure_ok - } - - /// Return the set of (transitive) callees that may result in a recursive call to `key`, - /// if we were able to walk all callees. - query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option> { - cycle_fatal - arena_cache - desc { |tcx| - "computing (transitive) callees of `{}` that may recurse", - tcx.def_path_str(key), - } - cache_on_disk_if { true } - } - - /// Obtain all the calls into other local functions - query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { - cycle_fatal - desc { |tcx| - "computing all local function calls in `{}`", - tcx.def_path_str(key.def_id()), - } - } - - /// Computes the tag (if any) for a given type and variant. - /// - /// `None` means that the variant doesn't need a tag (because it is niched). - /// - /// # Panics - /// - /// This query will panic for uninhabited variants and if the passed type is not an enum. - query tag_for_variant( - key: PseudoCanonicalInput<'tcx, (Ty<'tcx>, abi::VariantIdx)>, - ) -> Option { - desc { "computing variant tag for enum" } - } - - /// Evaluates a constant and returns the computed allocation. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::eval_to_const_value_raw`] or - /// [`Self::eval_to_valtree`] instead. - /// - ///
- query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) - -> EvalToAllocationRawResult<'tcx> { - desc { |tcx| - "const-evaluating + checking `{}`", - key.value.display(tcx) - } - cache_on_disk_if { true } - } - - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - query eval_static_initializer(key: DefId) -> EvalStaticInitializerRawResult<'tcx> { - desc { |tcx| - "evaluating initializer of static `{}`", - tcx.def_path_str(key) - } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Evaluates const items or anonymous constants[^1] into a representation - /// suitable for the type system and const generics. - /// - ///
- /// - /// **Do not call this** directly, use one of the following wrappers: - /// [`TyCtxt::const_eval_poly`], [`TyCtxt::const_eval_resolve`], - /// [`TyCtxt::const_eval_instance`], or [`TyCtxt::const_eval_global_id`]. - /// - ///
- /// - /// [^1]: Such as enum variant explicit discriminants or array lengths. - query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) - -> EvalToConstValueResult<'tcx> { - desc { |tcx| - "simplifying constant for the type system `{}`", - key.value.display(tcx) - } - depth_limit - cache_on_disk_if { true } - } - - /// Evaluate a constant and convert it to a type level constant or - /// return `None` if that is not possible. - query eval_to_valtree( - key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> - ) -> EvalToValTreeResult<'tcx> { - desc { "evaluating type-level constant" } - } - - /// Converts a type-level constant value into a MIR constant value. - query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue { - desc { "converting type-level constant value to MIR constant value"} - } - - // FIXME get rid of this with valtrees - query lit_to_const( - key: LitToConstInput<'tcx> - ) -> ty::Const<'tcx> { - desc { "converting literal to const" } - } - - query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { - desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Performs part of the privacy check and computes effective visibilities. - query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { - eval_always - desc { "checking effective visibilities" } - } - query check_private_in_public(module_def_id: LocalModDefId) { - desc { |tcx| - "checking for private elements in public interfaces for {}", - describe_as_module(module_def_id, tcx) - } - } - - query reachable_set(_: ()) -> &'tcx LocalDefIdSet { - arena_cache - desc { "reachability" } - cache_on_disk_if { true } - } - - /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body; - /// in the case of closures, this will be redirected to the enclosing function. - query region_scope_tree(def_id: DefId) -> &'tcx crate::middle::region::ScopeTree { - desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) } - } - - /// Generates a MIR body for the shim. - query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { - arena_cache - desc { - |tcx| "generating MIR shim for `{}`, instance={:?}", - tcx.def_path_str(key.def_id()), - key - } - } - - /// The `symbol_name` query provides the symbol name for calling a - /// given instance from the local crate. In particular, it will also - /// look up the correct symbol name of instances from upstream crates. - query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> { - desc { "computing the symbol for `{}`", key } - cache_on_disk_if { true } - } - - query def_kind(def_id: DefId) -> DefKind { - desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the definition. - query def_span(def_id: DefId) -> Span { - desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the identifier of the definition. - query def_ident_span(def_id: DefId) -> Option { - desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the type of the definition. - /// Panics if it is not a definition that has a single type. - query ty_span(def_id: LocalDefId) -> Span { - desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - query lookup_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - query lookup_const_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - query lookup_default_body_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up default body stability of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query should_inherit_track_caller(def_id: DefId) -> bool { - desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } - } - - query inherited_align(def_id: DefId) -> Option { - desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) } - } - - query lookup_deprecation_entry(def_id: DefId) -> Option { - desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Determines whether an item is annotated with `#[doc(hidden)]`. - query is_doc_hidden(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Determines whether an item is annotated with `#[doc(notable_trait)]`. - query is_doc_notable_trait(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } - } - - /// Returns the attributes on the item at `def_id`. - /// - /// Do not use this directly, use `tcx.get_attrs` instead. - query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] { - desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Returns the `CodegenFnAttrs` for the item at `def_id`. - /// - /// If possible, use `tcx.codegen_instance_attrs` instead. That function takes the - /// instance kind into account. - /// - /// For example, the `#[naked]` attribute should be applied for `InstanceKind::Item`, - /// but should not be applied if the instance kind is `InstanceKind::ReifyShim`. - /// Using this query would include the attribute regardless of the actual instance - /// kind at the call site. - query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs { - desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } - arena_cache - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { - desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } - } - - query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { - desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the rendered value of the specified constant or associated constant. - /// Used by rustdoc. - query rendered_const(def_id: DefId) -> &'tcx String { - arena_cache - desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the rendered precise capturing args for an opaque for use in rustdoc. - query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind]> { - desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query impl_parent(def_id: DefId) -> Option { - desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query is_ctfe_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query is_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query own_existential_vtable_entries( - key: DefId - ) -> &'tcx [DefId] { - desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } - } - - query vtable_entries(key: ty::TraitRef<'tcx>) - -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } - } - - query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { - desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() } - } - - query supertrait_vtable_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option { - desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable", - key.1, key.0 } - } - - query vtable_allocation(key: (Ty<'tcx>, Option>)) -> mir::interpret::AllocId { - desc { |tcx| "vtable const allocation for <{} as {}>", - key.0, - key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or_else(|| "_".to_owned()) - } - } - - query codegen_select_candidate( - key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> - ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { - cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.value } - } - - /// Return all `impl` blocks in the current crate. - query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap> { - desc { "finding local trait impls" } - } - - /// Return all `impl` blocks of the given trait in the current crate. - query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { - desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } - } - - /// Given a trait `trait_id`, return all known `impl` blocks. - query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { - arena_cache - desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } - } - - query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { - desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } - cache_on_disk_if { true } - return_result_from_ensure_ok - } - query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { - desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } - } - query is_dyn_compatible(trait_id: DefId) -> bool { - desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) } - } - - /// Gets the ParameterEnvironment for a given item; this environment - /// will be in "user-facing" mode, meaning that it is suitable for - /// type-checking etc, and it does not normalize specializable - /// associated types. - /// - /// You should almost certainly not use this. If you already have an InferCtxt, then - /// you should also probably have a `ParamEnv` from when it was built. If you don't, - /// then you should take a `TypingEnv` to ensure that you handle opaque types correctly. - query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { - desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } - feedable - } - - /// Like `param_env`, but returns the `ParamEnv` after all opaque types have been - /// replaced with their hidden type. This is used in the old trait solver - /// when in `PostAnalysis` mode and should not be called directly. - query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> { - desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } - } - - /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, - /// `ty.is_copy()`, etc, since that will prune the environment where possible. - query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Copy`", env.value } - } - /// Trait selection queries. These are best used by invoking `ty.is_use_cloned_modulo_regions()`, - /// `ty.is_use_cloned()`, etc, since that will prune the environment where possible. - query is_use_cloned_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `UseCloned`", env.value } - } - /// Query backing `Ty::is_sized`. - query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Sized`", env.value } - } - /// Query backing `Ty::is_freeze`. - query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is freeze", env.value } - } - /// Query backing `Ty::is_unpin`. - query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Unpin`", env.value } - } - /// Query backing `Ty::is_async_drop`. - query is_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `AsyncDrop`", env.value } - } - /// Query backing `Ty::needs_drop`. - query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` needs drop", env.value } - } - /// Query backing `Ty::needs_async_drop`. - query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` needs async drop", env.value } - } - /// Query backing `Ty::has_significant_drop_raw`. - query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` has a significant drop", env.value } - } - - /// Query backing `Ty::is_structural_eq_shallow`. - /// - /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types - /// correctly. - query has_structural_eq_impl(ty: Ty<'tcx>) -> bool { - desc { - "computing whether `{}` implements `StructuralPartialEq`", - ty - } - } - - /// A list of types where the ADT requires drop if and only if any of - /// those types require drop. If the ADT is known to always need drop - /// then `Err(AlwaysRequiresDrop)` is returned. - query adt_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` needs drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - /// A list of types where the ADT requires async drop if and only if any of - /// those types require async drop. If the ADT is known to always need async drop - /// then `Err(AlwaysRequiresDrop)` is returned. - query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` needs async drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - /// A list of types where the ADT requires drop if and only if any of those types - /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor` - /// is considered to not be significant. A drop is significant if it is implemented - /// by the user or does anything that will have any observable behavior (other than - /// freeing up memory). If the ADT is known to have a significant destructor then - /// `Err(AlwaysRequiresDrop)` is returned. - query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } - } - - /// Returns a list of types which (a) have a potentially significant destructor - /// and (b) may be dropped as a result of dropping a value of some type `ty` - /// (in the given environment). - /// - /// The idea of "significant" drop is somewhat informal and is used only for - /// diagnostics and edition migrations. The idea is that a significant drop may have - /// some visible side-effect on execution; freeing memory is NOT considered a side-effect. - /// The rules are as follows: - /// * Type with no explicit drop impl do not have significant drop. - /// * Types with a drop impl are assumed to have significant drop unless they have a `#[rustc_insignificant_dtor]` annotation. - /// - /// Note that insignificant drop is a "shallow" property. A type like `Vec` does not - /// have significant drop but the type `LockGuard` does, and so if `ty = Vec` - /// then the return value would be `&[LockGuard]`. - /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, - /// because this query partially depends on that query. - /// Otherwise, there is a risk of query cycles. - query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { - desc { |tcx| "computing when `{}` has a significant destructor", ty.value } - } - - /// Computes the layout of a type. Note that this implicitly - /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. - query layout_of( - key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> - ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { - depth_limit - desc { "computing layout of `{}`", key.value } - // we emit our own error during query cycle handling - cycle_delay_bug - } - - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` - /// instead, where the instance is an `InstanceKind::Virtual`. - query fn_abi_of_fn_ptr( - key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> - ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}` function pointers", key.value.0 } - } - - /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for - /// direct calls to an `fn`. - /// - /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceKind::Virtual` instance (of `::fn`). - query fn_abi_of_instance( - key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> - ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}`", key.value.0 } - } - - query dylib_dependency_formats(_: CrateNum) - -> &'tcx [(CrateNum, LinkagePreference)] { - desc { "getting dylib dependency formats of crate" } - separate_provide_extern - } - - query dependency_formats(_: ()) -> &'tcx Arc { - arena_cache - desc { "getting the linkage format of all dependencies" } - } - - query is_compiler_builtins(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate is_compiler_builtins" } - separate_provide_extern - } - query has_global_allocator(_: CrateNum) -> bool { - // This query depends on untracked global state in CStore - eval_always - cycle_fatal - desc { "checking if the crate has_global_allocator" } - separate_provide_extern - } - query has_alloc_error_handler(_: CrateNum) -> bool { - // This query depends on untracked global state in CStore - eval_always - cycle_fatal - desc { "checking if the crate has_alloc_error_handler" } - separate_provide_extern - } - query has_panic_handler(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate has_panic_handler" } - separate_provide_extern - } - query is_profiler_runtime(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if a crate is `#![profiler_runtime]`" } - separate_provide_extern - } - query has_ffi_unwind_calls(key: LocalDefId) -> bool { - desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - query required_panic_strategy(_: CrateNum) -> Option { - cycle_fatal - desc { "getting a crate's required panic strategy" } - separate_provide_extern - } - query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { - cycle_fatal - desc { "getting a crate's configured panic-in-drop strategy" } - separate_provide_extern - } - query is_no_builtins(_: CrateNum) -> bool { - cycle_fatal - desc { "getting whether a crate has `#![no_builtins]`" } - separate_provide_extern - } - query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { - cycle_fatal - desc { "getting a crate's symbol mangling version" } - separate_provide_extern - } - - query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> { - eval_always - desc { "getting crate's ExternCrateData" } - separate_provide_extern - } - - query specialization_enabled_in(cnum: CrateNum) -> bool { - desc { "checking whether the crate enabled `specialization`/`min_specialization`" } - separate_provide_extern - } - - query specializes(_: (DefId, DefId)) -> bool { - desc { "computing whether impls specialize one another" } - } - query in_scope_traits_map(_: hir::OwnerId) - -> Option<&'tcx ItemLocalMap>> { - desc { "getting traits in scope at a block" } - } - - /// Returns whether the impl or associated function has the `default` keyword. - /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`. - query defaultness(def_id: DefId) -> hir::Defaultness { - desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - /// Returns whether the field corresponding to the `DefId` has a default field value. - query default_field(def_id: DefId) -> Option { - desc { |tcx| "looking up the `const` corresponding to the default for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - // The `DefId`s of all non-generic functions and statics in the given crate - // that can be reached from outside the crate. - // - // We expect this items to be available for being linked to. - // - // This query can also be called for `LOCAL_CRATE`. In this case it will - // compute which items will be reachable to other crates, taking into account - // the kind of crate that is currently compiled. Crates with only a - // C interface have fewer reachable things. - // - // Does not include external symbols that don't have a corresponding DefId, - // like the compiler-generated `main` function and so on. - query reachable_non_generics(_: CrateNum) - -> &'tcx DefIdMap { - arena_cache - desc { "looking up the exported symbols of a crate" } - separate_provide_extern - } - query is_reachable_non_generic(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - query is_unreachable_local_definition(def_id: LocalDefId) -> bool { - desc { |tcx| - "checking whether `{}` is reachable from outside the crate", - tcx.def_path_str(def_id), - } - } - - /// The entire set of monomorphizations the local crate can safely - /// link to because they are exported from upstream crates. Do - /// not depend on this directly, as its value changes anytime - /// a monomorphization gets added or removed in any upstream - /// crate. Instead use the narrower `upstream_monomorphizations_for`, - /// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or, - /// even better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { - arena_cache - desc { "collecting available upstream monomorphizations" } - } - - /// Returns the set of upstream monomorphizations available for the - /// generic function identified by the given `def_id`. The query makes - /// sure to make a stable selection if the same monomorphization is - /// available in multiple upstream crates. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx UnordMap, CrateNum>> - { - desc { |tcx| - "collecting available upstream monomorphizations for `{}`", - tcx.def_path_str(def_id), - } - separate_provide_extern - } - - /// Returns the upstream crate that exports drop-glue for the given - /// type (`args` is expected to be a single-item list containing the - /// type one wants drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order to - /// increase dep-tracking granularity. Otherwise adding or removing any - /// type with drop-glue in any upstream crate would invalidate all - /// functions calling drop-glue of an upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream drop-glue for `{:?}`", args } - } - - /// Returns the upstream crate that exports async-drop-glue for - /// the given type (`args` is expected to be a single-item list - /// containing the type one wants async-drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order - /// to increase dep-tracking granularity. Otherwise adding or - /// removing any type with async-drop-glue in any upstream crate - /// would invalidate all functions calling async-drop-glue of an - /// upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream async-drop-glue for `{:?}`", args } - } - - /// Returns a list of all `extern` blocks of a crate. - query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap { - arena_cache - desc { "looking up the foreign modules of a linked crate" } - separate_provide_extern - } - - /// Lint against `extern fn` declarations having incompatible types. - query clashing_extern_declarations(_: ()) { - desc { "checking `extern fn` declarations are compatible" } - } - - /// Identifies the entry-point (e.g., the `main` function) for a given - /// crate, returning `None` if there is no entry point (such as for library crates). - query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { - desc { "looking up the entry function of a crate" } - } - - /// Finds the `rustc_proc_macro_decls` item of a crate. - query proc_macro_decls_static(_: ()) -> Option { - desc { "looking up the proc macro declarations for a crate" } - } - - // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. - // Changing the name should cause a compiler error, but in case that changes, be aware. - // - // The hash should not be calculated before the `analysis` pass is complete, specifically - // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental - // compilation is enabled calculating this hash can freeze this structure too early in - // compilation and cause subsequent crashes when attempting to write to `definitions` - query crate_hash(_: CrateNum) -> Svh { - eval_always - desc { "looking up the hash a crate" } - separate_provide_extern - } - - /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. - query crate_host_hash(_: CrateNum) -> Option { - eval_always - desc { "looking up the hash of a host version of a crate" } - separate_provide_extern - } - - /// Gets the extra data to put in each output filename for a crate. - /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. - query extra_filename(_: CrateNum) -> &'tcx String { - arena_cache - eval_always - desc { "looking up the extra filename for a crate" } - separate_provide_extern - } - - /// Gets the paths where the crate came from in the file system. - query crate_extern_paths(_: CrateNum) -> &'tcx Vec { - arena_cache - eval_always - desc { "looking up the paths for extern crates" } - separate_provide_extern - } - - /// Given a crate and a trait, look up all impls of that trait in the crate. - /// Return `(impl_id, self_ty)`. - query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { - desc { "looking up implementations of a trait in a crate" } - separate_provide_extern - } - - /// Collects all incoherent impls for the given crate and type. - /// - /// Do not call this directly, but instead use the `incoherent_impls` query. - /// This query is only used to get the data necessary for that query. - query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { - desc { |tcx| "collecting all impls for a type in a crate" } - separate_provide_extern - } - - /// Get the corresponding native library from the `native_libraries` query - query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { - desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } - } - - query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] { - desc { "inheriting delegation signature" } - } - - /// Does lifetime resolution on items. Importantly, we can't resolve - /// lifetimes directly on things like trait methods, because of trait params. - /// See `rustc_resolve::late::lifetimes` for details. - query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars { - arena_cache - desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } - } - query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { - desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } - } - query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { - desc { |tcx| "testing if a region is late bound inside `{}`", tcx.def_path_str(owner_id) } - } - /// Returns the *default lifetime* to be used if a trait object type were to be passed for - /// the type parameter given by `DefId`. - /// - /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically - /// print the result of this query for use in UI tests or for debugging purposes. - /// - /// # Examples - /// - /// - For `T` in `struct Foo<'a, T: 'a>(&'a T);`, this would be `Param('a)` - /// - For `T` in `struct Bar<'a, T>(&'a T);`, this would be `Empty` - /// - /// # Panics - /// - /// This query will panic if the given definition is not a type parameter. - query object_lifetime_default(def_id: DefId) -> ObjectLifetimeDefault { - desc { "looking up lifetime defaults for type parameter `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - query late_bound_vars_map(owner_id: hir::OwnerId) - -> &'tcx SortedMap> { - desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } - } - /// For an opaque type, return the list of (captured lifetime, inner generic param). - /// ```ignore (illustrative) - /// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into + 'b { ... } - /// ``` - /// - /// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound. - /// - /// After hir_ty_lowering, we get: - /// ```ignore (pseudo-code) - /// opaque foo::<'a>::opaque<'_a, '_b>: Into> + '_b; - /// ^^^^^^^^ inner generic params - /// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b> - /// ^^^^^^ captured lifetimes - /// ``` - query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] { - desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } - } - - /// Computes the visibility of the provided `def_id`. - /// - /// If the item from the `def_id` doesn't have a visibility, it will panic. For example - /// a generic type parameter will panic if you call this method on it: - /// - /// ``` - /// use std::fmt::Debug; - /// - /// pub trait Foo {} - /// ``` - /// - /// In here, if you call `visibility` on `T`, it'll panic. - query visibility(def_id: DefId) -> ty::Visibility { - desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { - desc { "computing the uninhabited predicate of `{:?}`", key } - } - - /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead. - query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> { - desc { "computing the uninhabited predicate of `{}`", key } - } - - query dep_kind(_: CrateNum) -> CrateDepKind { - eval_always - desc { "fetching what a dependency looks like" } - separate_provide_extern - } - - /// Gets the name of the crate. - query crate_name(_: CrateNum) -> Symbol { - feedable - desc { "fetching what a crate is named" } - separate_provide_extern - } - query module_children(def_id: DefId) -> &'tcx [ModChild] { - desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the number of definitions in a foreign crate. - /// - /// This allows external tools to iterate over all definitions in a foreign crate. - /// - /// This should never be used for the local crate, instead use `iter_local_def_id`. - query num_extern_def_ids(_: CrateNum) -> usize { - desc { "fetching the number of definitions in a crate" } - separate_provide_extern - } - - query lib_features(_: CrateNum) -> &'tcx LibFeatures { - desc { "calculating the lib features defined in a crate" } - separate_provide_extern - arena_cache - } - /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` - /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute - /// exists, then this map will have a `impliee -> implier` entry. - /// - /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should - /// specify their implications (both `implies` and `implied_by`). If only one of the two - /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this - /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is - /// reported, only the `#[stable]` attribute information is available, so the map is necessary - /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` - /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of - /// unstable feature" error for a feature that was implied. - query stability_implications(_: CrateNum) -> &'tcx UnordMap { - arena_cache - desc { "calculating the implications between `#[unstable]` features defined in a crate" } - separate_provide_extern - } - /// Whether the function is an intrinsic - query intrinsic_raw(def_id: DefId) -> Option { - desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) } - separate_provide_extern - } - /// Returns the lang items defined in another crate by loading it from metadata. - query get_lang_items(_: ()) -> &'tcx LanguageItems { - arena_cache - eval_always - desc { "calculating the lang items map" } - } - - /// Returns all diagnostic items defined in all crates. - query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { - arena_cache - eval_always - desc { "calculating the diagnostic items map" } - } - - /// Returns the lang items defined in another crate by loading it from metadata. - query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] { - desc { "calculating the lang items defined in a crate" } - separate_provide_extern - } - - /// Returns the diagnostic items defined in a crate. - query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { - arena_cache - desc { "calculating the diagnostic items map in a crate" } - separate_provide_extern - } - - query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { - desc { "calculating the missing lang items in a crate" } - separate_provide_extern - } - - /// The visible parent map is a map from every item to a visible parent. - /// It prefers the shortest visible path to an item. - /// Used for diagnostics, for example path trimming. - /// The parents are modules, enums or traits. - query visible_parent_map(_: ()) -> &'tcx DefIdMap { - arena_cache - desc { "calculating the visible parent map" } - } - /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. - /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. - query trimmed_def_paths(_: ()) -> &'tcx DefIdMap { - arena_cache - desc { "calculating trimmed def paths" } - } - query missing_extern_crate_item(_: CrateNum) -> bool { - eval_always - desc { "seeing if we're missing an `extern crate` item for this crate" } - separate_provide_extern - } - query used_crate_source(_: CrateNum) -> &'tcx Arc { - arena_cache - eval_always - desc { "looking at the source for a crate" } - separate_provide_extern - } - - /// Returns the debugger visualizers defined for this crate. - /// NOTE: This query has to be marked `eval_always` because it reads data - /// directly from disk that is not tracked anywhere else. I.e. it - /// represents a genuine input to the query system. - query debugger_visualizers(_: CrateNum) -> &'tcx Vec { - arena_cache - desc { "looking up the debugger visualizers for this crate" } - separate_provide_extern - eval_always - } - - query postorder_cnums(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "generating a postorder list of CrateNums" } - } - /// Returns whether or not the crate with CrateNum 'cnum' - /// is marked as a private dependency - query is_private_dep(c: CrateNum) -> bool { - eval_always - desc { "checking whether crate `{}` is a private dependency", c } - separate_provide_extern - } - query allocator_kind(_: ()) -> Option { - eval_always - desc { "getting the allocator kind for the current crate" } - } - query alloc_error_handler_kind(_: ()) -> Option { - eval_always - desc { "alloc error handler kind for the current crate" } - } - - query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { - desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } - } - - /// All available crates in the graph, including those that should not be user-facing - /// (such as private crates). - query crates(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "fetching all foreign CrateNum instances" } - } - - // Crates that are loaded non-speculatively (not for diagnostics or doc links). - // FIXME: This is currently only used for collecting lang items, but should be used instead of - // `crates` in most other cases too. - query used_crates(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } - } - - /// All crates that share the same name as crate `c`. - /// - /// This normally occurs when multiple versions of the same dependency are present in the - /// dependency tree. - query duplicate_crate_names(c: CrateNum) -> &'tcx [CrateNum] { - desc { "fetching `CrateNum`s with same name as `{c:?}`" } - } - - /// A list of all traits in a crate, used by rustdoc and error reporting. - query traits(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all traits in a crate" } - separate_provide_extern - } - - query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all trait impls in a crate" } - separate_provide_extern - } - - query stable_order_of_exportable_impls(_: CrateNum) -> &'tcx FxIndexMap { - desc { "fetching the stable impl's order" } - separate_provide_extern - } - - query exportable_items(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all exportable items in a crate" } - separate_provide_extern - } - - /// The list of non-generic symbols exported from the given crate. - /// - /// This is separate from exported_generic_symbols to avoid having - /// to deserialize all non-generic symbols too for upstream crates - /// in the upstream_monomorphizations query. - /// - /// - All names contained in `exported_non_generic_symbols(cnum)` are - /// guaranteed to correspond to a publicly visible symbol in `cnum` - /// machine code. - /// - The `exported_non_generic_symbols` and `exported_generic_symbols` - /// sets of different crates do not intersect. - query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "collecting exported non-generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } - - /// The list of generic symbols exported from the given crate. - /// - /// - All names contained in `exported_generic_symbols(cnum)` are - /// guaranteed to correspond to a publicly visible symbol in `cnum` - /// machine code. - /// - The `exported_non_generic_symbols` and `exported_generic_symbols` - /// sets of different crates do not intersect. - query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "collecting exported generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } - - query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> { - eval_always - desc { "collect_and_partition_mono_items" } - } - - query is_codegened_item(def_id: DefId) -> bool { - desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } - } - - query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { - desc { "getting codegen unit `{sym}`" } - } - - query backend_optimization_level(_: ()) -> OptLevel { - desc { "optimization level used by backend" } - } - - /// Return the filenames where output artefacts shall be stored. - /// - /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` - /// has been destroyed. - query output_filenames(_: ()) -> &'tcx Arc { - feedable - desc { "getting output filenames" } - arena_cache - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_projection( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_free_alias( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_inherent_projection( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. - query try_normalize_generic_arg_after_erasing_regions( - goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> - ) -> Result, NoSolution> { - desc { "normalizing `{}`", goal.value } - } - - query implied_outlives_bounds( - key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool) - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, - NoSolution, - > { - desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 } - } - - /// Do not call this query directly: - /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. - query dropck_outlives( - goal: CanonicalDropckOutlivesGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, - NoSolution, - > { - desc { "computing dropck types for `{}`", goal.canonical.value.value.dropped_ty } - } - - /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or - /// `infcx.predicate_must_hold()` instead. - query evaluate_obligation( - goal: CanonicalPredicateGoal<'tcx> - ) -> Result { - desc { "evaluating trait selection obligation `{}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `Eq` type-op - query type_op_ascribe_user_type( - goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `ProvePredicate` type-op - query type_op_prove_predicate( - goal: CanonicalTypeOpProvePredicateGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_ty( - goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_clause( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_poly_fn_sig( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_fn_sig( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { - desc { |tcx| - "checking impossible instantiated predicates: `{}`", - tcx.def_path_str(key.0) - } - } - - query is_impossible_associated_item(key: (DefId, DefId)) -> bool { - desc { |tcx| - "checking if `{}` is impossible to reference within `{}`", - tcx.def_path_str(key.1), - tcx.def_path_str(key.0), - } - } - - query method_autoderef_steps( - goal: CanonicalMethodAutoderefStepsGoal<'tcx> - ) -> MethodAutoderefStepsResult<'tcx> { - desc { "computing autoderef types for `{}`", goal.canonical.value.value.self_ty } - } - - /// Used by `-Znext-solver` to compute proof trees. - query evaluate_root_goal_for_proof_tree_raw( - goal: solve::CanonicalInput<'tcx>, - ) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe>) { - no_hash - desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate } - } - - /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! - query rust_target_features(_: CrateNum) -> &'tcx UnordMap { - arena_cache - eval_always - desc { "looking up Rust target features" } - } - - query implied_target_features(feature: Symbol) -> &'tcx Vec { - arena_cache - eval_always - desc { "looking up implied target features" } - } - - query features_query(_: ()) -> &'tcx rustc_feature::Features { - feedable - desc { "looking up enabled feature gates" } - } - - query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { - feedable - no_hash - desc { "the ast before macro expansion and name resolution" } - } - - /// Attempt to resolve the given `DefId` to an `Instance`, for the - /// given generics args (`GenericArgsRef`), returning one of: - /// * `Ok(Some(instance))` on success - /// * `Ok(None)` when the `GenericArgsRef` are still too generic, - /// and therefore don't allow finding the final `Instance` - /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process - /// couldn't complete due to errors elsewhere - this is distinct - /// from `Ok(None)` to avoid misleading diagnostics when an error - /// has already been/will be emitted, for the original cause. - query resolve_instance_raw( - key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> - ) -> Result>, ErrorGuaranteed> { - desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) } - } - - query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { - desc { "revealing opaque types in `{:?}`", key } - } - - query limits(key: ()) -> Limits { - desc { "looking up limits" } - } - - /// Performs an HIR-based well-formed check on the item with the given `HirId`. If - /// we get an `Unimplemented` error that matches the provided `Predicate`, return - /// the cause of the newly created obligation. - /// - /// This is only used by error-reporting code to get a better cause (in particular, a better - /// span) for an *existing* error. Therefore, it is best-effort, and may never handle - /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, - /// because the `ty::Ty`-based wfcheck is always run. - query diagnostic_hir_wf_check( - key: (ty::Predicate<'tcx>, WellFormedLoc) - ) -> Option<&'tcx ObligationCause<'tcx>> { - arena_cache - eval_always - no_hash - desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } - } - - /// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, - /// `--target` and similar). - query global_backend_features(_: ()) -> &'tcx Vec { - arena_cache - eval_always - desc { "computing the backend features for CLI flags" } - } - - query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { - desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } - } - - /// This takes the def-id of an associated item from a impl of a trait, - /// and checks its validity against the trait item it corresponds to. - /// - /// Any other def id will ICE. - query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - query deduced_param_attrs(def_id: DefId) -> &'tcx [DeducedParamAttrs] { - desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap { - eval_always - desc { "resolutions for documentation links for a module" } - separate_provide_extern - } - - query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] { - eval_always - desc { "traits in scope for documentation links for a module" } - separate_provide_extern - } - - /// Get all item paths that were stripped by a `#[cfg]` in a particular crate. - /// Should not be called for the local crate before the resolver outputs are created, as it - /// is only fed there. - query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { - desc { "getting cfg-ed out item names" } - separate_provide_extern - } - - query generics_require_sized_self(def_id: DefId) -> bool { - desc { "check whether the item has a `where Self: Sized` bound" } - } - - query cross_crate_inlinable(def_id: DefId) -> bool { - desc { "whether the item should be made inlinable across crates" } - separate_provide_extern - } - - /// Perform monomorphization-time checking on this item. - /// This is used for lints/errors that can only be checked once the instance is fully - /// monomorphized. - query check_mono_item(key: ty::Instance<'tcx>) { - desc { "monomorphization-time checking" } - } - - /// Builds the set of functions that should be skipped for the move-size check. - query skip_move_check_fns(_: ()) -> &'tcx FxIndexSet { - arena_cache - desc { "functions to skip for move-size check" } - } - - query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { - desc { "collecting items used by `{}`", key.0 } - cache_on_disk_if { true } - } - - query size_estimate(key: ty::Instance<'tcx>) -> usize { - desc { "estimating codegen size of `{}`", key } - cache_on_disk_if { true } - } - - query anon_const_kind(def_id: DefId) -> ty::AnonConstKind { - desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query trivial_const(def_id: DefId) -> Option<(mir::ConstValue, Ty<'tcx>)> { - desc { |tcx| "checking if `{}` is a trivial const", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Checks for the nearest `#[sanitize(xyz = "off")]` or - /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the - /// crate root. - /// - /// Returns the sanitizer settings for this def. - query sanitizer_settings_for(key: LocalDefId) -> SanitizerFnAttrs { - desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } - feedable - } - - query check_externally_implementable_items(_: ()) { - desc { "check externally implementable items" } - } - - /// Returns a list of all `externally implementable items` crate. - query externally_implementable_items(cnum: CrateNum) -> &'tcx FxIndexMap)> { - arena_cache - desc { "looking up the externally implementable items of a crate" } - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } -} - -rustc_with_all_queries! { define_callbacks! } -rustc_feedable_queries! { define_feedable! } - -fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { +pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { let def_id = def_id.into(); if def_id.is_top_level_module() { "top-level module".to_string() @@ -2794,3 +36,18 @@ fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String format!("module `{}`", tcx.def_path_str(def_id)) } } + +pub trait QueryContext<'tcx>: HasDepContext { + /// Gets a jobserver reference which is used to release then acquire + /// a token while waiting on a query. + fn jobserver_proxy(&self) -> &Proxy; + + /// Load a side effect associated to the node in the previous session. + fn load_side_effect( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option; + + /// Register a side effect for the given node, for use in next session. + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); +} diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs new file mode 100644 index 000000000000..81b9f0da6446 --- /dev/null +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -0,0 +1,77 @@ +//! This contains documentation which is linked from query modifiers used in the `rustc_queries!` proc macro. +#![allow(unused, non_camel_case_types)] +// FIXME: Update and clarify documentation for these modifiers. + +/// # `desc` query modifier +/// +/// The description of the query. This modifier is required on every query. +pub struct desc; + +/// # `arena_cache` query modifier +/// +/// Use this type for the in-memory cache. +pub struct arena_cache; + +/// # `cache_on_disk_if` query modifier +/// +/// Cache the query to disk if the `Block` returns true. +pub struct cache_on_disk_if; + +/// # `cycle_fatal` query modifier +/// +/// A cycle error for this query aborting the compilation with a fatal error. +pub struct cycle_fatal; + +/// # `cycle_delay_bug` query modifier +/// +/// A cycle error results in a delay_bug call +pub struct cycle_delay_bug; + +/// # `cycle_stash` query modifier +/// +/// A cycle error results in a stashed cycle error that can be unstashed and canceled later +pub struct cycle_stash; + +/// # `no_hash` query modifier +/// +/// Don't hash the result, instead just mark a query red if it runs +pub struct no_hash; + +/// # `anon` query modifier +/// +/// Generate a dep node based on the dependencies of the query +pub struct anon; + +/// # `eval_always` query modifier +/// +/// Always evaluate the query, ignoring its dependencies +pub struct eval_always; + +/// # `depth_limit` query modifier +/// +/// Whether the query has a call depth limit +pub struct depth_limit; + +/// # `separate_provide_extern` query modifier +/// +/// Use a separate query provider for local and extern crates +pub struct separate_provide_extern; + +/// # `feedable` query modifier +/// +/// Generate a `feed` method to set the query's value from another query. +pub struct feedable; + +/// # `return_result_from_ensure_ok` query modifier +/// +/// When this query is called via `tcx.ensure_ok()`, it returns +/// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to +/// be executed, and that execution returns an error, the error result is +/// returned to the caller. +/// +/// If execution is skipped, a synthetic `Ok(())` is returned, on the +/// assumption that a query with all-green inputs must have succeeded. +/// +/// Can only be applied to queries with a return value of +/// `Result<_, ErrorGuaranteed>`. +pub struct return_result_from_ensure_ok; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 0e536352563f..727e93148251 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -1,26 +1,110 @@ +use std::fmt::Debug; use std::ops::Deref; +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::hash_table::HashTable; +use rustc_data_structures::sharded::Sharded; use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; -use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; -pub(crate) use rustc_query_system::query::QueryJobId; -use rustc_query_system::query::{CycleError, CycleErrorHandling, HashResult, QueryCache}; +use rustc_query_system::ich::StableHashingContext; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; use crate::dep_graph; -use crate::dep_graph::DepKind; -use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use crate::query::{ +use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; +use crate::queries::{ ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates, }; +use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; +use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; +use crate::query::{QueryCache, QueryInfo, QueryJob}; use crate::ty::TyCtxt; +/// For a particular query, keeps track of "active" keys, i.e. keys whose +/// evaluation has started but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) +pub struct QueryState<'tcx, K> { + pub active: Sharded)>>, +} + +impl<'tcx, K> Default for QueryState<'tcx, K> { + fn default() -> QueryState<'tcx, K> { + QueryState { active: Default::default() } + } +} + +/// For a particular query and key, tracks the status of a query evaluation +/// that has started, but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) +pub enum ActiveKeyStatus<'tcx> { + /// Some thread is already evaluating the query for this key. + /// + /// The enclosed [`QueryJob`] can be used to wait for it to finish. + Started(QueryJob<'tcx>), + + /// The query panicked. Queries trying to wait on this will raise a fatal error which will + /// silently panic. + Poisoned, +} + +/// How a particular query deals with query cycle errors. +/// +/// Inspected by the code that actually handles cycle errors, to decide what +/// approach to use. +#[derive(Copy, Clone)] +pub enum CycleErrorHandling { + Error, + Fatal, + DelayBug, + Stash, +} + +pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; + +pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( + tcx: TyCtxt<'tcx>, + key: &Key, + prev_index: SerializedDepNodeIndex, + index: DepNodeIndex, +) -> Option; + +pub type IsLoadableFromDiskFn<'tcx, Key> = + fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool; + +pub type HashResult = Option, &V) -> Fingerprint>; + +#[derive(Clone, Debug)] +pub struct CycleError { + /// The query and related span that uses the cycle. + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec>, +} + +impl<'tcx> CycleError> { + pub fn lift(&self) -> CycleError { + CycleError { + usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())), + cycle: self.cycle.iter().map(|info| info.lift()).collect(), + } + } +} + +#[derive(Debug)] +pub enum QueryMode { + Get, + Ensure { check_cache: bool }, +} + /// Stores function pointers and other metadata for a particular query. /// -/// Used indirectly by query plumbing in `rustc_query_system`, via a trait. +/// Used indirectly by query plumbing in `rustc_query_system` via a trait, +/// and also used directly by query plumbing in `rustc_query_impl`. pub struct QueryVTable<'tcx, C: QueryCache> { pub name: &'static str, pub eval_always: bool, @@ -31,22 +115,34 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub query_state: usize, // Offset of this query's cache field in the QueryCaches struct pub query_cache: usize, - pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, - pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, - pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, - pub can_load_from_disk: bool, - pub try_load_from_disk: fn( - tcx: TyCtxt<'tcx>, - key: &C::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option, - pub loadable_from_disk: - fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, + pub will_cache_on_disk_for_key_fn: Option>, + + /// Function pointer that calls `tcx.$query(key)` for this query and + /// discards the returned value. + /// + /// This is a weird thing to be doing, and probably not what you want. + /// It is used for loading query results from disk-cache in some cases. + pub call_query_method_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key), + + /// Function pointer that actually calls this query's provider. + /// Also performs some associated secondary tasks; see the macro-defined + /// implementation in `mod invoke_provider_fn` for more details. + /// + /// This should be the only code that calls the provider function. + pub invoke_provider_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, + + pub try_load_from_disk_fn: Option>, + pub is_loadable_from_disk_fn: Option>, pub hash_result: HashResult, pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value, pub format_value: fn(&C::Value) -> String, + + /// Formats a human-readable description of this query and its key, as + /// specified by the `desc` query modifier. + /// + /// Used when reporting query cycle errors and similar problems. + pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String, } pub struct QuerySystemFns { @@ -184,8 +280,8 @@ macro_rules! query_ensure_select { } macro_rules! query_helper_param_ty { - (DefId) => { impl IntoQueryParam }; - (LocalDefId) => { impl IntoQueryParam }; + (DefId) => { impl $crate::query::IntoQueryParam }; + (LocalDefId) => { impl $crate::query::IntoQueryParam }; ($K:ty) => { $K }; } @@ -208,7 +304,7 @@ macro_rules! local_key_if_separate_extern { $($K)* }; ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => { - <$($K)* as AsLocalKey>::LocalKey + <$($K)* as $crate::query::AsLocalKey>::LocalKey }; ([$other:tt $($modifiers:tt)*] $($K:tt)*) => { local_key_if_separate_extern!([$($modifiers)*] $($K)*) @@ -222,8 +318,8 @@ macro_rules! separate_provide_extern_decl { ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { for<'tcx> fn( TyCtxt<'tcx>, - queries::$name::Key<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx> + $name::Key<'tcx>, + ) -> $name::ProvidedValue<'tcx> }; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { separate_provide_extern_decl!([$($modifiers)*][$($args)*]) @@ -261,89 +357,82 @@ macro_rules! define_callbacks { [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { + $(#[allow(unused_lifetimes)] pub mod $name { + use super::*; + use $crate::query::erase::{self, Erased}; - #[allow(unused_lifetimes)] - pub mod queries { - $(pub mod $name { - use super::super::*; + pub type Key<'tcx> = $($K)*; + pub type Value<'tcx> = $V; - pub type Key<'tcx> = $($K)*; - pub type Value<'tcx> = $V; + pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); - pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); + /// This type alias specifies the type returned from query providers and the type + /// used for decoding. For regular queries this is the declared returned type `V`, + /// but `arena_cache` will use `::Provided` instead. + pub type ProvidedValue<'tcx> = query_if_arena!( + [$($modifiers)*] + (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) + ($V) + ); - /// This type alias specifies the type returned from query providers and the type - /// used for decoding. For regular queries this is the declared returned type `V`, - /// but `arena_cache` will use `::Provided` instead. - pub type ProvidedValue<'tcx> = query_if_arena!( - [$($modifiers)*] - (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) - ($V) - ); + /// This helper function takes a value returned by the query provider + /// (or loaded from disk, or supplied by query feeding), allocates + /// it in an arena if requested by the `arena_cache` modifier, and + /// then returns an erased copy of it. + #[inline(always)] + pub fn provided_to_erased<'tcx>( + tcx: TyCtxt<'tcx>, + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // For queries with the `arena_cache` modifier, store the + // provided value in an arena and get a reference to it. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] { + <$V as $crate::query::arena_cached::ArenaCached>::alloc_in_arena( + tcx, + &tcx.query_system.arenas.$name, + provided_value, + ) + } { + // Otherwise, the provided value is the value (and `tcx` is unused). + let _ = tcx; + provided_value + }); + erase::erase_val(value) + } - /// This function takes `ProvidedValue` and converts it to an erased `Value` by - /// allocating it on an arena if the query has the `arena_cache` modifier. The - /// value is then erased and returned. This will happen when computing the query - /// using a provider or decoding a stored result. - #[inline(always)] - pub fn provided_to_erased<'tcx>( - _tcx: TyCtxt<'tcx>, - value: ProvidedValue<'tcx>, - ) -> Erase> { - erase(query_if_arena!([$($modifiers)*] - { - use $crate::query::arena_cached::ArenaCached; + pub type Storage<'tcx> = <$($K)* as $crate::query::Key>::Cache>; - if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.query_system.arenas.$name.alloc(v), - value, - ) - } else { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.arena.dropless.alloc(v), - value, - ) - } - } - (value) - )) + // Ensure that keys grow no larger than 88 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + const _: () = { + if size_of::>() > 88 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a key type `", + stringify!($($K)*), + "` that is too large" + )); } + }; - pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; - - // Ensure that keys grow no larger than 88 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - const _: () = { - if size_of::>() > 88 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a key type `", - stringify!($($K)*), - "` that is too large" - )); - } - }; - - // Ensure that values grow no larger than 64 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - #[cfg(not(feature = "rustc_randomized_layouts"))] - const _: () = { - if size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a value type `", - stringify!($V), - "` that is too large" - )); - } - }; - })* - } + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] + const _: () = { + if size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a value type `", + stringify!($V), + "` that is too large" + )); + } + }; + })* /// Holds per-query arenas for queries with the `arena_cache` modifier. #[derive(Default)] @@ -361,10 +450,10 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryCaches<'tcx> { - $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)* + $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* } - impl<'tcx> TyCtxtEnsureOk<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name( @@ -376,13 +465,13 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), false, ) })* } - impl<'tcx> TyCtxtEnsureDone<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { @@ -390,7 +479,7 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), true, ); })* @@ -406,17 +495,19 @@ macro_rules! define_callbacks { })* } - impl<'tcx> TyCtxtAt<'tcx> { + impl<'tcx> $crate::query::TyCtxtAt<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { - restore::<$V>(crate::query::inner::query_get_at( + use $crate::query::{erase, inner}; + + erase::restore_val::<$V>(inner::query_get_at( self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, self.span, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), )) })* } @@ -426,22 +517,26 @@ macro_rules! define_callbacks { /// ("Per" just makes this pluralized name more visually distinct.) pub struct PerQueryVTables<'tcx> { $( - pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, queries::$name::Storage<'tcx>>, + pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Storage<'tcx>>, )* } #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>, + pub $name: $crate::query::QueryState<'tcx, $($K)*>, )* } pub struct Providers { - $(pub $name: for<'tcx> fn( - TyCtxt<'tcx>, - queries::$name::LocalKey<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx>,)* + $( + /// This is the provider for the query. Use `Find references` on this to + /// navigate between the provider assignment and the query definition. + pub $name: for<'tcx> fn( + TyCtxt<'tcx>, + $name::LocalKey<'tcx>, + ) -> $name::ProvidedValue<'tcx>, + )* } pub struct ExternProviders { @@ -478,47 +573,33 @@ macro_rules! define_callbacks { $(pub $name: for<'tcx> fn( TyCtxt<'tcx>, Span, - queries::$name::Key<'tcx>, - QueryMode, - ) -> Option>,)* + $name::Key<'tcx>, + $crate::query::QueryMode, + ) -> Option<$crate::query::erase::Erased<$V>>,)* } }; } -macro_rules! hash_result { - ([]) => {{ - Some(dep_graph::hash_result) - }}; - ([(no_hash) $($rest:tt)*]) => {{ - None - }}; - ([$other:tt $($modifiers:tt)*]) => { - hash_result!([$($modifiers)*]) - }; -} - macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(impl<'tcx, K: $crate::query::IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { $(#[$attr])* #[inline(always)] - pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) { + pub fn $name(self, value: $name::ProvidedValue<'tcx>) { let key = self.key().into_query_param(); let tcx = self.tcx; - let erased = queries::$name::provided_to_erased(tcx, value); - let cache = &tcx.query_system.caches.$name; + let erased_value = $name::provided_to_erased(tcx, value); let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; - let hasher: Option, &_) -> _> = hash_result!([$($modifiers)*]); $crate::query::inner::query_feed( tcx, dep_kind, - hasher, - cache, + &tcx.query_system.query_vtables.$name, + &tcx.query_system.caches.$name, key, - erased, + erased_value, ); } })* diff --git a/compiler/rustc_middle/src/query/stack.rs b/compiler/rustc_middle/src/query/stack.rs new file mode 100644 index 000000000000..b2b01517b7ee --- /dev/null +++ b/compiler/rustc_middle/src/query/stack.rs @@ -0,0 +1,112 @@ +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::transmute; +use std::sync::Arc; + +use rustc_data_structures::sync::{DynSend, DynSync}; +use rustc_hashes::Hash64; +use rustc_hir::def::DefKind; +use rustc_span::Span; +use rustc_span::def_id::DefId; + +use crate::dep_graph::DepKind; + +/// Description of a frame in the query stack. +/// +/// This is mostly used in case of cycles for error reporting. +#[derive(Clone, Debug)] +pub struct QueryStackFrame { + /// This field initially stores a `QueryStackDeferred` during collection, + /// but can later be changed to `QueryStackFrameExtra` containing concrete information + /// by calling `lift`. This is done so that collecting query does not need to invoke + /// queries, instead `lift` will call queries in a more appropriate location. + pub info: I, + + pub dep_kind: DepKind, + /// This hash is used to deterministically pick + /// a query to remove cycles in the parallel compiler. + pub hash: Hash64, + pub def_id: Option, + /// A def-id that is extracted from a `Ty` in a query key + pub def_id_for_ty_in_cycle: Option, +} + +impl<'tcx> QueryStackFrame> { + #[inline] + pub fn new( + info: QueryStackDeferred<'tcx>, + dep_kind: DepKind, + hash: Hash64, + def_id: Option, + def_id_for_ty_in_cycle: Option, + ) -> Self { + Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } + } + + pub fn lift(&self) -> QueryStackFrame { + QueryStackFrame { + info: self.info.extract(), + dep_kind: self.dep_kind, + hash: self.hash, + def_id: self.def_id, + def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle, + } + } +} + +#[derive(Clone, Debug)] +pub struct QueryStackFrameExtra { + pub description: String, + pub span: Option, + pub def_kind: Option, +} + +impl QueryStackFrameExtra { + #[inline] + pub fn new(description: String, span: Option, def_kind: Option) -> Self { + Self { description, span, def_kind } + } + + // FIXME(eddyb) Get more valid `Span`s on queries. + #[inline] + pub fn default_span(&self, span: Span) -> Span { + if !span.is_dummy() { + return span; + } + self.span.unwrap_or(span) + } +} + +/// Track a 'side effect' for a particular query. +/// This is used to hold a closure which can create `QueryStackFrameExtra`. +#[derive(Clone)] +pub struct QueryStackDeferred<'tcx> { + _dummy: PhantomData<&'tcx ()>, + + // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't + // access it in the destructor. + extract: Arc QueryStackFrameExtra + DynSync + DynSend>, +} + +impl<'tcx> QueryStackDeferred<'tcx> { + pub fn new( + context: C, + extract: fn(C) -> QueryStackFrameExtra, + ) -> Self { + let extract: Arc QueryStackFrameExtra + DynSync + DynSend + 'tcx> = + Arc::new(move || extract(context)); + // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only + // captured variable is `context` which is Copy and cannot have a destructor. + Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } } + } + + pub fn extract(&self) -> QueryStackFrameExtra { + (self.extract)() + } +} + +impl<'tcx> Debug for QueryStackDeferred<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("QueryStackDeferred") + } +} diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_middle/src/traits/cache.rs similarity index 54% rename from compiler/rustc_query_system/src/cache.rs rename to compiler/rustc_middle/src/traits/cache.rs index 1b8332ad9e01..9391764bf1ce 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_middle/src/traits/cache.rs @@ -5,33 +5,27 @@ use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; -use crate::dep_graph::{DepContext, DepNodeIndex}; +use crate::dep_graph::DepNodeIndex; +use crate::ty::TyCtxt; -pub struct Cache { +pub struct WithDepNodeCache { hashmap: Lock>>, } -impl Clone for Cache { +impl Clone for WithDepNodeCache { fn clone(&self) -> Self { Self { hashmap: Lock::new(self.hashmap.borrow().clone()) } } } -impl Default for Cache { +impl Default for WithDepNodeCache { fn default() -> Self { Self { hashmap: Default::default() } } } -impl Cache { - /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear` - pub fn clear(&self) { - *self.hashmap.borrow_mut() = Default::default(); - } -} - -impl Cache { - pub fn get(&self, key: &Key, tcx: Tcx) -> Option { +impl WithDepNodeCache { + pub fn get<'tcx>(&self, key: &Key, tcx: TyCtxt<'tcx>) -> Option { Some(self.hashmap.borrow().get(key)?.get(tcx)) } @@ -47,12 +41,12 @@ pub struct WithDepNode { } impl WithDepNode { - pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self { + pub(crate) fn new(dep_node: DepNodeIndex, cached_value: T) -> Self { WithDepNode { dep_node, cached_value } } - pub fn get(&self, tcx: Tcx) -> T { - tcx.dep_graph().read_index(self.dep_node); + pub(crate) fn get<'tcx>(&self, tcx: TyCtxt<'tcx>) -> T { + tcx.dep_graph.read_index(self.dep_node); self.cached_value.clone() } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3a1682614cbf..2fca85c9f2f1 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -2,6 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html +pub mod cache; pub mod query; pub mod select; pub mod solve; @@ -844,7 +845,7 @@ impl DynCompatibilityViolation { format!("it contains generic associated const `{name}`").into() } Self::AssocConst(name, AssocConstViolation::NonType, _) => { - format!("it contains associated const `{name}` that's not marked `#[type_const]`") + format!("it contains associated const `{name}` that's not defined as `type const`") .into() } Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!( @@ -998,7 +999,7 @@ pub enum AssocConstViolation { /// Has own generic parameters (GAC). Generic, - /// Isn't marked `#[type_const]`. + /// Isn't defined as `type const`. NonType, /// Its type mentions the `Self` type parameter. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 3861efd36428..3a32029c60bd 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -5,17 +5,20 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TypeVisitable}; -use rustc_query_system::cache::Cache; use rustc_type_ir::solve::AliasBoundKind; use self::EvaluationResult::*; use super::{SelectionError, SelectionResult}; +use crate::traits::cache::WithDepNodeCache; use crate::ty; -pub type SelectionCache<'tcx, ENV> = - Cache<(ENV, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>; +pub type SelectionCache<'tcx, ENV> = WithDepNodeCache< + (ENV, ty::TraitPredicate<'tcx>), + SelectionResult<'tcx, SelectionCandidate<'tcx>>, +>; -pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>; +pub type EvaluationCache<'tcx, ENV> = + WithDepNodeCache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 05c19db4caa8..84415a592a2e 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,8 +1,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{DefId, DefIdMap}; +use rustc_hir::find_attr; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_span::sym; use crate::error::StrictCoherenceNeedsNegativeCoherence; use crate::ty::fast_reject::SimplifiedType; @@ -61,23 +62,15 @@ pub enum OverlapMode { impl OverlapMode { pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode { let with_negative_coherence = tcx.features().with_negative_coherence(); - let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence); + let strict_coherence = find_attr!(tcx.get_all_attrs(trait_id), AttributeKind::RustcStrictCoherence(span) => *span); if with_negative_coherence { - if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative } + if strict_coherence.is_some() { OverlapMode::Strict } else { OverlapMode::WithNegative } } else { - if strict_coherence { - let attr_span = trait_id - .as_local() - .into_iter() - .flat_map(|local_def_id| { - tcx.hir_attrs(tcx.local_def_id_to_hir_id(local_def_id)) - }) - .find(|attr| attr.has_name(sym::rustc_strict_coherence)) - .map(|attr| attr.span()); + if let Some(span) = strict_coherence { tcx.dcx().emit_err(StrictCoherenceNeedsNegativeCoherence { span: tcx.def_span(trait_id), - attr_span, + attr_span: span, }); } OverlapMode::Stable diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index c806366b518a..6d546aede4cf 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -97,7 +97,7 @@ pub enum Adjust { NeverToAny, /// Dereference once, producing a place. - Deref(Option), + Deref(DerefAdjustKind), /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow), @@ -108,6 +108,12 @@ pub enum Adjust { ReborrowPin(hir::Mutability), } +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +pub enum DerefAdjustKind { + Builtin, + Overloaded(OverloadedDeref), +} + /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)` /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`. /// The target type is `U` in both cases, with the region and mutability diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 75b1317e022b..4856df3a6222 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -427,11 +427,11 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_bound_variable_kinds_from_iter( - (0..len).map::(|_| Decodable::decode(decoder)), + (0..len).map::, _>(|_| Decodable::decode(decoder)), ) } } @@ -495,7 +495,7 @@ impl_decodable_via_ref! { &'tcx ty::List>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, - &'tcx ty::List, + &'tcx ty::List>, &'tcx ty::List>, &'tcx ty::ListWithCachedTypeInfo>, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index da3caf0bb210..aade274bfc98 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::HashStable; use rustc_type_ir::walk::TypeWalker; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; @@ -11,10 +11,12 @@ use crate::ty::{self, Ty, TyCtxt}; mod int; mod kind; +mod lit; mod valtree; pub use int::*; pub use kind::*; +pub use lit::*; use rustc_span::{DUMMY_SP, ErrorGuaranteed}; pub use valtree::*; @@ -94,7 +96,7 @@ impl<'tcx> Const<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst, + bound_const: ty::BoundConst<'tcx>, ) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)) } @@ -103,7 +105,7 @@ impl<'tcx> Const<'tcx> { pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> { Const::new( tcx, - ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst { var }), + ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)), ) } @@ -183,13 +185,13 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn new_bound( interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst, + bound_const: ty::BoundConst<'tcx>, ) -> Self { Const::new_bound(interner, debruijn, bound_const) } fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Const::new_bound(tcx, debruijn, ty::BoundConst { var }) + Const::new_bound(tcx, debruijn, ty::BoundConst::new(var)) } fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self { @@ -335,16 +337,3 @@ impl<'tcx> Const<'tcx> { TypeWalker::new(self.into()) } } - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum AnonConstKind { - /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope - GCE, - /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - MCG, - /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters - /// but must not depend on the actual instantiation. See #76200 for more information - RepeatExprCount, - /// anon consts outside of the type system, e.g. enum discriminants - NonTypeSystem, -} diff --git a/compiler/rustc_middle/src/ty/consts/lit.rs b/compiler/rustc_middle/src/ty/consts/lit.rs new file mode 100644 index 000000000000..3d41925131b4 --- /dev/null +++ b/compiler/rustc_middle/src/ty/consts/lit.rs @@ -0,0 +1,55 @@ +use rustc_ast::LitKind; +use rustc_hir; +use rustc_macros::HashStable; + +use crate::ty::{self, Ty, TyCtxt}; + +/// Input argument for `tcx.lit_to_const`. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)] +pub struct LitToConstInput<'tcx> { + /// The absolute value of the resultant constant. + pub lit: LitKind, + /// The type of the constant. + pub ty: Ty<'tcx>, + /// If the constant is negative. + pub neg: bool, +} + +/// Checks whether a literal can be interpreted as a const of the given type. +pub fn const_lit_matches_ty<'tcx>( + tcx: TyCtxt<'tcx>, + kind: &LitKind, + ty: Ty<'tcx>, + neg: bool, +) -> bool { + match (*kind, ty.kind()) { + (LitKind::Str(..), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => true, + (LitKind::Str(..), ty::Str) if tcx.features().deref_patterns() => true, + (LitKind::ByteStr(..), ty::Ref(_, inner_ty, _)) + if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind() + && matches!(ty.kind(), ty::Uint(ty::UintTy::U8)) => + { + true + } + (LitKind::ByteStr(..), ty::Slice(inner_ty) | ty::Array(inner_ty, _)) + if tcx.features().deref_patterns() + && matches!(inner_ty.kind(), ty::Uint(ty::UintTy::U8)) => + { + true + } + (LitKind::Byte(..), ty::Uint(ty::UintTy::U8)) => true, + (LitKind::CStr(..), ty::Ref(_, inner_ty, _)) + if matches!(inner_ty.kind(), ty::Adt(def, _) + if tcx.is_lang_item(def.did(), rustc_hir::LangItem::CStr)) => + { + true + } + (LitKind::Int(..), ty::Uint(_)) if !neg => true, + (LitKind::Int(..), ty::Int(_)) => true, + (LitKind::Bool(..), ty::Bool) => true, + (LitKind::Float(..), ty::Float(_)) => true, + (LitKind::Char(..), ty::Char) => true, + (LitKind::Err(..), _) => true, + _ => false, + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f015d0edc56c..430890d5a42d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2,6 +2,7 @@ #![allow(rustc::usage_of_ty_tykind)] +mod impl_interner; pub mod tls; use std::borrow::{Borrow, Cow}; @@ -16,6 +17,7 @@ use std::{fmt, iter, mem}; use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx}; use rustc_ast as ast; +use rustc_data_structures::defer; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; @@ -27,12 +29,9 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{ self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal, }; -use rustc_data_structures::{debug_assert_matches, defer}; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan, -}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, LintDiagnostic, MultiSpan}; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::{CtorKind, CtorOf, DefKind}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; @@ -40,8 +39,6 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::limit::Limit; use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr}; use rustc_index::IndexVec; -use rustc_query_system::cache::WithDepNode; -use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::Session; @@ -51,16 +48,14 @@ use rustc_session::lint::Lint; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; pub use rustc_type_ir::lift::Lift; -use rustc_type_ir::{ - CollectAndApply, Interner, TypeFlags, TypeFoldable, WithCachedTypeInfo, elaborate, search_graph, -}; +use rustc_type_ir::{CollectAndApply, TypeFlags, WithCachedTypeInfo, elaborate, search_graph}; use tracing::{debug, instrument}; use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKindVTable}; -use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, CanonicalVarKinds}; +use crate::dep_graph::dep_node::make_metadata; +use crate::dep_graph::{DepGraph, DepKindVTable, DepNodeIndex}; +use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind}; use crate::lint::lint_level; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; @@ -71,794 +66,16 @@ use crate::query::plumbing::QuerySystem; use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt}; use crate::thir::Thir; use crate::traits; -use crate::traits::solve::{ - self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, - QueryResult, inspect, -}; +use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData, PredefinedOpaques}; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs, - GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy, - Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, - PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, - ValTree, ValTreeKind, Visibility, + GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, Pattern, + PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, ValTree, ValTreeKind, + Visibility, }; -#[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Interner for TyCtxt<'tcx> { - fn next_trait_solver_globally(self) -> bool { - self.next_trait_solver_globally() - } - - type DefId = DefId; - type LocalDefId = LocalDefId; - type TraitId = DefId; - type ForeignId = DefId; - type FunctionId = DefId; - type ClosureId = DefId; - type CoroutineClosureId = DefId; - type CoroutineId = DefId; - type AdtId = DefId; - type ImplId = DefId; - type UnevaluatedConstId = DefId; - type Span = Span; - - type GenericArgs = ty::GenericArgsRef<'tcx>; - - type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; - type GenericArg = ty::GenericArg<'tcx>; - type Term = ty::Term<'tcx>; - type BoundVarKinds = &'tcx List; - - type BoundVarKind = ty::BoundVariableKind; - type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; - - fn mk_predefined_opaques_in_body( - self, - data: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], - ) -> Self::PredefinedOpaques { - self.mk_predefined_opaques_in_body(data) - } - type LocalDefIds = &'tcx ty::List; - type CanonicalVarKinds = CanonicalVarKinds<'tcx>; - fn mk_canonical_var_kinds( - self, - kinds: &[ty::CanonicalVarKind], - ) -> Self::CanonicalVarKinds { - self.mk_canonical_var_kinds(kinds) - } - - type ExternalConstraints = ExternalConstraints<'tcx>; - fn mk_external_constraints( - self, - data: ExternalConstraintsData, - ) -> ExternalConstraints<'tcx> { - self.mk_external_constraints(data) - } - type DepNodeIndex = DepNodeIndex; - fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { - self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) - } - type Ty = Ty<'tcx>; - type Tys = &'tcx List>; - - type FnInputTys = &'tcx [Ty<'tcx>]; - type ParamTy = ParamTy; - type BoundTy = ty::BoundTy; - type Symbol = Symbol; - - type PlaceholderTy = ty::PlaceholderType<'tcx>; - type ErrorGuaranteed = ErrorGuaranteed; - type BoundExistentialPredicates = &'tcx List>; - - type AllocId = crate::mir::interpret::AllocId; - type Pat = Pattern<'tcx>; - type PatList = &'tcx List>; - type Safety = hir::Safety; - type Abi = ExternAbi; - type Const = ty::Const<'tcx>; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; - - type ParamConst = ty::ParamConst; - type BoundConst = ty::BoundConst; - type ValueConst = ty::Value<'tcx>; - type ExprConst = ty::Expr<'tcx>; - type ValTree = ty::ValTree<'tcx>; - type ScalarInt = ty::ScalarInt; - - type Region = Region<'tcx>; - type EarlyParamRegion = ty::EarlyParamRegion; - type LateParamRegion = ty::LateParamRegion; - type BoundRegion = ty::BoundRegion; - type PlaceholderRegion = ty::PlaceholderRegion<'tcx>; - - type RegionAssumptions = &'tcx ty::List>; - - type ParamEnv = ty::ParamEnv<'tcx>; - type Predicate = Predicate<'tcx>; - - type Clause = Clause<'tcx>; - type Clauses = ty::Clauses<'tcx>; - - type Tracked = WithDepNode; - fn mk_tracked( - self, - data: T, - dep_node: DepNodeIndex, - ) -> Self::Tracked { - WithDepNode::new(dep_node, data) - } - fn get_tracked(self, tracked: &Self::Tracked) -> T { - tracked.get(self) - } - - fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { - f(&mut *self.new_solver_evaluation_cache.lock()) - } - - fn canonical_param_env_cache_get_or_insert( - self, - param_env: ty::ParamEnv<'tcx>, - f: impl FnOnce() -> ty::CanonicalParamEnvCacheEntry, - from_entry: impl FnOnce(&ty::CanonicalParamEnvCacheEntry) -> R, - ) -> R { - let mut cache = self.new_solver_canonical_param_env_cache.lock(); - let entry = cache.entry(param_env).or_insert_with(f); - from_entry(entry) - } - - fn assert_evaluation_is_concurrent(&self) { - // Turns out, the assumption for this function isn't perfect. - // See trait-system-refactor-initiative#234. - } - - fn expand_abstract_consts>>(self, t: T) -> T { - self.expand_abstract_consts(t) - } - - type GenericsOf = &'tcx ty::Generics; - - fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { - self.generics_of(def_id) - } - - type VariancesOf = &'tcx [ty::Variance]; - - fn variances_of(self, def_id: DefId) -> Self::VariancesOf { - self.variances_of(def_id) - } - - fn opt_alias_variances( - self, - kind: impl Into, - def_id: DefId, - ) -> Option<&'tcx [ty::Variance]> { - self.opt_alias_variances(kind, def_id) - } - - fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - self.type_of(def_id) - } - fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - self.type_of_opaque_hir_typeck(def_id) - } - fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - self.const_of_item(def_id) - } - - type AdtDef = ty::AdtDef<'tcx>; - fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { - self.adt_def(adt_def_id) - } - - fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { - match self.def_kind(alias.def_id) { - DefKind::AssocTy => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::Inherent - } else { - ty::Projection - } - } - DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias => ty::Free, - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - - fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind { - match self.def_kind(alias.def_id) { - DefKind::AssocTy => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::AliasTermKind::InherentTy - } else { - ty::AliasTermKind::ProjectionTy - } - } - DefKind::AssocConst => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::AliasTermKind::InherentConst - } else { - ty::AliasTermKind::ProjectionConst - } - } - DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, - DefKind::TyAlias => ty::AliasTermKind::FreeTy, - DefKind::Const => ty::AliasTermKind::FreeConst, - DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { - ty::AliasTermKind::UnevaluatedConst - } - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - - fn trait_ref_and_own_args_for_alias( - self, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); - let trait_def_id = self.parent(def_id); - debug_assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); - let trait_ref = ty::TraitRef::from_assoc(self, trait_def_id, args); - (trait_ref, &args[trait_ref.args.len()..]) - } - - fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> { - self.mk_args(args) - } - - fn mk_args_from_iter(self, args: I) -> T::Output - where - I: Iterator, - T: CollectAndApply>, - { - self.mk_args_from_iter(args) - } - - fn check_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> bool { - self.check_args_compatible(def_id, args) - } - - fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) { - self.debug_assert_args_compatible(def_id, args); - } - - /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` - /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on - /// a dummy self type and forward to `debug_assert_args_compatible`. - fn debug_assert_existential_args_compatible( - self, - def_id: Self::DefId, - args: Self::GenericArgs, - ) { - // FIXME: We could perhaps add a `skip: usize` to `debug_assert_args_compatible` - // to avoid needing to reintern the set of args... - if cfg!(debug_assertions) { - self.debug_assert_args_compatible( - def_id, - self.mk_args_from_iter( - [self.types.trait_object_dummy_self.into()].into_iter().chain(args.iter()), - ), - ); - } - } - - fn mk_type_list_from_iter(self, args: I) -> T::Output - where - I: Iterator, - T: CollectAndApply, &'tcx List>>, - { - self.mk_type_list_from_iter(args) - } - - fn parent(self, def_id: DefId) -> DefId { - self.parent(def_id) - } - - fn recursion_limit(self) -> usize { - self.recursion_limit().0 - } - - type Features = &'tcx rustc_feature::Features; - - fn features(self) -> Self::Features { - self.features() - } - - fn coroutine_hidden_types( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { - self.coroutine_hidden_types(def_id) - } - - fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { - self.fn_sig(def_id) - } - - fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability { - self.coroutine_movability(def_id) - } - - fn coroutine_for_closure(self, def_id: DefId) -> DefId { - self.coroutine_for_closure(def_id) - } - - fn generics_require_sized_self(self, def_id: DefId) -> bool { - self.generics_require_sized_self(def_id) - } - - fn item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn item_self_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_self_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn item_non_self_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_non_self_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( - self.predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), - ) - } - - fn own_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( - self.predicates_of(def_id).instantiate_own_identity().map(|(clause, _)| clause), - ) - } - - fn explicit_super_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { - self.explicit_super_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) - } - - fn explicit_implied_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { - self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) - } - - fn impl_super_outlives( - self, - impl_def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.impl_super_outlives(impl_def_id) - } - - fn impl_is_const(self, def_id: DefId) -> bool { - debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); - self.is_conditionally_const(def_id) - } - - fn fn_is_const(self, def_id: DefId) -> bool { - debug_assert_matches!( - self.def_kind(def_id), - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) - ); - self.is_conditionally_const(def_id) - } - - fn alias_has_const_conditions(self, def_id: DefId) -> bool { - debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); - self.is_conditionally_const(def_id) - } - - fn const_conditions( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( - self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c), - ) - } - - fn explicit_implied_const_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( - self.explicit_implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), - ) - } - - fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool { - self.impl_self_is_guaranteed_unsized(impl_def_id) - } - - fn has_target_features(self, def_id: DefId) -> bool { - !self.codegen_fn_attrs(def_id).target_features.is_empty() - } - - fn require_lang_item(self, lang_item: SolverLangItem) -> DefId { - self.require_lang_item(solver_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> DefId { - self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> DefId { - self.require_lang_item(solver_adt_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool { - self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) - } - - fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool { - self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) - } - - fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool { - self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item)) - } - - fn is_default_trait(self, def_id: DefId) -> bool { - self.is_default_trait(def_id) - } - - fn is_sizedness_trait(self, def_id: DefId) -> bool { - self.is_sizedness_trait(def_id) - } - - fn as_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn as_trait_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn as_adt_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_adt_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { - self.associated_items(def_id) - .in_definition_order() - .filter(|assoc_item| assoc_item.is_type()) - .map(|assoc_item| assoc_item.def_id) - } - - // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`, - // since we want to skip over blanket impls for non-rigid aliases, and also we - // only want to consider types that *actually* unify with float/int vars. - fn for_each_relevant_impl( - self, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - mut f: impl FnMut(DefId), - ) { - let tcx = self; - let trait_impls = tcx.trait_impls_of(trait_def_id); - let mut consider_impls_for_simplified_type = |simp| { - if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { - for &impl_def_id in impls_for_type { - f(impl_def_id); - } - } - }; - - match self_ty.kind() { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::Dynamic(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(_, _) - | ty::Never - | ty::Tuple(_) - | ty::UnsafeBinder(_) => { - if let Some(simp) = ty::fast_reject::simplify_type( - tcx, - self_ty, - ty::fast_reject::TreatParams::AsRigid, - ) { - consider_impls_for_simplified_type(simp); - } - } - - // HACK: For integer and float variables we have to manually look at all impls - // which have some integer or float as a self type. - ty::Infer(ty::IntVar(_)) => { - use ty::IntTy::*; - use ty::UintTy::*; - // This causes a compiler error if any new integer kinds are added. - let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; - let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; - let possible_integers = [ - // signed integers - ty::SimplifiedType::Int(I8), - ty::SimplifiedType::Int(I16), - ty::SimplifiedType::Int(I32), - ty::SimplifiedType::Int(I64), - ty::SimplifiedType::Int(I128), - ty::SimplifiedType::Int(Isize), - // unsigned integers - ty::SimplifiedType::Uint(U8), - ty::SimplifiedType::Uint(U16), - ty::SimplifiedType::Uint(U32), - ty::SimplifiedType::Uint(U64), - ty::SimplifiedType::Uint(U128), - ty::SimplifiedType::Uint(Usize), - ]; - for simp in possible_integers { - consider_impls_for_simplified_type(simp); - } - } - - ty::Infer(ty::FloatVar(_)) => { - // This causes a compiler error if any new float kinds are added. - let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); - let possible_floats = [ - ty::SimplifiedType::Float(ty::FloatTy::F16), - ty::SimplifiedType::Float(ty::FloatTy::F32), - ty::SimplifiedType::Float(ty::FloatTy::F64), - ty::SimplifiedType::Float(ty::FloatTy::F128), - ]; - - for simp in possible_floats { - consider_impls_for_simplified_type(simp); - } - } - - // The only traits applying to aliases and placeholders are blanket impls. - // - // Impls which apply to an alias after normalization are handled by - // `assemble_candidates_after_normalizing_self_ty`. - ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), - - // FIXME: These should ideally not exist as a self type. It would be nice for - // the builtin auto trait impls of coroutines to instead directly recurse - // into the witness. - ty::CoroutineWitness(..) => (), - - // These variants should not exist as a self type. - ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Param(_) - | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), - } - - #[allow(rustc::usage_of_type_ir_traits)] - self.for_each_blanket_impl(trait_def_id, f) - } - fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) { - let trait_impls = self.trait_impls_of(trait_def_id); - for &impl_def_id in trait_impls.blanket_impls() { - f(impl_def_id); - } - } - - fn has_item_definition(self, def_id: DefId) -> bool { - self.defaultness(def_id).has_value() - } - - fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool { - self.specializes((impl_def_id, victim_def_id)) - } - - fn impl_is_default(self, impl_def_id: DefId) -> bool { - self.defaultness(impl_def_id).is_default() - } - - fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { - self.impl_trait_ref(impl_def_id) - } - - fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { - self.impl_polarity(impl_def_id) - } - - fn trait_is_auto(self, trait_def_id: DefId) -> bool { - self.trait_is_auto(trait_def_id) - } - - fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { - self.trait_is_coinductive(trait_def_id) - } - - fn trait_is_alias(self, trait_def_id: DefId) -> bool { - self.trait_is_alias(trait_def_id) - } - - fn trait_is_dyn_compatible(self, trait_def_id: DefId) -> bool { - self.is_dyn_compatible(trait_def_id) - } - - fn trait_is_fundamental(self, def_id: DefId) -> bool { - self.trait_def(def_id).is_fundamental - } - - fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { - self.trait_def(trait_def_id).safety.is_unsafe() - } - - fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { - self.is_impl_trait_in_trait(def_id) - } - - fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { - self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) - } - - fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { - self.is_general_coroutine(coroutine_def_id) - } - - fn coroutine_is_async(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_async(coroutine_def_id) - } - - fn coroutine_is_gen(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_gen(coroutine_def_id) - } - - fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_async_gen(coroutine_def_id) - } - - type UnsizingParams = &'tcx rustc_index::bit_set::DenseBitSet; - fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams { - self.unsizing_params_for_adt(adt_def_id) - } - - fn anonymize_bound_vars>>( - self, - binder: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.anonymize_bound_vars(binder) - } - - fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds { - self.opaque_types_defined_by(defining_anchor) - } - - fn opaque_types_and_coroutines_defined_by( - self, - defining_anchor: Self::LocalDefId, - ) -> Self::LocalDefIds { - let coroutines_defined_by = self - .nested_bodies_within(defining_anchor) - .iter() - .filter(|def_id| self.is_coroutine(def_id.to_def_id())); - self.mk_local_def_ids_from_iter( - self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), - ) - } - - type Probe = &'tcx inspect::Probe>; - fn mk_probe(self, probe: inspect::Probe) -> &'tcx inspect::Probe> { - self.arena.alloc(probe) - } - fn evaluate_root_goal_for_proof_tree_raw( - self, - canonical_goal: CanonicalInput<'tcx>, - ) -> (QueryResult<'tcx>, &'tcx inspect::Probe>) { - self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) - } -} - -macro_rules! bidirectional_lang_item_map { - ( - $solver_ty:ident, $to_solver:ident, $from_solver:ident; - $($name:ident),+ $(,)? - ) => { - fn $from_solver(lang_item: $solver_ty) -> LangItem { - match lang_item { - $($solver_ty::$name => LangItem::$name,)+ - } - } - - fn $to_solver(lang_item: LangItem) -> Option<$solver_ty> { - Some(match lang_item { - $(LangItem::$name => $solver_ty::$name,)+ - _ => return None, - }) - } - } -} - -bidirectional_lang_item_map! { - SolverLangItem, lang_item_to_solver_lang_item, solver_lang_item_to_lang_item; - -// tidy-alphabetical-start - AsyncFnKindUpvars, - AsyncFnOnceOutput, - CallOnceFuture, - CallRefFuture, - CoroutineReturn, - CoroutineYield, - DynMetadata, - FutureOutput, - Metadata, -// tidy-alphabetical-end -} - -bidirectional_lang_item_map! { - SolverAdtLangItem, lang_item_to_solver_adt_lang_item, solver_adt_lang_item_to_lang_item; - -// tidy-alphabetical-start - Option, - Poll, -// tidy-alphabetical-end -} - -bidirectional_lang_item_map! { - SolverTraitLangItem, lang_item_to_solver_trait_lang_item, solver_trait_lang_item_to_lang_item; - -// tidy-alphabetical-start - AsyncFn, - AsyncFnKindHelper, - AsyncFnMut, - AsyncFnOnce, - AsyncFnOnceOutput, - AsyncIterator, - BikeshedGuaranteedNoDrop, - Clone, - Copy, - Coroutine, - Destruct, - DiscriminantKind, - Drop, - Fn, - FnMut, - FnOnce, - FnPtrTrait, - FusedIterator, - Future, - Iterator, - MetaSized, - PointeeSized, - PointeeTrait, - Sized, - TransmuteTrait, - TrivialClone, - Tuple, - Unpin, - Unsize, -// tidy-alphabetical-end -} - impl<'tcx> rustc_type_ir::inherent::DefId> for DefId { fn is_local(self) -> bool { self.is_local() @@ -938,7 +155,7 @@ pub struct CtxtInterners<'tcx> { const_: InternedSet<'tcx, WithCachedTypeInfo>>, pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, - bound_variable_kinds: InternedSet<'tcx, List>, + bound_variable_kinds: InternedSet<'tcx, List>>, layout: InternedSet<'tcx, LayoutData>, adt_def: InternedSet<'tcx, AdtDefData>, external_constraints: InternedSet<'tcx, ExternalConstraintsData>>, @@ -1886,10 +1103,23 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } - /// Check if the given `def_id` is a const with the `#[type_const]` attribute. - pub fn is_type_const(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) - && find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(_)) + pub fn type_const_span(self, def_id: DefId) -> Option { + if !self.is_type_const(def_id) { + return None; + } + Some(self.def_span(def_id)) + } + + /// Check if the given `def_id` is a `type const` (mgca) + pub fn is_type_const>(self, def_id: I) -> bool { + // No need to call the query directly in this case always false. + if !(matches!( + self.def_kind(def_id.into_query_param()), + DefKind::Const | DefKind::AssocConst + )) { + return false; + } + self.is_rhs_type_const(def_id) } /// Returns the movability of the coroutine of `def_id`, or panics @@ -2530,7 +1760,7 @@ nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> } nop_list_lift! { poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx> } -nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind } +nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind<'a> => ty::BoundVariableKind<'tcx> } // This is the impl for `&'a GenericArgs<'a>`. nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> } @@ -2817,7 +2047,7 @@ slice_interners!( poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), projs: pub mk_projs(ProjectionKind), place_elems: pub mk_place_elems(PlaceElem<'tcx>), - bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), + bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind<'tcx>), fields: pub mk_fields(FieldIdx), local_def_ids: intern_local_def_ids(LocalDefId), captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>), @@ -2915,12 +2145,15 @@ impl<'tcx> TyCtxt<'tcx> { ) -> bool { let generics = self.generics_of(def_id); - // IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs - // (namely: opaques, i.e. ATPITs) do not. - let own_args = if !nested - && let DefKind::AssocTy = self.def_kind(def_id) - && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) - { + // IATs and IACs (inherent associated types/consts with `type const`) themselves have a + // weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e. + // ATPITs) do not. + let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy) + && matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false }); + let is_inherent_assoc_type_const = matches!(self.def_kind(def_id), DefKind::AssocConst) + && matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false }) + && self.is_type_const(def_id); + let own_args = if !nested && (is_inherent_assoc_ty || is_inherent_assoc_type_const) { if generics.own_params.len() + 1 != args.len() { return false; } @@ -2962,9 +2195,12 @@ impl<'tcx> TyCtxt<'tcx> { /// and print out the args if not. pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { if cfg!(debug_assertions) && !self.check_args_compatible(def_id, args) { - if let DefKind::AssocTy = self.def_kind(def_id) - && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) - { + let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy) + && matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false }); + let is_inherent_assoc_type_const = matches!(self.def_kind(def_id), DefKind::AssocConst) + && matches!(self.def_kind(self.parent(def_id)), DefKind::Impl { of_trait: false }) + && self.is_type_const(def_id); + if is_inherent_assoc_ty || is_inherent_assoc_type_const { bug!( "args not compatible with generics for {}: args={:#?}, generics={:#?}", self.def_path_str(def_id), @@ -3242,7 +2478,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: CollectAndApply>, + T: CollectAndApply, &'tcx List>>, { T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs)) } @@ -3362,7 +2598,7 @@ impl<'tcx> TyCtxt<'tcx> { self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id)) } - pub fn late_bound_vars(self, id: HirId) -> &'tcx List { + pub fn late_bound_vars(self, id: HirId) -> &'tcx List> { self.mk_bound_variable_kinds( &self .late_bound_vars_map(id.owner) @@ -3470,10 +2706,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intrinsic(self, def_id: impl IntoQueryParam + Copy) -> Option { match self.def_kind(def_id) { - DefKind::Fn | DefKind::AssocFn => {} - _ => return None, + DefKind::Fn | DefKind::AssocFn => self.intrinsic_raw(def_id), + _ => None, } - self.intrinsic_raw(def_id) } pub fn next_trait_solver_globally(self) -> bool { @@ -3516,7 +2751,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode { - crate::dep_graph::make_metadata(self) + make_metadata(self) } pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs new file mode 100644 index 000000000000..7580cc65d530 --- /dev/null +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -0,0 +1,806 @@ +//! Implementation of [`rustc_type_ir::Interner`] for [`TyCtxt`]. + +use std::fmt; + +use rustc_abi::ExternAbi; +use rustc_data_structures::debug_assert_matches; +use rustc_errors::ErrorGuaranteed; +use rustc_hir::def::{CtorKind, CtorOf, DefKind}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::lang_items::LangItem; +use rustc_hir::{self as hir}; +use rustc_span::{DUMMY_SP, Span, Symbol}; +use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, search_graph}; + +use crate::dep_graph::DepNodeIndex; +use crate::infer::canonical::CanonicalVarKinds; +use crate::query::IntoQueryParam; +use crate::traits::cache::WithDepNode; +use crate::traits::solve::{ + self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, QueryResult, inspect, +}; +use crate::ty::{ + self, Clause, Const, List, ParamTy, Pattern, PolyExistentialPredicate, Predicate, Region, Ty, + TyCtxt, +}; + +#[allow(rustc::usage_of_ty_tykind)] +impl<'tcx> Interner for TyCtxt<'tcx> { + fn next_trait_solver_globally(self) -> bool { + self.next_trait_solver_globally() + } + + type DefId = DefId; + type LocalDefId = LocalDefId; + type TraitId = DefId; + type ForeignId = DefId; + type FunctionId = DefId; + type ClosureId = DefId; + type CoroutineClosureId = DefId; + type CoroutineId = DefId; + type AdtId = DefId; + type ImplId = DefId; + type UnevaluatedConstId = DefId; + type Span = Span; + + type GenericArgs = ty::GenericArgsRef<'tcx>; + + type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; + type GenericArg = ty::GenericArg<'tcx>; + type Term = ty::Term<'tcx>; + type BoundVarKinds = &'tcx List>; + + type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; + + fn mk_predefined_opaques_in_body( + self, + data: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], + ) -> Self::PredefinedOpaques { + self.mk_predefined_opaques_in_body(data) + } + type LocalDefIds = &'tcx ty::List; + type CanonicalVarKinds = CanonicalVarKinds<'tcx>; + fn mk_canonical_var_kinds( + self, + kinds: &[ty::CanonicalVarKind], + ) -> Self::CanonicalVarKinds { + self.mk_canonical_var_kinds(kinds) + } + + type ExternalConstraints = ExternalConstraints<'tcx>; + fn mk_external_constraints( + self, + data: ExternalConstraintsData, + ) -> ExternalConstraints<'tcx> { + self.mk_external_constraints(data) + } + type DepNodeIndex = DepNodeIndex; + fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { + self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) + } + type Ty = Ty<'tcx>; + type Tys = &'tcx List>; + + type FnInputTys = &'tcx [Ty<'tcx>]; + type ParamTy = ParamTy; + type Symbol = Symbol; + + type ErrorGuaranteed = ErrorGuaranteed; + type BoundExistentialPredicates = &'tcx List>; + + type AllocId = crate::mir::interpret::AllocId; + type Pat = Pattern<'tcx>; + type PatList = &'tcx List>; + type Safety = hir::Safety; + type Abi = ExternAbi; + type Const = ty::Const<'tcx>; + + type ParamConst = ty::ParamConst; + type ValueConst = ty::Value<'tcx>; + type ExprConst = ty::Expr<'tcx>; + type ValTree = ty::ValTree<'tcx>; + type ScalarInt = ty::ScalarInt; + + type Region = Region<'tcx>; + type EarlyParamRegion = ty::EarlyParamRegion; + type LateParamRegion = ty::LateParamRegion; + + type RegionAssumptions = &'tcx ty::List>; + + type ParamEnv = ty::ParamEnv<'tcx>; + type Predicate = Predicate<'tcx>; + + type Clause = Clause<'tcx>; + type Clauses = ty::Clauses<'tcx>; + + type Tracked = WithDepNode; + fn mk_tracked( + self, + data: T, + dep_node: DepNodeIndex, + ) -> Self::Tracked { + WithDepNode::new(dep_node, data) + } + fn get_tracked(self, tracked: &Self::Tracked) -> T { + tracked.get(self) + } + + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { + f(&mut *self.new_solver_evaluation_cache.lock()) + } + + fn canonical_param_env_cache_get_or_insert( + self, + param_env: ty::ParamEnv<'tcx>, + f: impl FnOnce() -> ty::CanonicalParamEnvCacheEntry, + from_entry: impl FnOnce(&ty::CanonicalParamEnvCacheEntry) -> R, + ) -> R { + let mut cache = self.new_solver_canonical_param_env_cache.lock(); + let entry = cache.entry(param_env).or_insert_with(f); + from_entry(entry) + } + + fn assert_evaluation_is_concurrent(&self) { + // Turns out, the assumption for this function isn't perfect. + // See trait-system-refactor-initiative#234. + } + + fn expand_abstract_consts>>(self, t: T) -> T { + self.expand_abstract_consts(t) + } + + type GenericsOf = &'tcx ty::Generics; + + fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { + self.generics_of(def_id) + } + + type VariancesOf = &'tcx [ty::Variance]; + + fn variances_of(self, def_id: DefId) -> Self::VariancesOf { + self.variances_of(def_id) + } + + fn opt_alias_variances( + self, + kind: impl Into, + def_id: DefId, + ) -> Option<&'tcx [ty::Variance]> { + self.opt_alias_variances(kind, def_id) + } + + fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of(def_id) + } + fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of_opaque_hir_typeck(def_id) + } + fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { + self.const_of_item(def_id) + } + fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { + self.anon_const_kind(def_id) + } + + type AdtDef = ty::AdtDef<'tcx>; + fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { + self.adt_def(adt_def_id) + } + + fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::Inherent + } else { + ty::Projection + } + } + DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Free, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentTy + } else { + ty::AliasTermKind::ProjectionTy + } + } + DefKind::AssocConst => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentConst + } else { + ty::AliasTermKind::ProjectionConst + } + } + DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, + DefKind::TyAlias => ty::AliasTermKind::FreeTy, + DefKind::Const => ty::AliasTermKind::FreeConst, + DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { + ty::AliasTermKind::UnevaluatedConst + } + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn trait_ref_and_own_args_for_alias( + self, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { + debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); + let trait_def_id = self.parent(def_id); + debug_assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); + let trait_ref = ty::TraitRef::from_assoc(self, trait_def_id, args); + (trait_ref, &args[trait_ref.args.len()..]) + } + + fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> { + self.mk_args(args) + } + + fn mk_args_from_iter(self, args: I) -> T::Output + where + I: Iterator, + T: CollectAndApply>, + { + self.mk_args_from_iter(args) + } + + fn check_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> bool { + self.check_args_compatible(def_id, args) + } + + fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) { + self.debug_assert_args_compatible(def_id, args); + } + + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` + /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on + /// a dummy self type and forward to `debug_assert_args_compatible`. + fn debug_assert_existential_args_compatible( + self, + def_id: Self::DefId, + args: Self::GenericArgs, + ) { + // FIXME: We could perhaps add a `skip: usize` to `debug_assert_args_compatible` + // to avoid needing to reintern the set of args... + if cfg!(debug_assertions) { + self.debug_assert_args_compatible( + def_id, + self.mk_args_from_iter( + [self.types.trait_object_dummy_self.into()].into_iter().chain(args.iter()), + ), + ); + } + } + + fn mk_type_list_from_iter(self, args: I) -> T::Output + where + I: Iterator, + T: CollectAndApply, &'tcx List>>, + { + self.mk_type_list_from_iter(args) + } + + fn parent(self, def_id: DefId) -> DefId { + self.parent(def_id) + } + + fn recursion_limit(self) -> usize { + self.recursion_limit().0 + } + + type Features = &'tcx rustc_feature::Features; + + fn features(self) -> Self::Features { + self.features() + } + + fn coroutine_hidden_types( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + self.coroutine_hidden_types(def_id) + } + + fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + self.fn_sig(def_id) + } + + fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability { + self.coroutine_movability(def_id) + } + + fn coroutine_for_closure(self, def_id: DefId) -> DefId { + self.coroutine_for_closure(def_id) + } + + fn generics_require_sized_self(self, def_id: DefId) -> bool { + self.generics_require_sized_self(def_id) + } + + fn item_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn item_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_self_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn item_non_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_non_self_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), + ) + } + + fn own_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_own_identity().map(|(clause, _)| clause), + ) + } + + fn explicit_super_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { + self.explicit_super_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) + } + + fn explicit_implied_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { + self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) + } + + fn impl_super_outlives( + self, + impl_def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.impl_super_outlives(impl_def_id) + } + + fn impl_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); + self.is_conditionally_const(def_id) + } + + fn fn_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) + ); + self.is_conditionally_const(def_id) + } + + fn alias_has_const_conditions(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); + self.is_conditionally_const(def_id) + } + + fn const_conditions( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { + ty::EarlyBinder::bind( + self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c), + ) + } + + fn explicit_implied_const_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { + ty::EarlyBinder::bind( + self.explicit_implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), + ) + } + + fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool { + self.impl_self_is_guaranteed_unsized(impl_def_id) + } + + fn has_target_features(self, def_id: DefId) -> bool { + !self.codegen_fn_attrs(def_id).target_features.is_empty() + } + + fn require_lang_item(self, lang_item: SolverLangItem) -> DefId { + self.require_lang_item(solver_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> DefId { + self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> DefId { + self.require_lang_item(solver_adt_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool { + self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) + } + + fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool { + self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) + } + + fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool { + self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item)) + } + + fn is_default_trait(self, def_id: DefId) -> bool { + self.is_default_trait(def_id) + } + + fn is_sizedness_trait(self, def_id: DefId) -> bool { + self.is_sizedness_trait(def_id) + } + + fn as_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn as_trait_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn as_adt_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_adt_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { + self.associated_items(def_id) + .in_definition_order() + .filter(|assoc_item| assoc_item.is_type()) + .map(|assoc_item| assoc_item.def_id) + } + + // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`, + // since we want to skip over blanket impls for non-rigid aliases, and also we + // only want to consider types that *actually* unify with float/int vars. + fn for_each_relevant_impl( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + mut f: impl FnMut(DefId), + ) { + let tcx = self; + let trait_impls = tcx.trait_impls_of(trait_def_id); + let mut consider_impls_for_simplified_type = |simp| { + if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { + for &impl_def_id in impls_for_type { + f(impl_def_id); + } + } + }; + + match self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::Dynamic(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Never + | ty::Tuple(_) + | ty::UnsafeBinder(_) => { + if let Some(simp) = ty::fast_reject::simplify_type( + tcx, + self_ty, + ty::fast_reject::TreatParams::AsRigid, + ) { + consider_impls_for_simplified_type(simp); + } + } + + // HACK: For integer and float variables we have to manually look at all impls + // which have some integer or float as a self type. + ty::Infer(ty::IntVar(_)) => { + use ty::IntTy::*; + use ty::UintTy::*; + // This causes a compiler error if any new integer kinds are added. + let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; + let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; + let possible_integers = [ + // signed integers + ty::SimplifiedType::Int(I8), + ty::SimplifiedType::Int(I16), + ty::SimplifiedType::Int(I32), + ty::SimplifiedType::Int(I64), + ty::SimplifiedType::Int(I128), + ty::SimplifiedType::Int(Isize), + // unsigned integers + ty::SimplifiedType::Uint(U8), + ty::SimplifiedType::Uint(U16), + ty::SimplifiedType::Uint(U32), + ty::SimplifiedType::Uint(U64), + ty::SimplifiedType::Uint(U128), + ty::SimplifiedType::Uint(Usize), + ]; + for simp in possible_integers { + consider_impls_for_simplified_type(simp); + } + } + + ty::Infer(ty::FloatVar(_)) => { + // This causes a compiler error if any new float kinds are added. + let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); + let possible_floats = [ + ty::SimplifiedType::Float(ty::FloatTy::F16), + ty::SimplifiedType::Float(ty::FloatTy::F32), + ty::SimplifiedType::Float(ty::FloatTy::F64), + ty::SimplifiedType::Float(ty::FloatTy::F128), + ]; + + for simp in possible_floats { + consider_impls_for_simplified_type(simp); + } + } + + // The only traits applying to aliases and placeholders are blanket impls. + // + // Impls which apply to an alias after normalization are handled by + // `assemble_candidates_after_normalizing_self_ty`. + ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), + + // FIXME: These should ideally not exist as a self type. It would be nice for + // the builtin auto trait impls of coroutines to instead directly recurse + // into the witness. + ty::CoroutineWitness(..) => (), + + // These variants should not exist as a self type. + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Param(_) + | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), + } + + #[allow(rustc::usage_of_type_ir_traits)] + self.for_each_blanket_impl(trait_def_id, f) + } + fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) { + let trait_impls = self.trait_impls_of(trait_def_id); + for &impl_def_id in trait_impls.blanket_impls() { + f(impl_def_id); + } + } + + fn has_item_definition(self, def_id: DefId) -> bool { + self.defaultness(def_id).has_value() + } + + fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool { + self.specializes((impl_def_id, victim_def_id)) + } + + fn impl_is_default(self, impl_def_id: DefId) -> bool { + self.defaultness(impl_def_id).is_default() + } + + fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { + self.impl_trait_ref(impl_def_id) + } + + fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { + self.impl_polarity(impl_def_id) + } + + fn trait_is_auto(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) + } + + fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_coinductive(trait_def_id) + } + + fn trait_is_alias(self, trait_def_id: DefId) -> bool { + self.trait_is_alias(trait_def_id) + } + + fn trait_is_dyn_compatible(self, trait_def_id: DefId) -> bool { + self.is_dyn_compatible(trait_def_id) + } + + fn trait_is_fundamental(self, def_id: DefId) -> bool { + self.trait_def(def_id).is_fundamental + } + + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { + self.trait_def(trait_def_id).safety.is_unsafe() + } + + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { + self.is_impl_trait_in_trait(def_id) + } + + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) + } + + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { + self.is_general_coroutine(coroutine_def_id) + } + + fn coroutine_is_async(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async(coroutine_def_id) + } + + fn coroutine_is_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_gen(coroutine_def_id) + } + + fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async_gen(coroutine_def_id) + } + + type UnsizingParams = &'tcx rustc_index::bit_set::DenseBitSet; + fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams { + self.unsizing_params_for_adt(adt_def_id) + } + + fn anonymize_bound_vars>>( + self, + binder: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.anonymize_bound_vars(binder) + } + + fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds { + self.opaque_types_defined_by(defining_anchor) + } + + fn opaque_types_and_coroutines_defined_by( + self, + defining_anchor: Self::LocalDefId, + ) -> Self::LocalDefIds { + let coroutines_defined_by = self + .nested_bodies_within(defining_anchor) + .iter() + .filter(|def_id| self.is_coroutine(def_id.to_def_id())); + self.mk_local_def_ids_from_iter( + self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), + ) + } + + type Probe = &'tcx inspect::Probe>; + fn mk_probe(self, probe: inspect::Probe) -> &'tcx inspect::Probe> { + self.arena.alloc(probe) + } + fn evaluate_root_goal_for_proof_tree_raw( + self, + canonical_goal: CanonicalInput<'tcx>, + ) -> (QueryResult<'tcx>, &'tcx inspect::Probe>) { + self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) + } + + fn item_name(self, id: DefId) -> Symbol { + let id = id.into_query_param(); + self.opt_item_name(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } +} + +/// Defines trivial conversion functions between the main [`LangItem`] enum, +/// and some other lang-item enum that is a subset of it. +macro_rules! bidirectional_lang_item_map { + ( + $solver_ty:ident, fn $to_solver:ident, fn $from_solver:ident; + $($name:ident),+ $(,)? + ) => { + fn $from_solver(lang_item: $solver_ty) -> LangItem { + match lang_item { + $($solver_ty::$name => LangItem::$name,)+ + } + } + + fn $to_solver(lang_item: LangItem) -> Option<$solver_ty> { + Some(match lang_item { + $(LangItem::$name => $solver_ty::$name,)+ + _ => return None, + }) + } + } +} + +bidirectional_lang_item_map! { + SolverLangItem, fn lang_item_to_solver_lang_item, fn solver_lang_item_to_lang_item; + +// tidy-alphabetical-start + AsyncFnKindUpvars, + AsyncFnOnceOutput, + CallOnceFuture, + CallRefFuture, + CoroutineReturn, + CoroutineYield, + DynMetadata, + FutureOutput, + Metadata, +// tidy-alphabetical-end +} + +bidirectional_lang_item_map! { + SolverAdtLangItem, fn lang_item_to_solver_adt_lang_item, fn solver_adt_lang_item_to_lang_item; + +// tidy-alphabetical-start + Option, + Poll, +// tidy-alphabetical-end +} + +bidirectional_lang_item_map! { + SolverTraitLangItem, fn lang_item_to_solver_trait_lang_item, fn solver_trait_lang_item_to_lang_item; + +// tidy-alphabetical-start + AsyncFn, + AsyncFnKindHelper, + AsyncFnMut, + AsyncFnOnce, + AsyncFnOnceOutput, + AsyncIterator, + BikeshedGuaranteedNoDrop, + Clone, + Copy, + Coroutine, + Destruct, + DiscriminantKind, + Drop, + Fn, + FnMut, + FnOnce, + FnPtrTrait, + FusedIterator, + Future, + Iterator, + MetaSized, + PointeeSized, + PointeeTrait, + Sized, + TransmuteTrait, + TrivialClone, + Tuple, + Unpin, + Unsize, +// tidy-alphabetical-end +} diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index fa9995898ac2..d37ad56c2e83 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sync; use super::{GlobalCtxt, TyCtxt}; use crate::dep_graph::TaskDepsRef; -use crate::query::plumbing::QueryJobId; +use crate::query::QueryJobId; /// This is the implicit state of rustc. It contains the current /// `TyCtxt` and query. It is updated when creating a local interner or @@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// The current `TyCtxt`. pub tcx: TyCtxt<'tcx>, - /// The current query job, if any. This is updated by `JobOwner::start` in - /// `ty::query::plumbing` when executing a query. + /// The current query job, if any. pub query: Option, /// Used to prevent queries from calling too deeply. diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 279c34cb275d..b3b06314e1a0 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -526,12 +526,15 @@ pub fn suggest_constraining_type_params<'a>( // // fn foo(t: T) { ... } // - help: consider restricting this type parameter with `T: Foo` - suggestions.push(( - param.span.shrink_to_hi(), - post, - format!(": {constraint}"), - SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, - )); + let span = param.span.shrink_to_hi(); + if span.can_be_used_for_suggestions() { + suggestions.push(( + span, + post, + format!(": {constraint}"), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } // FIXME: remove the suggestions that are from derive, as the span is not correct diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index ee29afcff638..3d9148d6ed7b 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; use crate::ty::{ - self, Binder, BoundConst, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -58,28 +58,28 @@ where /// gets mapped to the same result. `BoundVarReplacer` caches by using /// a `DelayedMap` which does not cache the first few types it encounters. pub trait BoundVarReplacerDelegate<'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>; - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>; - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx>; + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx>; + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx>; + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx>; } /// A simple delegate taking 3 mutable functions. The used functions must /// always return the same result for each bound variable, no matter how /// frequently they are called. pub struct FnMutDelegate<'a, 'tcx> { - pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), - pub consts: &'a mut (dyn FnMut(ty::BoundConst) -> ty::Const<'tcx> + 'a), + pub regions: &'a mut (dyn FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx> + 'a), + pub types: &'a mut (dyn FnMut(ty::BoundTy<'tcx>) -> Ty<'tcx> + 'a), + pub consts: &'a mut (dyn FnMut(ty::BoundConst<'tcx>) -> ty::Const<'tcx> + 'a), } impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { (self.regions)(br) } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { (self.types)(bt) } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { (self.consts)(bc) } } @@ -207,13 +207,14 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, mut fld_r: F, - ) -> (T, FxIndexMap>) + ) -> (T, FxIndexMap, ty::Region<'tcx>>) where - F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, { let mut region_map = FxIndexMap::default(); - let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); + let real_fld_r = + |br: ty::BoundRegion<'tcx>| *region_map.entry(br).or_insert_with(|| fld_r(br)); let value = self.instantiate_bound_regions_uncached(value, real_fld_r); (value, region_map) } @@ -224,7 +225,7 @@ impl<'tcx> TyCtxt<'tcx> { mut replace_regions: F, ) -> T where - F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, { let value = value.skip_binder(); @@ -292,14 +293,14 @@ impl<'tcx> TyCtxt<'tcx> { self.replace_escaping_bound_vars_uncached( value, FnMutDelegate { - regions: &mut |r: ty::BoundRegion| { + regions: &mut |r: ty::BoundRegion<'tcx>| { ty::Region::new_bound( self, ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, ) }, - types: &mut |t: ty::BoundTy| { + types: &mut |t: ty::BoundTy<'tcx>| { Ty::new_bound( self, ty::INNERMOST, @@ -307,11 +308,7 @@ impl<'tcx> TyCtxt<'tcx> { ) }, consts: &mut |c| { - ty::Const::new_bound( - self, - ty::INNERMOST, - ty::BoundConst { var: shift_bv(c.var) }, - ) + ty::Const::new_bound(self, ty::INNERMOST, ty::BoundConst::new(shift_bv(c.var))) }, }, ) @@ -333,10 +330,10 @@ impl<'tcx> TyCtxt<'tcx> { { struct Anonymize<'a, 'tcx> { tcx: TyCtxt<'tcx>, - map: &'a mut FxIndexMap, + map: &'a mut FxIndexMap>, } impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'_, 'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { let entry = self.map.entry(br.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); @@ -346,7 +343,7 @@ impl<'tcx> TyCtxt<'tcx> { let br = ty::BoundRegion { var, kind }; ty::Region::new_bound(self.tcx, ty::INNERMOST, br) } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { let entry = self.map.entry(bt.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); @@ -355,12 +352,12 @@ impl<'tcx> TyCtxt<'tcx> { .expect_ty(); Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { let entry = self.map.entry(bc.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - ty::Const::new_bound(self.tcx, ty::INNERMOST, BoundConst { var }) + ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var)) } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index b6b10e245857..ed587cbc3c28 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -284,7 +284,7 @@ impl<'tcx> Generics { args: &'a [ty::GenericArg<'tcx>], ) -> &'a [ty::GenericArg<'tcx>] { let mut own_params = self.parent_count..self.count(); - if self.has_self && self.parent.is_none() { + if self.has_own_self() { own_params.start = 1; } @@ -316,7 +316,7 @@ impl<'tcx> Generics { args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { let own = &args[self.parent_count..][..self.own_params.len()]; - if self.has_self && self.parent.is_none() { &own[1..] } else { own } + if self.has_own_self() { &own[1..] } else { own } } /// Returns true if a concrete type is specified after a default type. @@ -350,6 +350,10 @@ impl<'tcx> Generics { pub fn is_own_empty(&'tcx self) -> bool { self.own_params.is_empty() } + + pub fn has_own_self(&'tcx self) -> bool { + self.has_self && self.parent.is_none() + } } /// Bounds on generics. diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index ac45ce887c9a..95a1a1bf5bce 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -20,6 +20,9 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + // Note: this cache makes an *enormous* performance difference on certain benchmarks. E.g. + // without it, compiling `diesel-2.2.10` can be 74% slower, and compiling + // `deeply-nested-multi` can be ~4,000x slower(!) thread_local! { static CACHE: RefCell> = RefCell::new(Default::default()); diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index d03e593e37b9..c935869b504c 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -2,8 +2,7 @@ use rustc_macros::HashStable; use smallvec::SmallVec; use tracing::instrument; -use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv}; +use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TyCtxt, TypingEnv}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 7eb74b52b44c..5c4c1733be29 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -47,8 +47,7 @@ use rustc_type_ir::TyKind::*; use tracing::instrument; use crate::query::Providers; -use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility}; +use crate::ty::{self, DefId, Ty, TyCtxt, TypeVisitableExt, VariantDef, Visibility}; pub mod inhabited_predicate; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 14ebcc968f7a..0dcbafed3e90 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -8,7 +8,7 @@ use rustc_abi::{ }; use rustc_error_messages::DiagMessage; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, + Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg, }; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; @@ -268,18 +268,23 @@ impl<'tcx> LayoutError<'tcx> { pub fn diagnostic_message(&self) -> DiagMessage { use LayoutError::*; - use crate::fluent_generated::*; match self { - Unknown(_) => middle_layout_unknown, - SizeOverflow(_) => middle_layout_size_overflow, - InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { - middle_layout_simd_too_many + Unknown(_) => msg!("the type `{$ty}` has an unknown layout"), + SizeOverflow(_) => { + msg!("values of the type `{$ty}` are too big for the target architecture") } - InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => middle_layout_simd_zero_length, - TooGeneric(_) => middle_layout_too_generic, - NormalizationFailure(_, _) => middle_layout_normalization_failure, - Cycle(_) => middle_layout_cycle, - ReferencesError(_) => middle_layout_references_error, + InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { + msg!("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}") + } + InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => { + msg!("the SIMD type `{$ty}` has zero elements") + } + TooGeneric(_) => msg!("the type `{$ty}` does not have a fixed layout"), + NormalizationFailure(_, _) => msg!( + "unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized" + ), + Cycle(_) => msg!("a cycle occurred during layout computation"), + ReferencesError(_) => msg!("the type has an unknown layout"), } } @@ -1041,9 +1046,11 @@ where hir::Mutability::Not => { PointerKind::SharedRef { frozen: optimize && ty.is_freeze(tcx, typing_env) } } - hir::Mutability::Mut => { - PointerKind::MutableRef { unpin: optimize && ty.is_unpin(tcx, typing_env) } - } + hir::Mutability::Mut => PointerKind::MutableRef { + unpin: optimize + && ty.is_unpin(tcx, typing_env) + && ty.is_unsafe_unpin(tcx, typing_env), + }, }; tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { @@ -1138,7 +1145,9 @@ where debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && boxed_ty.is_unpin(tcx, typing_env), + unpin: optimize + && boxed_ty.is_unpin(tcx, typing_env) + && boxed_ty.is_unsafe_unpin(tcx, typing_env), global: this.ty.is_box_global(tcx), }); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ce713dcf42f5..036397709925 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -76,8 +76,9 @@ pub use self::closure::{ place_to_string_for_capture, }; pub use self::consts::{ - AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, - ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, + AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, + LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, + const_lit_matches_ty, }; pub use self::context::{ CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, @@ -97,13 +98,13 @@ pub use self::predicate::{ RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate, }; pub use self::region::{ - BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, - RegionKind, RegionVid, + EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ - AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, - ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, + AliasTy, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, + BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, + PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -408,6 +409,12 @@ impl> Visibility { } } +impl + Copy> Visibility { + pub fn min(self, vis: Visibility, tcx: TyCtxt<'_>) -> Visibility { + if self.is_at_least(vis, tcx) { vis } else { self } + } +} + impl Visibility { pub fn expect_local(self) -> Visibility { self.map_id(|id| id.expect_local()) @@ -914,100 +921,6 @@ impl<'tcx> DefinitionSiteHiddenType<'tcx> { } } -pub type PlaceholderRegion<'tcx> = ty::Placeholder, BoundRegion>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderRegion<'tcx> { - type Bound = BoundRegion; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundRegion) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundRegion { var, kind: BoundRegionKind::Anon }) - } -} - -pub type PlaceholderType<'tcx> = ty::Placeholder, BoundTy>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderType<'tcx> { - type Bound = BoundTy; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundTy) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundTy { var, kind: BoundTyKind::Anon }) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -#[derive(TyEncodable, TyDecodable)] -pub struct BoundConst { - pub var: BoundVar, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundConst { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - var.expect_const() - } -} - -pub type PlaceholderConst<'tcx> = ty::Placeholder, BoundConst>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderConst<'tcx> { - type Bound = BoundConst; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundConst) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundConst { var }) - } -} - pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo>; impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { @@ -2180,8 +2093,16 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Impl { of_trait: false } => { self.constness(def_id) == hir::Constness::Const } - DefKind::Impl { of_trait: true } | DefKind::Trait => { - self.is_conditionally_const(parent_def_id) + DefKind::Impl { of_trait: true } => { + let Some(trait_method_did) = self.trait_item_of(def_id) else { + return false; + }; + self.constness(trait_method_did) == hir::Constness::Const + && self.is_conditionally_const(parent_def_id) + } + DefKind::Trait => { + self.constness(def_id) == hir::Constness::Const + && self.is_conditionally_const(parent_def_id) } _ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"), } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 69dcca54f469..3baeb7141de5 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -49,10 +49,6 @@ impl<'tcx> rustc_type_ir::inherent::Predicate> for Predicate<'tcx> fn as_clause(self) -> Option> { self.as_clause() } - - fn allow_normalization(self) -> bool { - self.allow_normalization() - } } impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> { @@ -121,25 +117,7 @@ impl<'tcx> Predicate<'tcx> { /// unsoundly accept some programs. See #91068. #[inline] pub fn allow_normalization(self) -> bool { - match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { - false - } - PredicateKind::Clause(ClauseKind::Trait(_)) - | PredicateKind::Clause(ClauseKind::HostEffect(..)) - | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) - | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) - | PredicateKind::Clause(ClauseKind::Projection(_)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) - | PredicateKind::DynCompatible(_) - | PredicateKind::Subtype(_) - | PredicateKind::Coerce(_) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) - | PredicateKind::ConstEquate(_, _) - | PredicateKind::NormalizesTo(..) - | PredicateKind::Ambiguous => true, - } + rustc_type_ir::inherent::Predicate::allow_normalization(self) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 76a4f61e6714..02b804c1ab29 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -197,7 +197,7 @@ pub struct RegionHighlightMode<'tcx> { /// This is used when you have a signature like `fn foo(x: &u32, /// y: &'a u32)` and we want to give a name to the region of the /// reference `x`. - highlight_bound_region: Option<(ty::BoundRegionKind, usize)>, + highlight_bound_region: Option<(ty::BoundRegionKind<'tcx>, usize)>, } impl<'tcx> RegionHighlightMode<'tcx> { @@ -246,7 +246,7 @@ impl<'tcx> RegionHighlightMode<'tcx> { /// Highlight the given bound region. /// We can only highlight one bound region at a time. See /// the field `highlight_bound_region` for more detailed notes. - pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) { + pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind<'tcx>, number: usize) { assert!(self.highlight_bound_region.is_none()); self.highlight_bound_region = Some((br, number)); } @@ -2639,12 +2639,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, current_index: ty::DebruijnIndex, - region_map: UnordMap>, + region_map: UnordMap, ty::Region<'tcx>>, name: &'a mut ( dyn FnMut( Option, // Debruijn index of the folded late-bound region ty::DebruijnIndex, // Index corresponding to binder level - ty::BoundRegion, + ty::BoundRegion<'tcx>, ) -> ty::Region<'tcx> + 'a ), @@ -2717,7 +2717,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { &mut self, value: &ty::Binder<'tcx, T>, mode: WrapBinderMode, - ) -> Result<(T, UnordMap>), fmt::Error> + ) -> Result<(T, UnordMap, ty::Region<'tcx>>), fmt::Error> where T: TypeFoldable>, { @@ -2810,12 +2810,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // see issue #102392. let mut name = |lifetime_idx: Option, binder_level_idx: ty::DebruijnIndex, - br: ty::BoundRegion| { + br: ty::BoundRegion<'tcx>| { let (name, kind) = if let Some(name) = br.kind.get_name(tcx) { (name, br.kind) } else { let name = next_name(self); - (name, ty::BoundRegionKind::NamedAnon(name)) + (name, ty::BoundRegionKind::NamedForPrinting(name)) }; if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 61994d928dec..a497501ef19d 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -50,7 +50,7 @@ impl<'tcx> Region<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_region: ty::BoundRegion, + bound_region: ty::BoundRegion<'tcx>, ) -> Region<'tcx> { // Use a pre-interned one when possible. if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region @@ -160,7 +160,7 @@ impl<'tcx> rustc_type_ir::inherent::Region> for Region<'tcx> { fn new_bound( interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - var: ty::BoundRegion, + var: ty::BoundRegion<'tcx>, ) -> Self { Region::new_bound(interner, debruijn, var) } @@ -388,7 +388,7 @@ pub struct LateParamRegion { pub kind: LateParamRegionKind, } -/// When liberating bound regions, we map their [`BoundRegionKind`] +/// When liberating bound regions, we map their [`ty::BoundRegionKind`] /// to this as we need to track the index of anonymous regions. We /// otherwise end up liberating multiple bound regions to the same /// late-bound region. @@ -397,7 +397,7 @@ pub struct LateParamRegion { pub enum LateParamRegionKind { /// An anonymous region parameter for a given fn (&T) /// - /// Unlike [`BoundRegionKind::Anon`], this tracks the index of the + /// Unlike [`ty::BoundRegionKind::Anon`], this tracks the index of the /// liberated bound region. /// /// We should ideally never liberate anonymous regions, but do so for the @@ -418,12 +418,14 @@ pub enum LateParamRegionKind { } impl LateParamRegionKind { - pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind { + pub fn from_bound(var: BoundVar, br: ty::BoundRegionKind<'_>) -> LateParamRegionKind { match br { - BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()), - BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id), - BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv, - BoundRegionKind::NamedAnon(name) => LateParamRegionKind::NamedAnon(var.as_u32(), name), + ty::BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()), + ty::BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id), + ty::BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv, + ty::BoundRegionKind::NamedForPrinting(name) => { + LateParamRegionKind::NamedAnon(var.as_u32(), name) + } } } @@ -450,81 +452,6 @@ impl LateParamRegionKind { } } -#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -pub enum BoundRegionKind { - /// An anonymous region parameter for a given fn (&T) - Anon, - - /// An anonymous region parameter with a `Symbol` name. - /// - /// Used to give late-bound regions names for things like pretty printing. - NamedAnon(Symbol), - - /// Late-bound regions that appear in the AST. - Named(DefId), - - /// Anonymous region for the implicit env pointer parameter - /// to a closure - ClosureEnv, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub struct BoundRegion { - pub var: BoundVar, - pub kind: BoundRegionKind, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundRegion { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - assert_eq!(self.kind, var.expect_region()) - } -} - -impl core::fmt::Debug for BoundRegion { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.kind { - BoundRegionKind::Anon => write!(f, "{:?}", self.var), - BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var), - BoundRegionKind::Named(def) => { - write!(f, "{:?}.Named({:?})", self.var, def) - } - BoundRegionKind::NamedAnon(symbol) => { - write!(f, "{:?}.NamedAnon({:?})", self.var, symbol) - } - } - } -} - -impl BoundRegionKind { - pub fn is_named(&self, tcx: TyCtxt<'_>) -> bool { - self.get_name(tcx).is_some() - } - - pub fn get_name(&self, tcx: TyCtxt<'_>) -> Option { - match *self { - BoundRegionKind::Named(def_id) => { - let name = tcx.item_name(def_id); - if name != kw::UnderscoreLifetime { Some(name) } else { None } - } - BoundRegionKind::NamedAnon(name) => Some(name), - _ => None, - } - } - - pub fn get_id(&self) -> Option { - match *self { - BoundRegionKind::Named(id) => Some(id), - _ => None, - } - } -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 314d2ba39632..8707b03e4b8f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -65,21 +65,6 @@ impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> { } } -impl fmt::Debug for ty::BoundRegionKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::BoundRegionKind::Anon => write!(f, "BrAnon"), - ty::BoundRegionKind::NamedAnon(name) => { - write!(f, "BrNamedAnon({name})") - } - ty::BoundRegionKind::Named(did) => { - write!(f, "BrNamed({did:?})") - } - ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"), - } - } -} - impl fmt::Debug for ty::LateParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind) @@ -175,15 +160,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> { } } -impl fmt::Debug for ty::BoundTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ty::BoundTyKind::Anon => write!(f, "{:?}", self.var), - ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"), - } - } -} - impl<'tcx> fmt::Debug for GenericArg<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind() { @@ -255,7 +231,8 @@ TrivialTypeTraversalImpls! { crate::ty::AdtKind, crate::ty::AssocItem, crate::ty::AssocKind, - crate::ty::BoundRegion, + crate::ty::BoundRegion<'tcx>, + crate::ty::BoundTy<'tcx>, crate::ty::ScalarInt, crate::ty::UserTypeAnnotationIndex, crate::ty::abstract_const::NotConstEvaluatable, @@ -284,7 +261,6 @@ TrivialTypeTraversalImpls! { TrivialTypeTraversalAndLiftImpls! { // tidy-alphabetical-start crate::mir::RuntimeChecks, - crate::ty::BoundTy, crate::ty::ParamTy, crate::ty::instance::ReifyReason, rustc_hir::def_id::DefId, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b0b5a783b00e..4be30d8b6c91 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym}; use rustc_type_ir::TyKind::*; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::walk::TypeWalker; @@ -26,8 +26,8 @@ use crate::infer::canonical::Canonical; use crate::traits::ObligationCause; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, - Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, + self, AdtDef, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, Region, Ty, + TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, }; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here @@ -40,6 +40,15 @@ pub type Binder<'tcx, T> = ir::Binder, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub type TypingMode<'tcx> = ir::TypingMode>; pub type Placeholder<'tcx, T> = ir::Placeholder, T>; +pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion>; +pub type PlaceholderType<'tcx> = ir::PlaceholderType>; +pub type PlaceholderConst<'tcx> = ir::PlaceholderConst>; +pub type BoundTy<'tcx> = ir::BoundTy>; +pub type BoundConst<'tcx> = ir::BoundConst>; +pub type BoundRegion<'tcx> = ir::BoundRegion>; +pub type BoundVariableKind<'tcx> = ir::BoundVariableKind>; +pub type BoundRegionKind<'tcx> = ir::BoundRegionKind>; +pub type BoundTyKind<'tcx> = ir::BoundTyKind>; pub trait Article { fn article(&self) -> &'static str; @@ -257,37 +266,6 @@ impl<'tcx> InlineConstArgs<'tcx> { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum BoundVariableKind { - Ty(BoundTyKind), - Region(BoundRegionKind), - Const, -} - -impl BoundVariableKind { - pub fn expect_region(self) -> BoundRegionKind { - match self { - BoundVariableKind::Region(lt) => lt, - _ => bug!("expected a region, but found another kind"), - } - } - - pub fn expect_ty(self) -> BoundTyKind { - match self { - BoundVariableKind::Ty(ty) => ty, - _ => bug!("expected a type, but found another kind"), - } - } - - pub fn expect_const(self) { - match self { - BoundVariableKind::Const => (), - _ => bug!("expected a const, but found another kind"), - } - } -} - pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; @@ -381,30 +359,6 @@ impl ParamConst { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub struct BoundTy { - pub var: BoundVar, - pub kind: BoundTyKind, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundTy { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - assert_eq!(self.kind, var.expect_ty()) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum BoundTyKind { - Anon, - Param(DefId), -} - /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { /// Avoid using this in favour of more specific `new_*` methods, where possible. @@ -479,7 +433,7 @@ impl<'tcx> Ty<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, index: ty::DebruijnIndex, - bound_ty: ty::BoundTy, + bound_ty: ty::BoundTy<'tcx>, ) -> Ty<'tcx> { // Use a pre-interned one when possible. if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty @@ -961,7 +915,11 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_placeholder(tcx, placeholder) } - fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self { + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundTy<'tcx>, + ) -> Self { Ty::new_bound(interner, debruijn, var) } @@ -1378,25 +1336,17 @@ impl<'tcx> Ty<'tcx> { } } - pub fn pinned_ref(self) -> Option<(Ty<'tcx>, ty::Mutability)> { - if let Adt(def, args) = self.kind() - && def.is_pin() - && let &ty::Ref(_, ty, mutbl) = args.type_at(0).kind() - { - return Some((ty, mutbl)); - } - None - } - - pub fn maybe_pinned_ref(self) -> Option<(Ty<'tcx>, ty::Pinnedness, ty::Mutability)> { - match *self.kind() { + pub fn maybe_pinned_ref( + self, + ) -> Option<(Ty<'tcx>, ty::Pinnedness, ty::Mutability, Region<'tcx>)> { + match self.kind() { Adt(def, args) if def.is_pin() - && let ty::Ref(_, ty, mutbl) = *args.type_at(0).kind() => + && let &ty::Ref(region, ty, mutbl) = args.type_at(0).kind() => { - Some((ty, ty::Pinnedness::Pinned, mutbl)) + Some((ty, ty::Pinnedness::Pinned, mutbl, region)) } - ty::Ref(_, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl)), + &Ref(region, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl, region)), _ => None, } } @@ -2135,6 +2085,12 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { + fn is_kw_underscore_lifetime(self) -> bool { + self == kw::UnderscoreLifetime + } +} + // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c4212eee8e40..d534c273ff65 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -10,11 +10,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; use rustc_hashes::Hash128; -use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::limit::Limit; +use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_span::sym; @@ -642,12 +642,8 @@ impl<'tcx> TyCtxt<'tcx> { /// has its own type-checking context or "inference environment". /// /// For example, a closure has its own `DefId`, but it is type-checked - /// with the containing item. Similarly, an inline const block has its - /// own `DefId` but it is type-checked together with the containing item. - /// - /// Therefore, when we fetch the - /// `typeck` the closure, for example, we really wind up - /// fetching the `typeck` the enclosing fn item. + /// with the containing item. Therefore, when we fetch the `typeck` of the closure, + /// for example, we really wind up fetching the `typeck` of the enclosing fn item. pub fn typeck_root_def_id(self, def_id: DefId) -> DefId { let mut def_id = def_id; while self.is_typeck_child(def_id) { @@ -1193,14 +1189,23 @@ impl<'tcx> Ty<'tcx> { } } + /// Checks whether values of this type `T` implement the `UnsafeUnpin` trait. + pub fn is_unsafe_unpin(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx.is_unsafe_unpin_raw(typing_env.as_query_input(self)) + } + /// Checks whether values of this type `T` implement the `Unpin` trait. + /// + /// Note that this is a safe trait, so it cannot be very semantically meaningful. + /// However, as a hack to mitigate until a + /// proper solution is implemented, we do give special semantics to the `Unpin` trait. pub fn is_unpin(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { self.is_trivially_unpin() || tcx.is_unpin_raw(typing_env.as_query_input(self)) } - /// Fast path helper for testing if a type is `Unpin`. + /// Fast path helper for testing if a type is `Unpin` *and* `UnsafeUnpin`. /// - /// Returning true means the type is known to be `Unpin`. Returning + /// Returning true means the type is known to be `Unpin` and `UnsafeUnpin`. Returning /// `false` means nothing -- could be `Unpin`, might not be. fn is_trivially_unpin(self) -> bool { match self.kind() { @@ -1683,7 +1688,9 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may /// cause an ICE that we otherwise may want to prevent. pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - if tcx.features().intrinsics() && tcx.has_attr(def_id, sym::rustc_intrinsic) { + if tcx.features().intrinsics() + && find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) + { let must_be_overridden = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => { !has_body @@ -1693,7 +1700,10 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option TyCtxt<'tcx> { pub fn collect_constrained_late_bound_regions( self, value: Binder<'tcx, T>, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -124,7 +124,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn collect_referenced_late_bound_regions( self, value: Binder<'tcx, T>, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -135,7 +135,7 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, just_constrained: bool, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -149,9 +149,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Collects all the late-bound regions at the innermost binding level /// into a hash set. -struct LateBoundRegionsCollector { +struct LateBoundRegionsCollector<'tcx> { current_index: ty::DebruijnIndex, - regions: FxIndexSet, + regions: FxIndexSet>, /// `true` if we only want regions that are known to be /// "constrained" when you equate this type with another type. In @@ -163,13 +163,13 @@ struct LateBoundRegionsCollector { just_constrained: bool, } -impl LateBoundRegionsCollector { +impl LateBoundRegionsCollector<'_> { fn new(just_constrained: bool) -> Self { Self { current_index: ty::INNERMOST, regions: Default::default(), just_constrained } } } -impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { +impl<'tcx> TypeVisitor> for LateBoundRegionsCollector<'tcx> { fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); t.super_visit_with(self); diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index a3e9054fdcb8..edb1eaea3027 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -99,9 +99,10 @@ pub(super) fn vtable_allocation_provider<'tcx>( // This confirms that the layout computation for &dyn Trait has an accurate sizing. assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref)); - let layout = tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .expect("failed to build vtable representation"); + let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { + Ok(layout) => layout, + Err(e) => tcx.dcx().emit_fatal(e.into_diagnostic()), + }; assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); let align = layout.align.bytes(); diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index d5076a278eab..0bbe3856033b 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -2,7 +2,7 @@ pub mod bug; #[derive(Default, Copy, Clone)] pub struct Providers { - pub queries: crate::query::Providers, - pub extern_queries: crate::query::ExternProviders, + pub queries: crate::queries::Providers, + pub extern_queries: crate::queries::ExternProviders, pub hooks: crate::hooks::Providers, } diff --git a/compiler/rustc_middle/src/verify_ich.rs b/compiler/rustc_middle/src/verify_ich.rs new file mode 100644 index 000000000000..c5aec73679ec --- /dev/null +++ b/compiler/rustc_middle/src/verify_ich.rs @@ -0,0 +1,90 @@ +use std::cell::Cell; + +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_query_system::ich::StableHashingContext; +use tracing::instrument; + +use crate::dep_graph::{DepContext, DepGraphData, SerializedDepNodeIndex}; + +#[inline] +#[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] +pub fn incremental_verify_ich( + tcx: Tcx, + dep_graph_data: &DepGraphData, + result: &V, + prev_index: SerializedDepNodeIndex, + hash_result: Option, &V) -> Fingerprint>, + format_value: fn(&V) -> String, +) where + Tcx: DepContext, +{ + if !dep_graph_data.is_index_green(prev_index) { + incremental_verify_ich_not_green(tcx, prev_index) + } + + let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| { + tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) + }); + + let old_hash = dep_graph_data.prev_fingerprint_of(prev_index); + + if new_hash != old_hash { + incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); + } +} + +#[cold] +#[inline(never)] +fn incremental_verify_ich_not_green(tcx: Tcx, prev_index: SerializedDepNodeIndex) +where + Tcx: DepContext, +{ + panic!( + "fingerprint for green query instance not loaded from cache: {:?}", + tcx.dep_graph().data().unwrap().prev_node_of(prev_index) + ) +} + +// Note that this is marked #[cold] and intentionally takes `dyn Debug` for `result`, +// as we want to avoid generating a bunch of different implementations for LLVM to +// chew on (and filling up the final binary, too). +#[cold] +#[inline(never)] +fn incremental_verify_ich_failed( + tcx: Tcx, + prev_index: SerializedDepNodeIndex, + result: &dyn Fn() -> String, +) where + Tcx: DepContext, +{ + // When we emit an error message and panic, we try to debug-print the `DepNode` + // and query result. Unfortunately, this can cause us to run additional queries, + // which may result in another fingerprint mismatch while we're in the middle + // of processing this one. To avoid a double-panic (which kills the process + // before we can print out the query static), we print out a terse + // but 'safe' message if we detect a reentrant call to this method. + thread_local! { + static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; + }; + + let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); + + if old_in_panic { + tcx.sess().dcx().emit_err(crate::error::Reentrant); + } else { + let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { + format!("`cargo clean -p {crate_name}` or `cargo clean`") + } else { + "`cargo clean`".to_string() + }; + + let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index); + tcx.sess().dcx().emit_err(crate::error::IncrementCompilation { + run_cmd, + dep_node: format!("{dep_node:?}"), + }); + panic!("Found unstable fingerprints for {dep_node:?}: {}", result()); + } + + INSIDE_VERIFY_PANIC.set(old_in_panic); +} diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index f756f0a19ee9..f05183d7c068 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -12,7 +12,6 @@ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl deleted file mode 100644 index 8b0c38dd3b53..000000000000 --- a/compiler/rustc_mir_build/messages.ftl +++ /dev/null @@ -1,513 +0,0 @@ -mir_build_adt_defined_here = `{$ty}` defined here - -mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable - -mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable - -mir_build_bindings_with_variant_name = - pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}` - .suggestion = to match on the variant, qualify the path - -mir_build_borrow = value is borrowed by `{$name}` here - -mir_build_borrow_of_layout_constrained_field_requires_unsafe = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{$name}` here - .occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait - .value_borrowed_label = value borrowed here after move - .suggestion = borrow this binding in the pattern to avoid moving the value - -mir_build_call_to_deprecated_safe_fn_requires_unsafe = - call to deprecated safe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - .suggestion = you can wrap the call in an `unsafe` block if you can guarantee {$guarantee} - -mir_build_call_to_fn_with_requires_unsafe = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_call_to_unsafe_fn_requires_unsafe = - call to unsafe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_nameless = - call to unsafe function is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed = - call to unsafe function is unsafe and requires unsafe function or block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - call to unsafe function `{$function}` is unsafe and requires unsafe function or block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable - -mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]` - .label = this value is too generic - -mir_build_const_continue_missing_label_or_value = a `#[const_continue]` must break to a label with a value - -mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]` - .help = try extracting the expression into a `const` item - -mir_build_const_continue_not_const_const_block = `const` blocks may use generics, and are not evaluated early enough -mir_build_const_continue_not_const_const_other = this value must be a literal or a monomorphic const -mir_build_const_continue_not_const_constant_parameter = constant parameters may use generics, and are not evaluated early enough - -mir_build_const_continue_unknown_jump_target = the target of this `#[const_continue]` is not statically known - .label = this value must be a literal or a monomorphic const - -mir_build_const_defined_here = constant defined here - -mir_build_const_param_in_pattern = constant parameters cannot be referenced in patterns - .label = can't be used in patterns -mir_build_const_param_in_pattern_def = constant defined here - -mir_build_const_pattern_depends_on_generic_parameter = constant pattern cannot depend on generic parameters - .label = `const` depends on a generic parameter - -mir_build_could_not_eval_const_pattern = could not evaluate constant pattern - .label = could not evaluate constant - -mir_build_deref_raw_pointer_requires_unsafe = - dereference of raw pointer is unsafe and requires unsafe block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - dereference of raw pointer is unsafe and requires unsafe function or block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_extern_static_requires_unsafe = - use of extern static is unsafe and requires unsafe block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of extern static is unsafe and requires unsafe function or block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - -mir_build_initializing_type_with_requires_unsafe = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_initializing_type_with_unsafe_field_requires_unsafe = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_initializing_type_with_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_inline_assembly_requires_unsafe = - use of inline assembly is unsafe and requires unsafe block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of inline assembly is unsafe and requires unsafe function or block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_interpreted_as_const = introduce a variable instead - -mir_build_invalid_pattern = {$prefix} `{$non_sm_ty}` cannot be used in patterns - .label = {$prefix} can't be used in patterns - -mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the `if let` is useless - .help = consider replacing the `if let` with a `let` - -mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the guard is useless - .help = consider removing the guard and adding a `let` inside the match arm - -mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the `else` clause is useless - .help = consider removing the `else` clause - -mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the loop will never exit - .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it - -mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count -> - [one] pattern - *[other] patterns - } in let chain - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match - .help = consider moving {$count -> - [one] it - *[other] them - } outside of the construct - -mir_build_literal_in_range_out_of_bounds = - literal out of range for `{$ty}` - .label = this value does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - -mir_build_loop_match_arm_with_guard = - match arms that are part of a `#[loop_match]` cannot have guards - -mir_build_loop_match_bad_rhs = - this expression must be a single `match` wrapped in a labeled block - -mir_build_loop_match_bad_statements = - statements are not allowed in this position within a `#[loop_match]` - -mir_build_loop_match_invalid_match = - invalid match on `#[loop_match]` state - .note = a local variable must be the scrutinee within a `#[loop_match]` - -mir_build_loop_match_invalid_update = - invalid update of the `#[loop_match]` state - .label = the assignment must update this variable - -mir_build_loop_match_missing_assignment = - expected a single assignment expression - -mir_build_loop_match_unsupported_type = - this `#[loop_match]` state value has type `{$ty}`, which is not supported - .note = only integers, floats, bool, char, and enums without fields are supported - -mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = - lower bound for range pattern must be less than or equal to upper bound - .label = lower bound larger than upper bound - .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. - -mir_build_lower_range_bound_must_be_less_than_upper = lower bound for range pattern must be less than upper bound - -mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html - -mir_build_moved = value is moved into `{$name}` here - -mir_build_moved_while_borrowed = cannot move out of value because it is borrowed - -mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time - -mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here - -mir_build_mutable_static_requires_unsafe = - use of mutable static is unsafe and requires unsafe block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of mutable static is unsafe and requires unsafe function or block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_mutation_of_layout_constrained_field_requires_unsafe = - mutation of layout constrained field is unsafe and requires unsafe block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - mutation of layout constrained field is unsafe and requires unsafe function or block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_nan_pattern = cannot use NaN in patterns - .label = evaluates to `NaN`, which is not allowed in patterns - .note = NaNs compare inequal to everything, even themselves, so this pattern would never match - .help = try using the `is_nan` method instead - -mir_build_non_const_path = runtime values cannot be referenced in patterns - .label = references a runtime value - -mir_build_non_empty_never_pattern = - mismatched types - .label = a never pattern must be used on an uninhabited type - .note = the matched value is of type `{$ty}` - -mir_build_non_exhaustive_match_all_arms_guarded = - match arms with guards don't count towards exhaustivity - -mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty - .def_note = `{$peeled_ty}` defined here - .type_note = the matched value is of type `{$ty}` - .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive - .reference_note = references are always considered inhabited - .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 = constant of non-structural type `{$ty}` in a pattern - .label = constant of non-structural type - -mir_build_pattern_not_covered = refutable pattern in {$origin} - .pattern_ty = the matched value is of type `{$pattern_ty}` - -mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon - .label = can't be used in patterns - .note = see https://github.com/rust-lang/rust/issues/70861 for details - -mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future - -mir_build_static_in_pattern = statics cannot be referenced in patterns - .label = can't be used in patterns -mir_build_static_in_pattern_def = `static` defined here - -mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits - - -mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count -> - [one] variant that isn't - *[other] variants that aren't - } matched - -mir_build_suggest_let_else = you might want to use `let...else` to handle the {$count -> - [one] variant that isn't - *[other] variants that aren't - } matched - -mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> - [one] pattern - *[other] patterns - } in let chain - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match - .help = consider moving {$count -> - [one] it - *[other] them - } into the body - -mir_build_type_not_structural = constant of non-structural type `{$ty}` in a pattern - .label = constant of non-structural type -mir_build_type_not_structural_def = `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns -mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -mir_build_type_not_structural_tip = - the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -mir_build_union_field_requires_unsafe = - access to union field is unsafe and requires unsafe block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - access to union field is unsafe and requires unsafe function or block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_union_pattern = cannot use unions in constant patterns - .label = can't use a `union` here - -mir_build_unreachable_due_to_uninhabited = unreachable {$descr} - .label = unreachable {$descr} - .label_orig = any code following this expression is unreachable - .note = this expression has type `{$ty}`, which is uninhabited - -mir_build_unreachable_making_this_unreachable = collectively making this unreachable - -mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable - -mir_build_unreachable_matches_same_values = matches some of the same values - -mir_build_unreachable_pattern = unreachable pattern - .label = no value can reach this - .unreachable_matches_no_values = matches no values because `{$matches_no_values_ty}` is uninhabited - .unreachable_uninhabited_note = to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - .unreachable_covered_by_catchall = matches any value - .unreachable_covered_by_one = matches all the relevant values - .unreachable_covered_by_many = multiple earlier patterns match some of the same values - .unreachable_pattern_const_reexport_accessible = there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope - .unreachable_pattern_wanted_const = you might have meant to pattern match against the value of {$is_typo -> - [true] similarly named constant - *[false] constant - } `{$const_name}` instead of introducing a new catch-all binding - .unreachable_pattern_const_inaccessible = there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope - .unreachable_pattern_let_binding = there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings - .suggestion = remove the match arm - -mir_build_unsafe_binder_cast_requires_unsafe = - unsafe binder cast is unsafe and requires unsafe block - .label = unsafe binder cast - .note = casting to or from an `unsafe<...>` binder type is unsafe since it erases lifetime - information that may be required to uphold safety guarantees of a type - -mir_build_unsafe_binder_cast_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - unsafe binder cast is unsafe and requires unsafe block or unsafe fn - .label = unsafe binder cast - .note = casting to or from an `unsafe<...>` binder type is unsafe since it erases lifetime - information that may be required to uphold safety guarantees of a type - -mir_build_unsafe_field_requires_unsafe = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -mir_build_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default -mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items - -mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = - call to unsafe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless = - call to unsafe function is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe = - dereference of raw pointer is unsafe and requires unsafe block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe = - use of extern static is unsafe and requires unsafe block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_unsafe_field_requires_unsafe = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = - use of inline assembly is unsafe and requires unsafe block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe = - use of mutable static is unsafe and requires unsafe block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe = - mutation of layout constrained field is unsafe and requires unsafe block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe = - access to union field is unsafe and requires unsafe block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_unsafe_op_in_unsafe_fn_unsafe_field_requires_unsafe = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns - -mir_build_unused_unsafe = unnecessary `unsafe` block - .label = unnecessary `unsafe` block - -mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block - -mir_build_upper_range_bound_cannot_be_min = exclusive upper bound for a range bound cannot be the minimum - -mir_build_variant_defined_here = not covered - -mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index 792ad6d782cf..1005dd30d73f 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -85,7 +85,7 @@ pub(super) fn build_custom_mir<'tcx>( block_map: FxHashMap::default(), }; - let res: PResult<_> = try { + let res = try { pctxt.parse_args(params)?; pctxt.parse_body(expr)?; }; diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index f50083abc8e4..ed5f0b2e8f75 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -1,14 +1,14 @@ -//! See docs in build/expr/mod.rs +//! See docs in builder/expr/mod.rs use rustc_abi::Size; use rustc_ast::{self as ast}; use rustc_hir::LangItem; -use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar}; +use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{ - self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt as _, - UserTypeAnnotationIndex, + self, CanonicalUserType, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt, + TypeVisitableExt as _, UserTypeAnnotationIndex, }; use rustc_middle::{bug, mir, span_bug}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index a3662b2768cd..7698af4cd38b 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -291,22 +291,18 @@ impl<'tcx> MatchPairTree<'tcx> { } } - PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => { + PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => { let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)` cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns); - let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { - i == variant_index - || !v.inhabited_predicate(cx.tcx, adt_def).instantiate(cx.tcx, args).apply( - cx.tcx, - cx.infcx.typing_env(cx.param_env), - cx.def_id.into(), - ) - }) && !adt_def.variant_list_has_applicable_non_exhaustive(); - if irrefutable { - None - } else { + // We treat non-exhaustive enums the same independent of the crate they are + // defined in, to avoid differences in the operational semantics between crates. + let refutable = + adt_def.variants().len() > 1 || adt_def.is_variant_list_non_exhaustive(); + if refutable { Some(TestableCase::Variant { adt_def, variant_index }) + } else { + None } } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 317df4e64fdb..fbd7aa90f49c 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -578,7 +578,7 @@ fn construct_const<'a, 'tcx>( }) | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. }) | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(ty, Some(_)), + kind: hir::TraitItemKind::Const(ty, Some(_), _), span, .. }) => (*span, ty.span), diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 4a20b05d1fc2..7bced8168bd1 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::Level; use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol}; use crate::builder::ExprCategory; use crate::errors::*; @@ -98,29 +98,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { // from an edition before 2024. &UnsafeOpKind::CallToUnsafeFunction(Some(id)) if !span.at_least_rust_2024() - && let Some(attr) = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024) => + && let Some(suggestion) = find_attr!(self.tcx.get_all_attrs(id), AttributeKind::RustcDeprecatedSafe2024{suggestion} => suggestion) => { - let suggestion = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .find(|item| item.has_name(sym::audit_that)) - .map(|item| { - item.value_str().expect( - "`#[rustc_deprecated_safe_2024(audit_that)]` must have a string value", - ) - }); - let sm = self.tcx.sess.source_map(); - let guarantee = suggestion - .as_ref() - .map(|suggestion| format!("that {}", suggestion)) - .unwrap_or_else(|| String::from("its unsafe preconditions")); - let suggestion = suggestion - .and_then(|suggestion| { - sm.indentation_before(span).map(|indent| { - format!("{}// TODO: Audit that {}.\n", indent, suggestion) // ignore-tidy-todo - }) + let guarantee = format!("that {}", suggestion); + let suggestion = sm + .indentation_before(span) + .map(|indent| { + format!("{}// TODO: Audit that {}.\n", indent, suggestion) // ignore-tidy-todo }) .unwrap_or_default(); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 64e2bb3207c8..58ea9ec5aa22 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, Subdiagnostic, + MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -9,12 +9,10 @@ use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::RustcPatCtxt; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(LintDiagnostic)] -#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)] +#[diag("call to deprecated safe function `{$function}` is unsafe and requires unsafe block")] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, pub(crate) guarantee: String, @@ -23,7 +21,10 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { } #[derive(Subdiagnostic)] -#[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "you can wrap the call in an `unsafe` block if you can guarantee {$guarantee}", + applicability = "machine-applicable" +)] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { pub(crate) start_of_line_suggestion: String, #[suggestion_part(code = "{start_of_line_suggestion}")] @@ -35,10 +36,10 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -46,90 +47,100 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] -#[note] +#[diag("call to unsafe function is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block", code = E0133)] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithUnsafeFieldRequiresUnsafe { - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UnsafeOpInUnsafeFnUseOfUnsafeFieldRequiresUnsafe { - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -137,12 +148,12 @@ pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe, + "mutation of layout constrained field is unsafe and requires unsafe block", code = E0133 )] -#[note] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -150,11 +161,11 @@ pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsa #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe, + "borrow of layout constrained field with interior mutability is unsafe and requires unsafe block", code = E0133, )] pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -162,26 +173,37 @@ pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe, + "unsafe binder cast is unsafe and requires unsafe block information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeOpInUnsafeFnUnsafeBinderCastRequiresUnsafe { - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)] -#[help] +#[diag("call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block", code = E0133)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features}" +)] pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { - #[label] + #[label("call to function with `#[target_feature]`")] pub(crate) span: Span, pub(crate) function: String, pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, - #[note] + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -190,11 +212,11 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafe { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -202,22 +224,22 @@ pub(crate) struct CallToUnsafeFunctionRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] -#[note] +#[diag("call to unsafe function is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe function or block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -226,57 +248,59 @@ pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, + "call to unsafe function is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe function or block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block", code = E0133)] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct InitializingTypeWithRequiresUnsafe { #[primary_span] - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -284,13 +308,15 @@ pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -298,134 +324,150 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_initializing_type_with_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133 )] -#[note] +#[note("unsafe fields may carry library invariants")] pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfMutableStaticRequiresUnsafe { #[primary_span] - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfExternStaticRequiresUnsafe { #[primary_span] - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UseOfUnsafeFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UseOfUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct DerefOfRawPointerRequiresUnsafe { #[primary_span] - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct AccessToUnionFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)] -#[note] +#[diag("mutation of layout constrained field is unsafe and requires unsafe block", code = E0133)] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -433,24 +475,26 @@ pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "mutation of layout constrained field is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)] -#[note] +#[diag("borrow of layout constrained field with interior mutability is unsafe and requires unsafe block", code = E0133)] +#[note( + "references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values" +)] pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -458,47 +502,42 @@ pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note( + "references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values" +)] pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)] -#[help] +#[diag("call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block", code = E0133)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features +}: {$missing_target_features}" +)] pub(crate) struct CallToFunctionWithRequiresUnsafe { #[primary_span] - #[label] + #[label("call to function with `#[target_feature]`")] pub(crate) span: Span, pub(crate) function: String, pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, - #[note] - pub(crate) note: bool, - pub(crate) build_target_features: DiagArgValue, - pub(crate) build_target_features_count: usize, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option, -} - -#[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[help] -pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - #[primary_span] - #[label] - pub(crate) span: Span, - pub(crate) function: String, - pub(crate) missing_target_features: DiagArgValue, - pub(crate) missing_target_features_count: usize, - #[note] + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -508,12 +547,44 @@ pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe, + "call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block", + code = E0133, +)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features +}: {$missing_target_features}" +)] +pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label("call to function with `#[target_feature]`")] + pub(crate) span: Span, + pub(crate) function: String, + pub(crate) missing_target_features: DiagArgValue, + pub(crate) missing_target_features_count: usize, + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] + pub(crate) note: bool, + pub(crate) build_target_features: DiagArgValue, + pub(crate) build_target_features_count: usize, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option, +} + +#[derive(Diagnostic)] +#[diag( + "unsafe binder cast is unsafe and requires unsafe block information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeBinderCastRequiresUnsafe { #[primary_span] - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -521,19 +592,19 @@ pub(crate) struct UnsafeBinderCastRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "unsafe binder cast is unsafe and requires unsafe block or unsafe fn information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeBinderCastRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Subdiagnostic)] -#[label(mir_build_unsafe_not_inherited)] +#[label("items do not inherit unsafety from separate enclosing items")] pub(crate) struct UnsafeNotInheritedNote { #[primary_span] pub(crate) span: Span, @@ -546,11 +617,14 @@ pub(crate) struct UnsafeNotInheritedLintNote { impl Subdiagnostic for UnsafeNotInheritedLintNote { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); + diag.span_note( + self.signature_span, + msg!("an unsafe function restricts its caller, but its body is safe by default"), + ); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); diag.tool_only_multipart_suggestion( - fluent::mir_build_wrap_suggestion, + msg!("consider wrapping the function body in an unsafe block"), vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], Applicability::MachineApplicable, ); @@ -558,9 +632,9 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote { } #[derive(LintDiagnostic)] -#[diag(mir_build_unused_unsafe)] +#[diag("unnecessary `unsafe` block")] pub(crate) struct UnusedUnsafe { - #[label] + #[label("unnecessary `unsafe` block")] pub(crate) span: Span, #[subdiagnostic] pub(crate) enclosing: Option, @@ -568,7 +642,7 @@ pub(crate) struct UnusedUnsafe { #[derive(Subdiagnostic)] pub(crate) enum UnusedUnsafeEnclosing { - #[label(mir_build_unused_unsafe_enclosing_block_label)] + #[label("because it's nested under this `unsafe` block")] Block { #[primary_span] span: Span, @@ -585,7 +659,7 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = - Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); + Diag::new(dcx, level, msg!("non-exhaustive patterns: type `{$ty}` is non-empty")); diag.span(self.scrut_span); diag.code(E0004); let peeled_ty = self.ty.peel_refs(); @@ -605,20 +679,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo let mut span: MultiSpan = def_span.into(); span.push_span_label(def_span, ""); - diag.span_note(span, fluent::mir_build_def_note); + diag.span_note(span, msg!("`{$peeled_ty}` defined here")); } let is_non_exhaustive = matches!(self.ty.kind(), ty::Adt(def, _) if def.variant_list_has_applicable_non_exhaustive()); if is_non_exhaustive { - diag.note(fluent::mir_build_non_exhaustive_type_note); + diag.note(msg!( + "the matched value is of type `{$ty}`, which is marked as non-exhaustive" + )); } else { - diag.note(fluent::mir_build_type_note); + diag.note(msg!("the matched value is of type `{$ty}`")); } if let ty::Ref(_, sub_ty, _) = self.ty.kind() { if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env) { - diag.note(fluent::mir_build_reference_note); + diag.note(msg!("references are always considered inhabited")); } } @@ -633,12 +709,14 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo }; diag.span_suggestion_verbose( braces_span, - fluent::mir_build_suggestion, + msg!("ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown"), format!(" {{{indentation}{more}_ => todo!(),{indentation}}}"), Applicability::HasPlaceholders, ); } else { - diag.help(fluent::mir_build_help); + diag.help(msg!( + "ensure that all possible cases are being handled by adding a match arm with a wildcard pattern" + )); } diag @@ -646,69 +724,80 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } #[derive(Subdiagnostic)] -#[note(mir_build_non_exhaustive_match_all_arms_guarded)] +#[note("match arms with guards don't count towards exhaustivity")] pub(crate) struct NonExhaustiveMatchAllArmsGuarded; #[derive(Diagnostic)] -#[diag(mir_build_static_in_pattern, code = E0158)] +#[diag("statics cannot be referenced in patterns", code = E0158)] pub(crate) struct StaticInPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, - #[label(mir_build_static_in_pattern_def)] + #[label("`static` defined here")] pub(crate) static_span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_param_in_pattern, code = E0158)] +#[diag("constant parameters cannot be referenced in patterns", code = E0158)] pub(crate) struct ConstParamInPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, - #[label(mir_build_const_param_in_pattern_def)] + #[label("constant defined here")] pub(crate) const_span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_non_const_path, code = E0080)] +#[diag("runtime values cannot be referenced in patterns", code = E0080)] pub(crate) struct NonConstPath { #[primary_span] - #[label] + #[label("references a runtime value")] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build_unreachable_pattern)] +#[diag("unreachable pattern")] pub(crate) struct UnreachablePattern<'tcx> { - #[label] + #[label("no value can reach this")] pub(crate) span: Option, - #[label(mir_build_unreachable_matches_no_values)] + #[label("matches no values because `{$matches_no_values_ty}` is uninhabited")] pub(crate) matches_no_values: Option, pub(crate) matches_no_values_ty: Ty<'tcx>, - #[note(mir_build_unreachable_uninhabited_note)] + #[note( + "to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types" + )] pub(crate) uninhabited_note: Option<()>, - #[label(mir_build_unreachable_covered_by_catchall)] + #[label("matches any value")] pub(crate) covered_by_catchall: Option, #[subdiagnostic] pub(crate) wanted_constant: Option, - #[note(mir_build_unreachable_pattern_const_reexport_accessible)] + #[note( + "there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope" + )] pub(crate) accessible_constant: Option, - #[note(mir_build_unreachable_pattern_const_inaccessible)] + #[note( + "there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope" + )] pub(crate) inaccessible_constant: Option, - #[note(mir_build_unreachable_pattern_let_binding)] + #[note( + "there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings" + )] pub(crate) pattern_let_binding: Option, - #[label(mir_build_unreachable_covered_by_one)] + #[label("matches all the relevant values")] pub(crate) covered_by_one: Option, - #[note(mir_build_unreachable_covered_by_many)] + #[note("multiple earlier patterns match some of the same values")] pub(crate) covered_by_many: Option, pub(crate) covered_by_many_n_more_count: usize, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the match arm", code = "", applicability = "machine-applicable")] pub(crate) suggest_remove: Option, } #[derive(Subdiagnostic)] #[suggestion( - mir_build_unreachable_pattern_wanted_const, + "you might have meant to pattern match against the value of {$is_typo -> + [true] similarly named constant + *[false] constant + } `{$const_name}` instead of introducing a new catch-all binding", code = "{const_path}", applicability = "machine-applicable" )] @@ -721,48 +810,50 @@ pub(crate) struct WantedConstant { } #[derive(LintDiagnostic)] -#[diag(mir_build_unreachable_due_to_uninhabited)] +#[diag("unreachable {$descr}")] pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> { pub descr: &'desc str, - #[label] + #[label("unreachable {$descr}")] pub expr: Span, - #[label(mir_build_label_orig)] - #[note] + #[label("any code following this expression is unreachable")] + #[note("this expression has type `{$ty}`, which is uninhabited")] pub orig: Span, pub ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)] +#[diag("constant pattern cannot depend on generic parameters", code = E0158)] pub(crate) struct ConstPatternDependsOnGenericParameter { #[primary_span] - #[label] + #[label("`const` depends on a generic parameter")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_could_not_eval_const_pattern)] +#[diag("could not evaluate constant pattern")] pub(crate) struct CouldNotEvalConstPattern { #[primary_span] - #[label] + #[label("could not evaluate constant")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)] +#[diag("lower bound for range pattern must be less than or equal to upper bound", code = E0030)] pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[primary_span] - #[label] + #[label("lower bound larger than upper bound")] pub(crate) span: Span, - #[note(mir_build_teach_note)] + #[note( + "when matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range" + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(mir_build_literal_in_range_out_of_bounds)] +#[diag("literal out of range for `{$ty}`")] pub(crate) struct LiteralOutOfRange<'tcx> { #[primary_span] - #[label] + #[label("this value does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, pub(crate) min: i128, @@ -770,93 +861,173 @@ pub(crate) struct LiteralOutOfRange<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)] +#[diag("lower bound for range pattern must be less than upper bound", code = E0579)] pub(crate) struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_upper_range_bound_cannot_be_min, code = E0579)] +#[diag("exclusive upper bound for a range bound cannot be the minimum", code = E0579)] pub(crate) struct UpperRangeBoundCannotBeMin { #[primary_span] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build_leading_irrefutable_let_patterns)] -#[note] -#[help] +#[diag( + "leading irrefutable {$count -> + [one] pattern + *[other] patterns +} in let chain" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match" +)] +#[help( + "consider moving {$count -> + [one] it + *[other] them +} outside of the construct" +)] pub(crate) struct LeadingIrrefutableLetPatterns { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_trailing_irrefutable_let_patterns)] -#[note] -#[help] +#[diag( + "trailing irrefutable {$count -> + [one] pattern + *[other] patterns +} in let chain" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match" +)] +#[help( + "consider moving {$count -> + [one] it + *[other] them +} into the body" +)] pub(crate) struct TrailingIrrefutableLetPatterns { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_bindings_with_variant_name, code = E0170)] +#[diag("pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`", code = E0170)] pub(crate) struct BindingsWithVariantName { - #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] + #[suggestion( + "to match on the variant, qualify the path", + code = "{ty_path}::{name}", + applicability = "machine-applicable" + )] pub(crate) suggestion: Option, pub(crate) ty_path: String, pub(crate) name: Ident, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_if_let)] -#[note] -#[help] +#[diag( + "irrefutable `if let` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the `if let` is useless" +)] +#[help("consider replacing the `if let` with a `let`")] pub(crate) struct IrrefutableLetPatternsIfLet { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_if_let_guard)] -#[note] -#[help] +#[diag( + "irrefutable `if let` guard {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the guard is useless" +)] +#[help("consider removing the guard and adding a `let` inside the match arm")] pub(crate) struct IrrefutableLetPatternsIfLetGuard { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_let_else)] -#[note] -#[help] +#[diag( + "irrefutable `let...else` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the `else` clause is useless" +)] +#[help("consider removing the `else` clause")] pub(crate) struct IrrefutableLetPatternsLetElse { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_while_let)] -#[note] -#[help] +#[diag( + "irrefutable `while let` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the loop will never exit" +)] +#[help("consider instead using a `loop {\"{\"} ... {\"}\"}` with a `let` inside it")] pub(crate) struct IrrefutableLetPatternsWhileLet { pub(crate) count: usize, } #[derive(Diagnostic)] -#[diag(mir_build_borrow_of_moved_value)] +#[diag("borrow of moved value")] pub(crate) struct BorrowOfMovedValue<'tcx> { #[primary_span] - #[label] - #[label(mir_build_occurs_because_label)] + #[label("value moved into `{$name}` here")] + #[label( + "move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait" + )] pub(crate) binding_span: Span, - #[label(mir_build_value_borrowed_label)] + #[label("value borrowed here after move")] pub(crate) conflicts_ref: Vec, pub(crate) name: Ident, pub(crate) ty: Ty<'tcx>, - #[suggestion(code = "ref ", applicability = "machine-applicable")] + #[suggestion( + "borrow this binding in the pattern to avoid moving the value", + code = "ref ", + applicability = "machine-applicable" + )] pub(crate) suggest_borrowing: Option, } #[derive(Diagnostic)] -#[diag(mir_build_multiple_mut_borrows)] +#[diag("cannot borrow value as mutable more than once at a time")] pub(crate) struct MultipleMutBorrows { #[primary_span] pub(crate) span: Span, @@ -865,7 +1036,7 @@ pub(crate) struct MultipleMutBorrows { } #[derive(Diagnostic)] -#[diag(mir_build_already_borrowed)] +#[diag("cannot borrow value as mutable because it is also borrowed as immutable")] pub(crate) struct AlreadyBorrowed { #[primary_span] pub(crate) span: Span, @@ -874,7 +1045,7 @@ pub(crate) struct AlreadyBorrowed { } #[derive(Diagnostic)] -#[diag(mir_build_already_mut_borrowed)] +#[diag("cannot borrow value as immutable because it is also borrowed as mutable")] pub(crate) struct AlreadyMutBorrowed { #[primary_span] pub(crate) span: Span, @@ -883,7 +1054,7 @@ pub(crate) struct AlreadyMutBorrowed { } #[derive(Diagnostic)] -#[diag(mir_build_moved_while_borrowed)] +#[diag("cannot move out of value because it is borrowed")] pub(crate) struct MovedWhileBorrowed { #[primary_span] pub(crate) span: Span, @@ -893,19 +1064,19 @@ pub(crate) struct MovedWhileBorrowed { #[derive(Subdiagnostic)] pub(crate) enum Conflict { - #[label(mir_build_mutable_borrow)] + #[label("value is mutably borrowed by `{$name}` here")] Mut { #[primary_span] span: Span, name: Symbol, }, - #[label(mir_build_borrow)] + #[label("value is borrowed by `{$name}` here")] Ref { #[primary_span] span: Span, name: Symbol, }, - #[label(mir_build_moved)] + #[label("value is moved into `{$name}` here")] Moved { #[primary_span] span: Span, @@ -914,50 +1085,56 @@ pub(crate) enum Conflict { } #[derive(Diagnostic)] -#[diag(mir_build_union_pattern)] +#[diag("cannot use unions in constant patterns")] pub(crate) struct UnionPattern { #[primary_span] - #[label] + #[label("can't use a `union` here")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_type_not_structural)] +#[diag("constant of non-structural type `{$ty}` in a pattern")] pub(crate) struct TypeNotStructural<'tcx> { #[primary_span] - #[label] + #[label("constant of non-structural type")] pub(crate) span: Span, - #[label(mir_build_type_not_structural_def)] + #[label("`{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns")] pub(crate) ty_def_span: Span, pub(crate) ty: Ty<'tcx>, - #[note(mir_build_type_not_structural_tip)] + #[note( + "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" + )] pub(crate) manual_partialeq_impl_span: Option, - #[note(mir_build_type_not_structural_more_info)] + #[note( + "see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" + )] pub(crate) manual_partialeq_impl_note: bool, } #[derive(Diagnostic)] -#[diag(mir_build_non_partial_eq_match)] -#[note(mir_build_type_not_structural_more_info)] +#[diag("constant of non-structural type `{$ty}` in a pattern")] +#[note( + "see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" +)] pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] - #[label] + #[label("constant of non-structural type")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_invalid_pattern)] +#[diag("{$prefix} `{$non_sm_ty}` cannot be used in patterns")] pub(crate) struct InvalidPattern<'tcx> { #[primary_span] - #[label] + #[label("{$prefix} can't be used in patterns")] pub(crate) span: Span, pub(crate) non_sm_ty: Ty<'tcx>, pub(crate) prefix: String, } #[derive(Diagnostic)] -#[diag(mir_build_unsized_pattern)] +#[diag("cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns")] pub(crate) struct UnsizedPattern<'tcx> { #[primary_span] pub(crate) span: Span, @@ -965,36 +1142,38 @@ pub(crate) struct UnsizedPattern<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_nan_pattern)] -#[note] -#[help] +#[diag("cannot use NaN in patterns")] +#[note("NaNs compare inequal to everything, even themselves, so this pattern would never match")] +#[help("try using the `is_nan` method instead")] pub(crate) struct NaNPattern { #[primary_span] - #[label] + #[label("evaluates to `NaN`, which is not allowed in patterns")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_pointer_pattern)] -#[note] +#[diag( + "function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon" +)] +#[note("see https://github.com/rust-lang/rust/issues/70861 for details")] pub(crate) struct PointerPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_non_empty_never_pattern)] -#[note] +#[diag("mismatched types")] +#[note("the matched value is of type `{$ty}`")] pub(crate) struct NonEmptyNeverPattern<'tcx> { #[primary_span] - #[label] + #[label("a never pattern must be used on an uninhabited type")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_pattern_not_covered, code = E0005)] +#[diag("refutable pattern in {$origin}", code = E0005)] pub(crate) struct PatternNotCovered<'s, 'tcx> { #[primary_span] pub(crate) span: Span, @@ -1009,10 +1188,12 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { pub(crate) interpreted_as_const_sugg: Option, #[subdiagnostic] pub(crate) adt_defined_here: Option>, - #[note(mir_build_privately_uninhabited)] + #[note( + "pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future" + )] pub(crate) witness_1_is_privately_uninhabited: bool, pub(crate) witness_1: String, - #[note(mir_build_pattern_ty)] + #[note("the matched value is of type `{$pattern_ty}`")] pub(crate) _p: (), pub(crate) pattern_ty: Ty<'tcx>, #[subdiagnostic] @@ -1022,12 +1203,16 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { } #[derive(Subdiagnostic)] -#[note(mir_build_inform_irrefutable)] -#[note(mir_build_more_information)] +#[note( + "`let` bindings require an \"irrefutable pattern\", like a `struct` or an `enum` with only one variant" +)] +#[note("for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html")] pub(crate) struct Inform; #[derive(Subdiagnostic)] -#[label(mir_build_confused)] +#[label( + "missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable" +)] pub(crate) struct InterpretedAsConst { #[primary_span] pub(crate) span: Span, @@ -1050,16 +1235,16 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { let mut spans = MultiSpan::from(self.adt_def_span); for Variant { span } in self.variants { - spans.push_span_label(span, fluent::mir_build_variant_defined_here); + spans.push_span_label(span, msg!("not covered")); } - diag.span_note(spans, fluent::mir_build_adt_defined_here); + diag.span_note(spans, msg!("`{$ty}` defined here")); } } #[derive(Subdiagnostic)] #[suggestion( - mir_build_interpreted_as_const, + "introduce a variable instead", code = "{variable}_var", applicability = "maybe-incorrect", style = "verbose" @@ -1072,7 +1257,13 @@ pub(crate) struct InterpretedAsConstSugg { #[derive(Subdiagnostic)] pub(crate) enum SuggestLet { - #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")] + #[multipart_suggestion( + "you might want to use `if let` to ignore the {$count -> + [one] variant that isn't + *[other] variants that aren't + } matched", + applicability = "has-placeholders" + )] If { #[suggestion_part(code = "if ")] start_span: Span, @@ -1081,7 +1272,10 @@ pub(crate) enum SuggestLet { count: usize, }, #[suggestion( - mir_build_suggest_let_else, + "you might want to use `let...else` to handle the {$count -> + [one] variant that isn't + *[other] variants that aren't + } matched", code = " else {{ todo!() }}", applicability = "has-placeholders" )] @@ -1095,7 +1289,7 @@ pub(crate) enum SuggestLet { #[derive(Subdiagnostic)] pub(crate) enum MiscPatternSuggestion { #[suggestion( - mir_build_suggest_attempted_int_lit, + "alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits", code = "_", applicability = "maybe-incorrect" )] @@ -1106,25 +1300,25 @@ pub(crate) enum MiscPatternSuggestion { } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_invalid_update)] +#[diag("invalid update of the `#[loop_match]` state")] pub(crate) struct LoopMatchInvalidUpdate { #[primary_span] pub lhs: Span, - #[label] + #[label("the assignment must update this variable")] pub scrutinee: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_invalid_match)] -#[note] +#[diag("invalid match on `#[loop_match]` state")] +#[note("a local variable must be the scrutinee within a `#[loop_match]`")] pub(crate) struct LoopMatchInvalidMatch { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_unsupported_type)] -#[note] +#[diag("this `#[loop_match]` state value has type `{$ty}`, which is not supported")] +#[note("only integers, floats, bool, char, and enums without fields are supported")] pub(crate) struct LoopMatchUnsupportedType<'tcx> { #[primary_span] pub span: Span, @@ -1132,36 +1326,36 @@ pub(crate) struct LoopMatchUnsupportedType<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_bad_statements)] +#[diag("statements are not allowed in this position within a `#[loop_match]`")] pub(crate) struct LoopMatchBadStatements { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_bad_rhs)] +#[diag("this expression must be a single `match` wrapped in a labeled block")] pub(crate) struct LoopMatchBadRhs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_missing_assignment)] +#[diag("expected a single assignment expression")] pub(crate) struct LoopMatchMissingAssignment { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_arm_with_guard)] +#[diag("match arms that are part of a `#[loop_match]` cannot have guards")] pub(crate) struct LoopMatchArmWithGuard { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_not_const)] -#[help] +#[diag("could not determine the target branch for this `#[const_continue]`")] +#[help("try extracting the expression into a `const` item")] pub(crate) struct ConstContinueNotMonomorphicConst { #[primary_span] pub span: Span, @@ -1172,19 +1366,19 @@ pub(crate) struct ConstContinueNotMonomorphicConst { #[derive(Subdiagnostic)] pub(crate) enum ConstContinueNotMonomorphicConstReason { - #[label(mir_build_const_continue_not_const_constant_parameter)] + #[label("constant parameters may use generics, and are not evaluated early enough")] ConstantParameter { #[primary_span] span: Span, }, - #[label(mir_build_const_continue_not_const_const_block)] + #[label("`const` blocks may use generics, and are not evaluated early enough")] ConstBlock { #[primary_span] span: Span, }, - #[label(mir_build_const_continue_not_const_const_other)] + #[label("this value must be a literal or a monomorphic const")] Other { #[primary_span] span: Span, @@ -1192,22 +1386,22 @@ pub(crate) enum ConstContinueNotMonomorphicConstReason { } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_bad_const)] +#[diag("could not determine the target branch for this `#[const_continue]`")] pub(crate) struct ConstContinueBadConst { #[primary_span] - #[label] + #[label("this value is too generic")] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_missing_label_or_value)] +#[diag("a `#[const_continue]` must break to a label with a value")] pub(crate) struct ConstContinueMissingLabelOrValue { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_unknown_jump_target)] +#[diag("the target of this `#[const_continue]` is not statically known")] pub(crate) struct ConstContinueUnknownJumpTarget { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 5c5d979306bf..21817dea6cb4 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,7 +1,7 @@ //! Construction of MIR from HIR. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(try_blocks)] @@ -18,8 +18,6 @@ pub mod thir; use rustc_middle::util::Providers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { providers.queries.check_match = thir::pattern::check_match; providers.queries.lit_to_const = thir::constant::lit_to_const; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 96248499044a..b4eedb15033c 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,8 +2,7 @@ use rustc_abi::Size; use rustc_ast::{self as ast, UintTy}; use rustc_hir::LangItem; use rustc_middle::bug; -use rustc_middle::mir::interpret::LitToConstInput; -use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _}; +use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _}; use tracing::trace; use crate::builder::parse_float_into_scalar; @@ -11,11 +10,11 @@ use crate::builder::parse_float_into_scalar; pub(crate) fn lit_to_const<'tcx>( tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>, -) -> ty::Const<'tcx> { - let LitToConstInput { lit, ty, neg } = lit_input; +) -> Option> { + let LitToConstInput { lit, ty: expected_ty, neg } = lit_input; - if let Err(guar) = ty.error_reported() { - return ty::Const::new_error(tcx, guar); + if expected_ty.error_reported().is_err() { + return None; } let trunc = |n, width: ty::UintTy| { @@ -32,22 +31,17 @@ pub(crate) fn lit_to_const<'tcx>( .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)) }; - let valtree = match (lit, ty.kind()) { - (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { + let (valtree, valtree_ty) = match (lit, expected_ty.kind()) { + (ast::LitKind::Str(s, _), _) => { let str_bytes = s.as_str().as_bytes(); - ty::ValTree::from_raw_bytes(tcx, str_bytes) - } - (ast::LitKind::Str(s, _), ty::Str) if tcx.features().deref_patterns() => { - // String literal patterns may have type `str` if `deref_patterns` is enabled, in order - // to allow `deref!("..."): String`. - let str_bytes = s.as_str().as_bytes(); - ty::ValTree::from_raw_bytes(tcx, str_bytes) + let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_); + (ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty) } (ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind() && let ty::Uint(UintTy::U8) = ty.kind() => { - ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()) + (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty) } (ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _)) if tcx.features().deref_patterns() @@ -55,40 +49,66 @@ pub(crate) fn lit_to_const<'tcx>( { // Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is // enabled, in order to allow, e.g., `deref!(b"..."): Vec`. - ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()) + (ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty) } - (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { - ty::ValTree::from_scalar_int(tcx, n.into()) + (ast::LitKind::ByteStr(byte_sym, _), _) => { + let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()); + let valtree_ty = Ty::new_array(tcx, tcx.types.u8, byte_sym.as_byte_str().len() as u64); + (valtree, valtree_ty) } - (ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => + (ast::LitKind::Byte(n), _) => (ty::ValTree::from_scalar_int(tcx, n.into()), tcx.types.u8), + (ast::LitKind::CStr(byte_sym, _), _) + if let Some(cstr_def_id) = tcx.lang_items().get(LangItem::CStr) => { // A CStr is a newtype around a byte slice, so we create the inner slice here. // We need a branch for each "level" of the data structure. + let cstr_ty = tcx.type_of(cstr_def_id).skip_binder(); let bytes = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()); - ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, *inner_ty)]) + let valtree = + ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, bytes, cstr_ty)]); + let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, cstr_ty); + (valtree, valtree_ty) } - (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { + (ast::LitKind::Int(n, ast::LitIntType::Unsigned(ui)), _) if !neg => { + let scalar_int = trunc(n.get(), ui); + (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, ui)) + } + (ast::LitKind::Int(_, ast::LitIntType::Unsigned(_)), _) if neg => return None, + (ast::LitKind::Int(n, ast::LitIntType::Signed(i)), _) => { + let scalar_int = + trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned()); + (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i)) + } + (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => { let scalar_int = trunc(n.get(), *ui); - ty::ValTree::from_scalar_int(tcx, scalar_int) + (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui)) } - (ast::LitKind::Int(n, _), ty::Int(i)) => { + (ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => { // Unsigned "negation" has the same bitwise effect as signed negation, // which gets the result we want without additional casts. let scalar_int = trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned()); - ty::ValTree::from_scalar_int(tcx, scalar_int) + (ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, *i)) } - (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()), - (ast::LitKind::Float(n, _), ty::Float(fty)) => { - let bits = parse_float_into_scalar(n, *fty, neg).unwrap_or_else(|| { - tcx.dcx().bug(format!("couldn't parse float literal: {:?}", lit_input.lit)) - }); - ty::ValTree::from_scalar_int(tcx, bits) + (ast::LitKind::Bool(b), _) => (ty::ValTree::from_scalar_int(tcx, b.into()), tcx.types.bool), + (ast::LitKind::Float(n, ast::LitFloatType::Suffixed(fty)), _) => { + let fty = match fty { + ast::FloatTy::F16 => ty::FloatTy::F16, + ast::FloatTy::F32 => ty::FloatTy::F32, + ast::FloatTy::F64 => ty::FloatTy::F64, + ast::FloatTy::F128 => ty::FloatTy::F128, + }; + let bits = parse_float_into_scalar(n, fty, neg)?; + (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty)) } - (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int(tcx, c.into()), - (ast::LitKind::Err(guar), _) => return ty::Const::new_error(tcx, guar), - _ => return ty::Const::new_misc_error(tcx), + (ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => { + let bits = parse_float_into_scalar(n, *fty, neg)?; + (ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty)) + } + (ast::LitKind::Char(c), _) => (ty::ValTree::from_scalar_int(tcx, c.into()), tcx.types.char), + (ast::LitKind::Err(_), _) => return None, + _ => return None, }; - ty::Const::new_value(tcx, valtree, ty) + Some(ty::Value { ty: valtree_ty, valtree }) } diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index fad73a7115b0..b108dff5555f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -75,8 +75,13 @@ impl<'tcx> ThirBuildCx<'tcx> { debug!(?pattern); let span = match local.init { - Some(init) => local.span.with_hi(init.span.hi()), - None => local.span, + Some(init) + if let Some(init_span) = + init.span.find_ancestor_inside_same_ctxt(local.span) => + { + local.span.with_hi(init_span.hi()) + } + Some(_) | None => local.span, }; let stmt = Stmt { kind: StmtKind::Let { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 8e02424706ee..0117a10e3a8c 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -14,7 +14,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, + Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, PointerCoercion, }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, @@ -140,11 +140,11 @@ impl<'tcx> ThirBuildCx<'tcx> { } Adjust::NeverToAny if adjustment.target.is_never() => return expr, Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) }, - Adjust::Deref(None) => { + Adjust::Deref(DerefAdjustKind::Builtin) => { adjust_span(&mut expr); ExprKind::Deref { arg: self.thir.exprs.push(expr) } } - Adjust::Deref(Some(deref)) => { + Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => { // We don't need to do call adjust_span here since // deref coercions always start with a built-in deref. let call_def_id = deref.method_call(self.tcx); 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 290d4ab2bfbb..56a5aff41d8b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -3,7 +3,7 @@ use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err}; +use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, msg, struct_span_code_err}; use rustc_hir::def::*; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource}; @@ -29,7 +29,6 @@ use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; use crate::errors::*; -use crate::fluent_generated as fluent; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let typeck_results = tcx.typeck(def_id); @@ -986,22 +985,16 @@ fn report_unreachable_pattern<'p, 'tcx>( let mut iter = covering_pats.iter(); let mut multispan = MultiSpan::from_span(pat_span); for p in iter.by_ref().take(CAP_COVERED_BY_MANY) { - multispan.push_span_label( - p.data().span, - fluent::mir_build_unreachable_matches_same_values, - ); + multispan.push_span_label(p.data().span, msg!("matches some of the same values")); } let remain = iter.count(); if remain == 0 { - multispan.push_span_label( - pat_span, - fluent::mir_build_unreachable_making_this_unreachable, - ); + multispan.push_span_label(pat_span, msg!("collectively making this unreachable")); } else { lint.covered_by_many_n_more_count = remain; multispan.push_span_label( pat_span, - fluent::mir_build_unreachable_making_this_unreachable_n_more, + msg!("...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable"), ); } lint.covered_by_many = Some(multispan); 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 0a0e0d06061e..cce5776293e2 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 @@ -3,7 +3,7 @@ use core::ops::ControlFlow; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Diag; +use rustc_errors::{Diag, msg}; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; @@ -82,10 +82,7 @@ impl<'tcx> ConstToPat<'tcx> { err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), ""); } if let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = def_kind { - err.span_label( - self.tcx.def_span(uv.def), - crate::fluent_generated::mir_build_const_defined_here, - ); + err.span_label(self.tcx.def_span(uv.def), msg!("constant defined here")); } } Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None }) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3641561567bc..acf20cb092e2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -8,19 +8,21 @@ use std::cmp::Ordering; use std::sync::Arc; use rustc_abi::{FieldIdx, Integer}; +use rustc_ast::LitKind; use rustc_data_structures::assert_matches; use rustc_errors::codes::*; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, RangeEnd}; use rustc_index::Idx; -use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt, const_lit_matches_ty, +}; use rustc_middle::{bug, span_bug}; use rustc_span::ErrorGuaranteed; use tracing::{debug, instrument}; @@ -197,8 +199,6 @@ impl<'tcx> PatCtxt<'tcx> { expr: Option<&'tcx hir::PatExpr<'tcx>>, ty: Ty<'tcx>, ) -> Result<(), ErrorGuaranteed> { - use rustc_ast::ast::LitKind; - let Some(expr) = expr else { return Ok(()); }; @@ -696,7 +696,17 @@ impl<'tcx> PatCtxt<'tcx> { let pat_ty = self.typeck_results.node_type(pat.hir_id); let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated }; - let constant = self.tcx.at(expr.span).lit_to_const(lit_input); + let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated) + .then(|| self.tcx.at(expr.span).lit_to_const(lit_input)) + .flatten() + .map(|v| ty::Const::new_value(self.tcx, v.valtree, pat_ty)) + .unwrap_or_else(|| { + ty::Const::new_error_with_message( + self.tcx, + expr.span, + "literal does not match expected type", + ) + }); self.const_to_pat(constant, pat_ty, expr.hir_id, lit.span) } } diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 9621f9f20bdc..156caa7030a0 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -8,11 +8,10 @@ edition = "2024" polonius-engine = "0.13.0" regex = "1" rustc_abi = { path = "../rustc_abi" } -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl deleted file mode 100644 index 5698367e42ba..000000000000 --- a/compiler/rustc_mir_dataflow/messages.ftl +++ /dev/null @@ -1,29 +0,0 @@ -mir_dataflow_duplicate_values_for = - duplicate values for `{$name}` - -mir_dataflow_path_must_end_in_filename = - path must end in a filename - -mir_dataflow_peek_argument_not_a_local = - rustc_peek: argument was not a local - -mir_dataflow_peek_argument_untracked = - rustc_peek: argument untracked - -mir_dataflow_peek_bit_not_set = - rustc_peek: bit not set - -mir_dataflow_peek_must_be_not_temporary = - dataflow::sanity_check cannot feed a non-temp to rustc_peek - -mir_dataflow_peek_must_be_place_or_ref_place = - rustc_peek: argument expression must be either `place` or `&place` - -mir_dataflow_requires_an_argument = - `{$name}` requires an argument - -mir_dataflow_stop_after_dataflow_ended_compilation = - stop_after_dataflow ended compilation - -mir_dataflow_unknown_formatter = - unknown formatter diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/errors.rs index cfacc0ec370c..051c0305cf2b 100644 --- a/compiler/rustc_mir_dataflow/src/errors.rs +++ b/compiler/rustc_mir_dataflow/src/errors.rs @@ -1,70 +1,40 @@ use rustc_macros::Diagnostic; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; #[derive(Diagnostic)] -#[diag(mir_dataflow_path_must_end_in_filename)] -pub(crate) struct PathMustEndInFilename { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_unknown_formatter)] -pub(crate) struct UnknownFormatter { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_duplicate_values_for)] -pub(crate) struct DuplicateValuesFor { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_requires_an_argument)] -pub(crate) struct RequiresAnArgument { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_stop_after_dataflow_ended_compilation)] +#[diag("stop_after_dataflow ended compilation")] pub(crate) struct StopAfterDataFlowEndedCompilation; #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_must_be_place_or_ref_place)] +#[diag("rustc_peek: argument expression must be either `place` or `&place`")] pub(crate) struct PeekMustBePlaceOrRefPlace { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_must_be_not_temporary)] +#[diag("dataflow::sanity_check cannot feed a non-temp to rustc_peek")] pub(crate) struct PeekMustBeNotTemporary { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_bit_not_set)] +#[diag("rustc_peek: bit not set")] pub(crate) struct PeekBitNotSet { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_argument_not_a_local)] +#[diag("rustc_peek: argument was not a local")] pub(crate) struct PeekArgumentNotALocal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_argument_untracked)] +#[diag("rustc_peek: argument untracked")] pub(crate) struct PeekArgumentUntracked { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 22bff3806b15..c4b9b4ce6416 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -7,6 +7,9 @@ use std::sync::OnceLock; use std::{io, ops, str}; use regex::Regex; +use rustc_graphviz as dot; +use rustc_hir::attrs::{AttributeKind, BorrowckGraphvizFormatKind, RustcMirKind}; +use rustc_hir::find_attr; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ self, BasicBlock, Body, Location, MirDumper, graphviz_safe_def_name, traversal, @@ -14,17 +17,12 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_span::def_id::DefId; -use rustc_span::{Symbol, sym}; use tracing::debug; -use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; use super::{ Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor, visit_results, }; -use crate::errors::{ - DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, -}; /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are @@ -43,10 +41,7 @@ where use std::io::Write; let def_id = body.source.def_id(); - let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { - // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return Ok(()); - }; + let attrs = RustcMirAttrs::parse(tcx, def_id); let file = try { match attrs.output_path(A::NAME) { @@ -72,10 +67,7 @@ where Err(e) => return Err(e), }; - let style = match attrs.formatter { - Some(sym::two_phase) => OutputStyle::BeforeAndAfter, - _ => OutputStyle::AfterOnly, - }; + let style = attrs.formatter.unwrap_or(OutputStyle::AfterOnly); let mut buf = Vec::new(); @@ -98,71 +90,33 @@ where #[derive(Default)] struct RustcMirAttrs { basename_and_suffix: Option, - formatter: Option, + formatter: Option, } impl RustcMirAttrs { - fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { - let mut result = Ok(()); + fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Self { let mut ret = RustcMirAttrs::default(); - let rustc_mir_attrs = tcx - .get_attrs(def_id, sym::rustc_mir) - .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); - - for attr in rustc_mir_attrs { - let attr_result = match attr.name() { - Some(name @ sym::borrowck_graphviz_postflow) => { - Self::set_field(&mut ret.basename_and_suffix, tcx, name, &attr, |s| { - let path = PathBuf::from(s.to_string()); - match path.file_name() { - Some(_) => Ok(path), - None => { - tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); - Err(()) + let attrs = tcx.get_all_attrs(def_id); + if let Some(rustc_mir_attrs) = find_attr!(attrs, AttributeKind::RustcMir(kind) => kind) { + for attr in rustc_mir_attrs { + match attr { + RustcMirKind::BorrowckGraphvizPostflow { path } => { + ret.basename_and_suffix = Some(path.clone()); + } + RustcMirKind::BorrowckGraphvizFormat { format } => { + ret.formatter = match format { + BorrowckGraphvizFormatKind::TwoPhase => { + Some(OutputStyle::BeforeAndAfter) } - } - }) - } - Some(name @ sym::borrowck_graphviz_format) => { - Self::set_field(&mut ret.formatter, tcx, name, &attr, |s| match s { - sym::two_phase => Ok(s), - _ => { - tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); - Err(()) - } - }) - } - _ => Ok(()), - }; - - result = result.and(attr_result); + }; + } + _ => (), + }; + } } - result.map(|()| ret) - } - - fn set_field( - field: &mut Option, - tcx: TyCtxt<'_>, - name: Symbol, - attr: &ast::MetaItemInner, - mapper: impl FnOnce(Symbol) -> Result, - ) -> Result<(), ()> { - if field.is_some() { - tcx.dcx().emit_err(DuplicateValuesFor { span: attr.span(), name }); - - return Err(()); - } - - if let Some(s) = attr.value_str() { - *field = Some(mapper(s)?); - Ok(()) - } else { - tcx.dcx() - .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() }); - Err(()) - } + ret } /// Returns the path where dataflow results should be written, or `None` diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 485925e7b50c..692591a41a15 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(exact_size_is_empty)] @@ -34,8 +34,6 @@ pub mod rustc_peek; mod un_derefer; pub mod value_analysis; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct MoveDataTypingEnv<'tcx> { pub move_data: MoveData<'tcx>, pub typing_env: ty::TypingEnv<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index a899ec1fa884..1c5b38361669 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,8 +1,8 @@ -use rustc_ast::MetaItem; +use rustc_hir::attrs::{AttributeKind, RustcMirKind}; +use rustc_hir::find_attr; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::def_id::DefId; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, sym}; use tracing::{debug, info}; use crate::errors::{ @@ -14,52 +14,37 @@ use crate::impls::{MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPl use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; -fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { - for attr in tcx.get_attrs(def_id, sym::rustc_mir) { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } - } - } - None -} - pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id(); - if !tcx.has_attr(def_id, sym::rustc_mir) { - debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - return; - } else { + let attrs = tcx.get_all_attrs(def_id); + if let Some(kind) = find_attr!(attrs, AttributeKind::RustcMir(kind) => kind) { + let move_data = MoveData::gather_moves(body, tcx, |_| true); debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - } + if kind.contains(&RustcMirKind::PeekMaybeInit) { + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_inits); + } - let move_data = MoveData::gather_moves(body, tcx, |_| true); + if kind.contains(&RustcMirKind::PeekMaybeUninit) { + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_uninits); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_inits); - } + if kind.contains(&RustcMirKind::PeekLiveness) { + let flow_liveness = + MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_liveness); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_uninits); - } - - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = - MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_liveness); - } - - if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { - tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); + if kind.contains(&RustcMirKind::StopAfterDataflow) { + tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); + } + } else { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); } } diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 22de197d374a..395127edd1e0 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start either = "1" -hashbrown = { version = "0.16.1", default-features = false } itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } @@ -14,7 +13,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl deleted file mode 100644 index 7924c015200f..000000000000 --- a/compiler/rustc_mir_transform/messages.ftl +++ /dev/null @@ -1,114 +0,0 @@ -mir_transform_arithmetic_overflow = this arithmetic operation will overflow - -mir_transform_asm_unwind_call = call to inline assembly that may unwind - -mir_transform_const_defined_here = `const` item defined here - -mir_transform_const_modify = attempting to modify a `const` item - .note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified - -mir_transform_const_mut_borrow = taking a mutable reference to a `const` item - .note = each usage of a `const` item creates a new temporary - .note2 = the mutable reference will refer to this temporary, not the original `const` item - .note3 = mutable reference created due to call to this method - -mir_transform_ffi_unwind_call = call to {$foreign -> - [true] foreign function - *[false] function pointer - } with FFI-unwind ABI - -mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer - .suggestion = cast `{$ident}` to obtain a function pointer - -mir_transform_force_inline = - `{$callee}` could not be inlined into `{$caller}` but is required to be inlined - .call = ...`{$callee}` called here - .attr = inlining due to this annotation - .caller = within `{$caller}`... - .callee = `{$callee}` defined here - .note = could not be inlined due to: {$reason} - -mir_transform_force_inline_attr = - `{$callee}` is incompatible with `#[rustc_force_inline]` - .attr = annotation here - .callee = `{$callee}` defined here - .note = incompatible due to: {$reason} - -mir_transform_force_inline_justification = - `{$callee}` is required to be inlined to: {$sym} - -mir_transform_maybe_string_interpolation = you might have meant to use string interpolation in this string literal - -mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be - .label = the value is held across this suspend point - .note = {$reason} - .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point -mir_transform_operation_will_panic = this operation will panic at runtime - -mir_transform_string_interpolation_only_works = string interpolation only works in `format!` invocations - -mir_transform_tail_expr_drop_order = relative drop order changing in Rust 2024 - .temporaries = in Rust 2024, this temporary value will be dropped first - .observers = in Rust 2024, this local variable or temporary value will be dropped second - .note_dtors = - dropping the temporary value runs this custom `Drop` impl, which we could not prove to be side-effect free - .note_observer_dtors = - dropping the local runs this custom `Drop` impl, which we could not prove to be side-effect free - .drop_location = - now the temporary value is dropped here, before the local variables in the block or statement - .note_epilogue = most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages - .label_local_epilogue = {$is_dropped_first_edition_2024 -> - [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 - *[false] `{$name}` will be dropped later as of Edition 2024 - } - -mir_transform_tail_expr_dtor = {$dtor_kind -> - [dyn] `{$name}` may invoke a custom destructor because it contains a trait object - *[concrete] `{$name}` invokes this custom destructor - } - -mir_transform_tail_expr_local = {$is_generated_name -> - [true] this value will be stored in a temporary; let us call it `{$name}` - *[false] `{$name}` calls a custom destructor - } - -mir_transform_unaligned_packed_ref = reference to field of packed {$ty_descr} is unaligned - .note = this {$ty_descr} is {$align -> - [one] {""} - *[other] {"at most "} - }{$align}-byte aligned, but the type of this field may require higher alignment - .note_ub = 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) - -mir_transform_unconditional_recursion = function cannot return without recursing - .label = cannot return without recursing - .help = a `loop` may express intention better if this is on purpose - -mir_transform_unconditional_recursion_call_site_label = recursive call site - -mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored - -mir_transform_unused_assign = value assigned to `{$name}` is never read - .help = maybe it is overwritten before being read? - -mir_transform_unused_assign_passed = value passed to `{$name}` is never read - .help = maybe it is overwritten before being read? - -mir_transform_unused_assign_suggestion = - you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding - -mir_transform_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read - .help = did you mean to capture by reference instead? - -mir_transform_unused_var_assigned_only = variable `{$name}` is assigned to, but never used - .note = consider using `_{$name}` instead - -mir_transform_unused_var_underscore = if this is intentional, prefix it with an underscore - -mir_transform_unused_variable = unused variable: `{$name}` - -mir_transform_unused_variable_args_in_macro = `{$name}` is captured in macro and introduced a unused variable - -mir_transform_unused_variable_try_ignore = try ignoring the field - -mir_transform_unused_variable_typo = you might have meant to pattern match on the similarly named {$kind} `{$item_name}` diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index 8d28cb3ca003..1f65bd1ba69b 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -1,13 +1,13 @@ //! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its //! definition alone (irrespective of any specific caller). -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::DefId; +use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; -use rustc_span::sym; use crate::pass_manager::MirLint; @@ -41,7 +41,8 @@ pub(super) fn is_inline_valid_on_fn<'tcx>( def_id: DefId, ) -> Result<(), &'static str> { let codegen_attrs = tcx.codegen_fn_attrs(def_id); - if tcx.has_attr(def_id, sym::rustc_no_mir_inline) { + + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcNoMirInline) { return Err("#[rustc_no_mir_inline]"); } @@ -62,7 +63,7 @@ pub(super) fn is_inline_valid_on_fn<'tcx>( // but at this stage we don't know whether codegen knows the intrinsic, // so just conservatively don't inline it. This also ensures that we do not // accidentally inline the body of an intrinsic that *must* be overridden. - if tcx.has_attr(def_id, sym::rustc_intrinsic) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) { return Err("callee is an intrinsic"); } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b1ce0069b43a..bdc861e2cece 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -55,12 +55,10 @@ pub(super) fn extract_refined_covspans<'tcx>( } // Each pushed covspan should have the same context as the body span. - // If it somehow doesn't, discard the covspan, or panic in debug builds. + // If it somehow doesn't, discard the covspan. if !body_span.eq_ctxt(covspan_span) { - debug_assert!( - false, - "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}" - ); + // FIXME(Zalathar): Investigate how and why this is triggered + // by `tests/coverage/macros/context-mismatch-issue-147339.rs`. return false; } diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 71bdafa958ca..da133861617f 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -1,6 +1,7 @@ -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -43,7 +44,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } - if tcx.has_attr(def_id, sym::rustc_intrinsic) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) { // Intrinsic fallback bodies are always cross-crate inlineable. // To ensure that the MIR inliner doesn't cluelessly try to inline fallback // bodies even when the backend would implement something better, we stop @@ -157,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { // But intrinsics don't have a body that gets assigned to a CGU, so they are // ignored. if let Some((fn_def_id, _)) = func.const_fn_def() - && self.tcx.has_attr(fn_def_id, sym::rustc_intrinsic) + && find_attr!(tcx.get_all_attrs(fn_def_id), AttributeKind::RustcIntrinsic) { return; } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index d4c58f7fe05d..7421a55f2a79 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintDiagnostic, Subdiagnostic}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintDiagnostic, Subdiagnostic, msg}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::AssertKind; use rustc_middle::query::Key; @@ -8,8 +8,6 @@ use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - /// Emit diagnostic for calls to `#[inline(always)]`-annotated functions with a /// `#[target_feature]` attribute where the caller enables a different set of target features. pub(crate) fn emit_inline_always_target_feature_diagnostic<'a, 'tcx>( @@ -51,22 +49,22 @@ pub(crate) fn emit_inline_always_target_feature_diagnostic<'a, 'tcx>( } #[derive(LintDiagnostic)] -#[diag(mir_transform_unconditional_recursion)] -#[help] +#[diag("function cannot return without recursing")] +#[help("a `loop` may express intention better if this is on purpose")] pub(crate) struct UnconditionalRecursion { - #[label] + #[label("cannot return without recursing")] pub(crate) span: Span, - #[label(mir_transform_unconditional_recursion_call_site_label)] + #[label("recursive call site")] pub(crate) call_sites: Vec, } #[derive(Diagnostic)] -#[diag(mir_transform_force_inline_attr)] -#[note] +#[diag("`{$callee}` is incompatible with `#[rustc_force_inline]`")] +#[note("incompatible due to: {$reason}")] pub(crate) struct InvalidForceInline { #[primary_span] pub attr_span: Span, - #[label(mir_transform_callee)] + #[label("`{$callee}` defined here")] pub callee_span: Span, pub callee: String, pub reason: &'static str, @@ -74,28 +72,39 @@ pub(crate) struct InvalidForceInline { #[derive(LintDiagnostic)] pub(crate) enum ConstMutate { - #[diag(mir_transform_const_modify)] - #[note] + #[diag("attempting to modify a `const` item")] + #[note( + "each usage of a `const` item creates a new temporary; the original `const` item will not be modified" + )] Modify { - #[note(mir_transform_const_defined_here)] + #[note("`const` item defined here")] konst: Span, }, - #[diag(mir_transform_const_mut_borrow)] - #[note] - #[note(mir_transform_note2)] + #[diag("taking a mutable reference to a `const` item")] + #[note("each usage of a `const` item creates a new temporary")] + #[note("the mutable reference will refer to this temporary, not the original `const` item")] MutBorrow { - #[note(mir_transform_note3)] + #[note("mutable reference created due to call to this method")] method_call: Option, - #[note(mir_transform_const_defined_here)] + #[note("`const` item defined here")] konst: Span, }, } #[derive(Diagnostic)] -#[diag(mir_transform_unaligned_packed_ref, code = E0793)] -#[note] -#[note(mir_transform_note_ub)] -#[help] +#[diag("reference to field of packed {$ty_descr} is unaligned", code = E0793)] +#[note( + "this {$ty_descr} is {$align -> + [one] {\"\"} + *[other] {\"at most \"} + }{$align}-byte aligned, but the type of this field may require higher alignment" +)] +#[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)" +)] pub(crate) struct UnalignedPackedRef { #[primary_span] pub span: Span, @@ -104,7 +113,7 @@ pub(crate) struct UnalignedPackedRef { } #[derive(Diagnostic)] -#[diag(mir_transform_unknown_pass_name)] +#[diag("MIR pass `{$name}` is unknown and will be ignored")] pub(crate) struct UnknownPassName<'a> { pub(crate) name: &'a str, } @@ -123,8 +132,12 @@ pub(crate) enum AssertLintKind { impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint

{ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(match self.lint_kind { - AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow, - AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic, + AssertLintKind::ArithmeticOverflow => { + msg!("this arithmetic operation will overflow") + } + AssertLintKind::UnconditionalPanic => { + msg!("this operation will panic at runtime") + } }); let label = self.assert_kind.diagnostic_message(); self.assert_kind.add_args(&mut |name, value| { @@ -144,39 +157,53 @@ impl AssertLintKind { } #[derive(LintDiagnostic)] -#[diag(mir_transform_asm_unwind_call)] +#[diag("call to inline assembly that may unwind")] pub(crate) struct AsmUnwindCall { - #[label(mir_transform_asm_unwind_call)] + #[label("call to inline assembly that may unwind")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_transform_ffi_unwind_call)] +#[diag( + "call to {$foreign -> + [true] foreign function + *[false] function pointer + } with FFI-unwind ABI" +)] pub(crate) struct FfiUnwindCall { - #[label(mir_transform_ffi_unwind_call)] + #[label( + "call to {$foreign -> + [true] foreign function + *[false] function pointer + } with FFI-unwind ABI" + )] pub span: Span, pub foreign: bool, } #[derive(LintDiagnostic)] -#[diag(mir_transform_fn_item_ref)] +#[diag("taking a reference to a function item does not give a function pointer")] pub(crate) struct FnItemRef { - #[suggestion(code = "{sugg}", applicability = "unspecified")] + #[suggestion( + "cast `{$ident}` to obtain a function pointer", + code = "{sugg}", + applicability = "unspecified" + )] pub span: Span, pub sugg: String, pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_capture_maybe_capture_ref)] -#[help] +#[diag("value captured by `{$name}` is never read")] +#[help("did you mean to capture by reference instead?")] pub(crate) struct UnusedCaptureMaybeCaptureRef { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_var_assigned_only)] -#[note] +#[diag("variable `{$name}` is assigned to, but never used")] +#[note("consider using `_{$name}` instead")] pub(crate) struct UnusedVarAssignedOnly { pub name: Symbol, #[subdiagnostic] @@ -184,17 +211,20 @@ pub(crate) struct UnusedVarAssignedOnly { } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_assign)] +#[diag("value assigned to `{$name}` is never read")] pub(crate) struct UnusedAssign { pub name: Symbol, #[subdiagnostic] pub suggestion: Option, - #[help] + #[help("maybe it is overwritten before being read?")] pub help: bool, } #[derive(Subdiagnostic)] -#[multipart_suggestion(mir_transform_unused_assign_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding", + applicability = "maybe-incorrect" +)] pub(crate) struct UnusedAssignSuggestion { pub pre: &'static str, #[suggestion_part(code = "{pre}mut ")] @@ -208,14 +238,14 @@ pub(crate) struct UnusedAssignSuggestion { } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_assign_passed)] -#[help] +#[diag("value passed to `{$name}` is never read")] +#[help("maybe it is overwritten before being read?")] pub(crate) struct UnusedAssignPassed { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_variable)] +#[diag("unused variable: `{$name}`")] pub(crate) struct UnusedVariable { pub name: Symbol, #[subdiagnostic] @@ -226,10 +256,7 @@ pub(crate) struct UnusedVariable { #[derive(Subdiagnostic)] pub(crate) enum UnusedVariableSugg { - #[multipart_suggestion( - mir_transform_unused_variable_try_ignore, - applicability = "machine-applicable" - )] + #[multipart_suggestion("try ignoring the field", applicability = "machine-applicable")] TryIgnore { #[suggestion_part(code = "{name}: _")] shorthands: Vec, @@ -239,7 +266,7 @@ pub(crate) enum UnusedVariableSugg { }, #[multipart_suggestion( - mir_transform_unused_var_underscore, + "if this is intentional, prefix it with an underscore", applicability = "machine-applicable" )] TryPrefix { @@ -250,7 +277,7 @@ pub(crate) enum UnusedVariableSugg { typo: Option, }, - #[help(mir_transform_unused_variable_args_in_macro)] + #[help("`{$name}` is captured in macro and introduced a unused variable")] NoSugg { #[primary_span] span: Span, @@ -266,10 +293,10 @@ impl Subdiagnostic for UnusedVariableStringInterp { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label( self.lit, - crate::fluent_generated::mir_transform_maybe_string_interpolation, + msg!("you might have meant to use string interpolation in this string literal"), ); diag.multipart_suggestion( - crate::fluent_generated::mir_transform_string_interpolation_only_works, + msg!("string interpolation only works in `format!` invocations"), vec![ (self.lit.shrink_to_lo(), String::from("format!(")), (self.lit.shrink_to_hi(), String::from(")")), @@ -281,7 +308,7 @@ impl Subdiagnostic for UnusedVariableStringInterp { #[derive(Subdiagnostic)] #[multipart_suggestion( - mir_transform_unused_variable_typo, + "you might have meant to pattern match on the similarly named {$kind} `{$item_name}`", style = "verbose", applicability = "maybe-incorrect" )] @@ -306,12 +333,14 @@ pub(crate) struct MustNotSupend<'a, 'tcx> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::mir_transform_must_not_suspend); - diag.span_label(self.yield_sp, fluent::_subdiag::label); + diag.primary_message(msg!( + "{$pre}`{$def_path}`{$post} held across a suspend point, but should not be" + )); + diag.span_label(self.yield_sp, msg!("the value is held across this suspend point")); if let Some(reason) = self.reason { diag.subdiagnostic(reason); } - diag.span_help(self.src_sp, fluent::_subdiag::help); + diag.span_help(self.src_sp, msg!("consider using a block (`{\"{ ... }\"}`) to shrink the value's scope, ending before the suspend point")); diag.arg("pre", self.pre); diag.arg("def_path", self.tcx.def_path_str(self.def_id)); diag.arg("post", self.post); @@ -319,7 +348,7 @@ impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { } #[derive(Subdiagnostic)] -#[note(mir_transform_note)] +#[note("{$reason}")] pub(crate) struct MustNotSuspendReason { #[primary_span] pub span: Span, @@ -327,17 +356,17 @@ pub(crate) struct MustNotSuspendReason { } #[derive(Diagnostic)] -#[diag(mir_transform_force_inline)] -#[note] +#[diag("`{$callee}` could not be inlined into `{$caller}` but is required to be inlined")] +#[note("could not be inlined due to: {$reason}")] pub(crate) struct ForceInlineFailure { - #[label(mir_transform_caller)] + #[label("within `{$caller}`...")] pub caller_span: Span, - #[label(mir_transform_callee)] + #[label("`{$callee}` defined here")] pub callee_span: Span, - #[label(mir_transform_attr)] + #[label("annotation here")] pub attr_span: Span, #[primary_span] - #[label(mir_transform_call)] + #[label("...`{$callee}` called here")] pub call_span: Span, pub callee: String, pub caller: String, @@ -347,7 +376,7 @@ pub(crate) struct ForceInlineFailure { } #[derive(Subdiagnostic)] -#[note(mir_transform_force_inline_justification)] +#[note("`{$callee}` is required to be inlined to: {$sym}")] pub(crate) struct ForceInlineJustification { pub sym: Symbol, } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 820998eed100..6507a5194add 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -88,7 +88,6 @@ use std::borrow::Cow; use std::hash::{Hash, Hasher}; use either::Either; -use hashbrown::hash_table::{Entry, HashTable}; use itertools::Itertools as _; use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx}; use rustc_arena::DroplessArena; @@ -99,6 +98,7 @@ use rustc_const_eval::interpret::{ }; use rustc_data_structures::fx::FxHasher; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; use rustc_index::{IndexVec, newtype_index}; @@ -129,24 +129,18 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let maybe_loop_headers = loops::maybe_loop_headers(body); let arena = DroplessArena::default(); let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena); for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { - let opaque = state.new_opaque(body.local_decls[local].ty); + let opaque = state.new_argument(body.local_decls[local].ty); state.assign(local, opaque); } let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); for bb in reverse_postorder { - // N.B. With loops, reverse postorder cannot produce a valid topological order. - // A statement or terminator from inside the loop, that is not processed yet, may have performed an indirect write. - if maybe_loop_headers.contains(bb) { - state.invalidate_derefs(); - } let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; state.visit_basic_block_data(bb, data); } @@ -204,8 +198,9 @@ enum AddressBase { enum Value<'a, 'tcx> { // Root values. /// Used to represent values we know nothing about. - /// The `usize` is a counter incremented by `new_opaque`. Opaque(VnOpaque), + /// The value is a argument. + Argument(VnOpaque), /// Evaluated or unevaluated constant value. Constant { value: Const<'tcx>, @@ -290,7 +285,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { let value = value(VnOpaque); debug_assert!(match value { - Value::Opaque(_) | Value::Address { .. } => true, + Value::Opaque(_) | Value::Argument(_) | Value::Address { .. } => true, Value::Constant { disambiguator, .. } => disambiguator.is_some(), _ => false, }); @@ -350,12 +345,6 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { fn ty(&self, index: VnIndex) -> Ty<'tcx> { self.types[index] } - - /// Replace the value associated with `index` with an opaque value. - #[inline] - fn forget(&mut self, index: VnIndex) { - self.values[index] = Value::Opaque(VnOpaque); - } } struct VnState<'body, 'a, 'tcx> { @@ -374,8 +363,6 @@ struct VnState<'body, 'a, 'tcx> { /// - `Some(None)` are values for which computation has failed; /// - `Some(Some(op))` are successful computations. evaluated: IndexVec>>>, - /// Cache the deref values. - derefs: Vec, ssa: &'body SsaLocals, dominators: Dominators, reused_locals: DenseBitSet, @@ -408,7 +395,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: ValueSet::new(num_values), evaluated: IndexVec::with_capacity(num_values), - derefs: Vec::new(), ssa, dominators, reused_locals: DenseBitSet::new_empty(local_decls.len()), @@ -455,6 +441,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { index } + #[instrument(level = "trace", skip(self), ret)] + fn new_argument(&mut self, ty: Ty<'tcx>) -> VnIndex { + let index = self.insert_unique(ty, Value::Argument); + self.evaluated[index] = Some(None); + index + } + /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option { @@ -472,8 +465,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { // Skip the initial `Deref`. projection.next(); AddressBase::Deref(base) - } else { + } else if self.ssa.is_ssa(place.local) { + // Only propagate the pointer of the SSA local. AddressBase::Local(place.local) + } else { + return None; }; // Do not try evaluating inside `Index`, this has been done by `simplify_place_projection`. let projection = @@ -541,18 +537,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values))) } - fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { - let value = self.insert(ty, Value::Projection(value, ProjectionElem::Deref)); - self.derefs.push(value); - value - } - - fn invalidate_derefs(&mut self) { - for deref in std::mem::take(&mut self.derefs) { - self.values.forget(deref); - } - } - #[instrument(level = "trace", skip(self), ret)] fn eval_to_const_inner(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -566,7 +550,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = match self.get(value) { _ if ty.is_zst() => ImmTy::uninit(ty).into(), - Opaque(_) => return None, + Opaque(_) | Argument(_) => return None, // Keep runtime check constants as symbolic. RuntimeChecks(..) => return None, @@ -815,10 +799,24 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { { return Some((projection_ty, value)); } + // DO NOT reason the pointer value. + // We cannot unify two pointers that dereference same local, because they may + // have different lifetimes. + // ``` + // let b: &T = *a; + // ... `a` is allowed to be modified. `c` and `b` have different borrowing lifetime. + // Unifying them will extend the lifetime of `b`. + // let c: &T = *a; + // ``` + if projection_ty.ty.is_ref() { + return None; + } // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - return Some((projection_ty, self.insert_deref(projection_ty.ty, value))); + let deref = self + .insert(projection_ty.ty, Value::Projection(value, ProjectionElem::Deref)); + return Some((projection_ty, deref)); } else { return None; } @@ -1037,7 +1035,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = self.simplify_operand(op, location)?; Value::Repeat(op, amount) } - Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location), + Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); @@ -1148,7 +1146,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { fn simplify_aggregate( &mut self, - lhs: &Place<'tcx>, rvalue: &mut Rvalue<'tcx>, location: Location, ) -> Option { @@ -1231,12 +1228,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) { - // Allow introducing places with non-constant offsets, as those are still better than - // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be - // aliases resulting in overlapping assignments. - let allow_complex_projection = - lhs.projection[..].iter().all(PlaceElem::is_stable_offset); - if let Some(place) = self.try_as_place(value, location, allow_complex_projection) { + if let Some(place) = self.try_as_place(value, location, true) { self.reused_locals.insert(place.local); *rvalue = Rvalue::Use(Operand::Copy(place)); } @@ -1591,10 +1583,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { (Transmute, PtrToPtr) if self.pointers_have_same_metadata(from, to) => { Some(Transmute) } - // If would be legal to always do this, but we don't want to hide information + // It would be legal to always do this, but we don't want to hide information // from the backend that it'd otherwise be able to use for optimizations. (Transmute, Transmute) - if !self.type_may_have_niche_of_interest_to_backend(from) => + if !self.transmute_may_have_niche_of_interest_to_backend( + inner_from, from, to, + ) => { Some(Transmute) } @@ -1642,24 +1636,65 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } } - /// Returns `false` if we know for sure that this type has no interesting niche, - /// and thus we can skip transmuting through it without worrying. + /// Returns `false` if we're confident that the middle type doesn't have an + /// interesting niche so we can skip that step when transmuting. /// /// The backend will emit `assume`s when transmuting between types with niches, /// so we want to preserve `i32 -> char -> u32` so that that data is around, /// but it's fine to skip whole-range-is-value steps like `A -> u32 -> B`. - fn type_may_have_niche_of_interest_to_backend(&self, ty: Ty<'tcx>) -> bool { - let Ok(layout) = self.ecx.layout_of(ty) else { + fn transmute_may_have_niche_of_interest_to_backend( + &self, + from_ty: Ty<'tcx>, + middle_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + ) -> bool { + let Ok(middle_layout) = self.ecx.layout_of(middle_ty) else { // If it's too generic or something, then assume it might be interesting later. return true; }; - if layout.uninhabited { + if middle_layout.uninhabited { return true; } - match layout.backend_repr { - BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), + match middle_layout.backend_repr { + BackendRepr::Scalar(mid) => { + if mid.is_always_valid(&self.ecx) { + // With no niche it's never interesting, so don't bother + // looking at the layout of the other two types. + false + } else if let Ok(from_layout) = self.ecx.layout_of(from_ty) + && !from_layout.uninhabited + && from_layout.size == middle_layout.size + && let BackendRepr::Scalar(from_a) = from_layout.backend_repr + && let mid_range = mid.valid_range(&self.ecx) + && let from_range = from_a.valid_range(&self.ecx) + && mid_range.contains_range(from_range, middle_layout.size) + { + // The `from_range` is a (non-strict) subset of `mid_range` + // such as if we're doing `bool` -> `ascii::Char` -> `_`, + // where `from_range: 0..=1` and `mid_range: 0..=127`, + // and thus the middle doesn't tell us anything we don't + // already know from the initial type. + false + } else if let Ok(to_layout) = self.ecx.layout_of(to_ty) + && !to_layout.uninhabited + && to_layout.size == middle_layout.size + && let BackendRepr::Scalar(to_a) = to_layout.backend_repr + && let mid_range = mid.valid_range(&self.ecx) + && let to_range = to_a.valid_range(&self.ecx) + && mid_range.contains_range(to_range, middle_layout.size) + { + // The `to_range` is a (non-strict) subset of `mid_range` + // such as if we're doing `_` -> `ascii::Char` -> `bool`, + // where `mid_range: 0..=127` and `to_range: 0..=1`, + // and thus the middle doesn't tell us anything we don't + // already know from the final type. + false + } else { + true + } + } BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) } @@ -1847,6 +1882,17 @@ impl<'tcx> VnState<'_, '_, 'tcx> { && (allow_complex_projection || proj.is_stable_offset()) && let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc) { + if proj == PlaceElem::Deref { + // We can introduce a new dereference if the source value cannot be changed in the body. + // Dereferencing an immutable argument always gives the same value in the body. + match self.get(pointer) { + Value::Argument(_) + if let Some(Mutability::Not) = self.ty(pointer).ref_mutability() => {} + _ => { + return None; + } + } + } projection.push(proj); index = pointer; } else { @@ -1873,10 +1919,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); - if context.is_mutating_use() && place.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } self.super_place(place, context, location); } @@ -1906,11 +1948,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { } } - if lhs.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } - if let Some(local) = lhs.as_local() && self.ssa.is_ssa(local) && let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) @@ -1933,10 +1970,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { self.assign(local, opaque); } } - // Terminators that can write to memory may invalidate (nested) derefs. - if terminator.kind.can_write_to_memory() { - self.invalidate_derefs(); - } self.super_terminator(terminator, location); } } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index fa9ceb018dd5..84d642ea4ebc 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,8 +1,8 @@ //! Performs various peephole optimizations. use rustc_abi::ExternAbi; -use rustc_ast::attr; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{LangItem, find_attr}; use rustc_middle::bug; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -31,7 +31,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let preserve_ub_checks = - attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); + find_attr!(tcx.hir_krate_attrs(), AttributeKind::RustcPreserveUbChecks); if !preserve_ub_checks { SimplifyUbCheck { tcx }.visit_body(body); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 2f8c6b876398..bc2c6bd81aca 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(const_type_name)] #![feature(cow_is_borrowed)] @@ -91,20 +91,32 @@ macro_rules! declare_passes { )+ )* - static PASS_NAMES: LazyLock> = LazyLock::new(|| [ + static PASS_NAMES: LazyLock> = LazyLock::new(|| { + let mut set = FxIndexSet::default(); // Fake marker pass - "PreCodegen", + set.insert("PreCodegen"); $( $( - stringify!($pass_name), - $( - $( - $mod_name::$pass_name::$ident.name(), - )* - )? + set.extend(pass_names!($mod_name : $pass_name $( { $($ident),* } )? )); )+ )* - ].into_iter().collect()); + set + }); + }; +} + +macro_rules! pass_names { + // pass groups: only pass names inside are considered pass_names + ($mod_name:ident : $pass_group:ident { $($pass_name:ident),* $(,)? }) => { + [ + $( + $mod_name::$pass_group::$pass_name.name(), + )* + ] + }; + // lone pass names: stringify the struct or enum name + ($mod_name:ident : $pass_name:ident) => { + [stringify!($pass_name)] }; } @@ -201,8 +213,6 @@ declare_passes! { mod validate : Validator; } -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { coverage::query::provide(providers); ffi_unwind_calls::provide(&mut providers.queries); @@ -219,7 +229,6 @@ pub fn provide(providers: &mut Providers) { optimized_mir, check_liveness: liveness::check_liveness, is_mir_available, - is_ctfe_mir_available: is_mir_available, mir_callgraph_cyclic: inline::cycle::mir_callgraph_cyclic, mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 61c9bbe31239..2f733f54b26c 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use itertools::Itertools as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::Subdiagnostic; +use rustc_errors::{Subdiagnostic, msg}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::MixedBitSet; @@ -499,13 +499,17 @@ fn assign_observables_names( } #[derive(LintDiagnostic)] -#[diag(mir_transform_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] struct TailExprDropOrderLint<'a> { #[subdiagnostic] local_labels: Vec>, - #[label(mir_transform_drop_location)] + #[label( + "now the temporary value is dropped here, before the local variables in the block or statement" + )] drop_span: Option, - #[note(mir_transform_note_epilogue)] + #[note( + "most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages" + )] _epilogue: (), } @@ -527,19 +531,34 @@ impl Subdiagnostic for LocalLabel<'_> { diag.arg("is_generated_name", self.is_generated_name); diag.remove_arg("is_dropped_first_edition_2024"); diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); - let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local); + let msg = diag.eagerly_translate(msg!( + "{$is_generated_name -> + [true] this value will be stored in a temporary; let us call it `{$name}` + *[false] `{$name}` calls a custom destructor + }" + )); diag.span_label(self.span, msg); for dtor in self.destructors { dtor.add_to_diag(diag); } let msg = - diag.eagerly_translate(crate::fluent_generated::mir_transform_label_local_epilogue); + diag.eagerly_translate(msg!( + "{$is_dropped_first_edition_2024 -> + [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 + *[false] `{$name}` will be dropped later as of Edition 2024 + }" + )); diag.span_label(self.span, msg); } } #[derive(Subdiagnostic)] -#[note(mir_transform_tail_expr_dtor)] +#[note( + "{$dtor_kind -> + [dyn] `{$name}` may invoke a custom destructor because it contains a trait object + *[concrete] `{$name}` invokes this custom destructor + }" +)] struct DestructorLabel<'a> { #[primary_span] span: Span, diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 98dc054918eb..9bafee9f31c3 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1086,11 +1086,6 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { let Some((name, decl_span)) = self.checked_places.names[index] else { continue }; - // By convention, underscore-prefixed bindings are explicitly allowed to be unused. - if name.as_str().starts_with('_') { - continue; - } - let is_maybe_drop_guard = maybe_drop_guard( tcx, self.typing_env, @@ -1118,6 +1113,11 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { continue; }; + // By convention, underscore-prefixed bindings are allowed to be unused explicitly + if name.as_str().starts_with('_') { + break; + } + match kind { AccessKind::Assign => { let suggestion = annotate_mut_binding_to_immutable_binding( @@ -1243,9 +1243,12 @@ struct TransferFunction<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for TransferFunction<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { - // `ForLet(None)` fake read erroneously marks the just-assigned local as live. - // This defeats the purpose of the analysis for `let` bindings. - StatementKind::FakeRead(box (FakeReadCause::ForLet(None), _)) => return, + // `ForLet(None)` and `ForGuardBinding` fake reads erroneously mark the just-assigned + // locals as live. This defeats the purpose of the analysis for such bindings. + StatementKind::FakeRead(box ( + FakeReadCause::ForLet(None) | FakeReadCause::ForGuardBinding, + _, + )) => return, // Handle self-assignment by restricting the read/write they do. StatementKind::Assign(box (ref dest, ref rvalue)) if self.self_assignment.contains(&location) => diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 0829d52283ab..552c092ef7c4 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl deleted file mode 100644 index 9c791208c093..000000000000 --- a/compiler/rustc_monomorphize/messages.ftl +++ /dev/null @@ -1,82 +0,0 @@ -monomorphize_abi_error_disabled_vector_type = - this function {$is_call -> - [true] call - *[false] definition - } uses {$is_scalable -> - [true] scalable - *[false] SIMD - } vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call -> - [true] {" "}in the caller - *[false] {""} - } - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) - -monomorphize_abi_error_unsupported_unsized_parameter = - this function {$is_call -> - [true] call - *[false] definition - } uses unsized type `{$ty}` which is not supported with the chosen ABI - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = only rustic ABIs support unsized parameters - -monomorphize_abi_error_unsupported_vector_type = - this function {$is_call -> - [true] call - *[false] definition - } uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI - .label = function {$is_call -> - [true] called - *[false] defined - } here - -monomorphize_abi_required_target_feature = - this function {$is_call -> - [true] call - *[false] definition - } uses ABI "{$abi}" which requires the `{$required_feature}` target feature, which is not enabled{$is_call -> - [true] {" "}in the caller - *[false] {""} - } - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) - -monomorphize_couldnt_dump_mono_stats = - unexpected error occurred while dumping monomorphization stats: {$error} - -monomorphize_encountered_error_while_instantiating = - the above error was encountered while instantiating `{$kind} {$instance}` - -monomorphize_encountered_error_while_instantiating_global_asm = - the above error was encountered while instantiating `global_asm` - -monomorphize_large_assignments = - moving {$size} bytes - .label = value moved from here - .note = the current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -monomorphize_no_optimized_mir = - missing optimized MIR for `{$instance}` in the crate `{$crate_name}` - .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?) - -monomorphize_recursion_limit = - reached the recursion limit while instantiating `{$instance}` - .note = `{$def_path_str}` defined here - -monomorphize_start_not_found = using `fn main` requires the standard library - .help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` - -monomorphize_static_initializer_cyclic = static initializer forms a cycle involving `{$head}` - .label = part of this cycle - .note = cyclic static initializers are not supported for target `{$target}` - -monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 81d46e3b5b0d..4f6e2cc00516 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1002,11 +1002,12 @@ fn visit_instance_use<'tcx>( if tcx.should_codegen_locally(panic_instance) { output.push(create_fn_mono_item(tcx, panic_instance, source)); } - } else if !intrinsic.must_be_overridden { + } else if !intrinsic.must_be_overridden + && !tcx.sess.replaced_intrinsics.contains(&intrinsic.name) + { // Codegen the fallback body of intrinsics with fallback bodies. - // We explicitly skip this otherwise to ensure we get a linker error - // if anyone tries to call this intrinsic and the codegen backend did not - // override the implementation. + // We have to skip this otherwise as there's no body to codegen. + // We also skip intrinsics the backend handles, to reduce monomorphizations. let instance = ty::Instance::new_raw(instance.def_id(), instance.args); if tcx.should_codegen_locally(instance) { output.push(create_fn_mono_item(tcx, instance, source)); @@ -1084,7 +1085,9 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> return false; } - if !tcx.is_mir_available(def_id) { + // See comment in should_encode_mir in rustc_metadata for why we don't report + // an error for constructors. + if !tcx.is_mir_available(def_id) && !matches!(tcx.def_kind(def_id), DefKind::Ctor(..)) { tcx.dcx().emit_fatal(NoOptimizedMir { span: tcx.def_span(def_id), crate_name: tcx.crate_name(def_id.krate), diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 723649f22117..62a8743873bd 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -3,37 +3,41 @@ use rustc_middle::ty::{Instance, Ty}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(monomorphize_recursion_limit)] +#[diag("reached the recursion limit while instantiating `{$instance}`")] pub(crate) struct RecursionLimit<'tcx> { #[primary_span] pub span: Span, pub instance: Instance<'tcx>, - #[note] + #[note("`{$def_path_str}` defined here")] pub def_span: Span, pub def_path_str: String, } #[derive(Diagnostic)] -#[diag(monomorphize_no_optimized_mir)] +#[diag("missing optimized MIR for `{$instance}` in the crate `{$crate_name}`")] pub(crate) struct NoOptimizedMir { - #[note] + #[note( + "missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)" + )] pub span: Span, pub crate_name: Symbol, pub instance: String, } #[derive(LintDiagnostic)] -#[diag(monomorphize_large_assignments)] -#[note] +#[diag("moving {$size} bytes")] +#[note( + "the current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = \"...\"]`" +)] pub(crate) struct LargeAssignmentsLint { - #[label] + #[label("value moved from here")] pub span: Span, pub size: u64, pub limit: u64, } #[derive(Diagnostic)] -#[diag(monomorphize_symbol_already_defined)] +#[diag("symbol `{$symbol}` is already defined")] pub(crate) struct SymbolAlreadyDefined { #[primary_span] pub span: Option, @@ -41,13 +45,13 @@ pub(crate) struct SymbolAlreadyDefined { } #[derive(Diagnostic)] -#[diag(monomorphize_couldnt_dump_mono_stats)] +#[diag("unexpected error occurred while dumping monomorphization stats: {$error}")] pub(crate) struct CouldntDumpMonoStats { pub error: String, } #[derive(Diagnostic)] -#[diag(monomorphize_encountered_error_while_instantiating)] +#[diag("the above error was encountered while instantiating `{$kind} {$instance}`")] pub(crate) struct EncounteredErrorWhileInstantiating<'tcx> { #[primary_span] pub span: Span, @@ -56,23 +60,41 @@ pub(crate) struct EncounteredErrorWhileInstantiating<'tcx> { } #[derive(Diagnostic)] -#[diag(monomorphize_encountered_error_while_instantiating_global_asm)] +#[diag("the above error was encountered while instantiating `global_asm`")] pub(crate) struct EncounteredErrorWhileInstantiatingGlobalAsm { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(monomorphize_start_not_found)] -#[help] +#[diag("using `fn main` requires the standard library")] +#[help( + "use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`" +)] pub(crate) struct StartNotFound; #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_disabled_vector_type)] -#[help] +#[diag("this function {$is_call -> + [true] call + *[false] definition +} uses {$is_scalable -> + [true] scalable + *[false] SIMD +} vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call -> + [true] {\" \"}in the caller + *[false] {\"\"} +}")] +#[help( + "consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable=\"{$required_feature}\")]`)" +)] pub(crate) struct AbiErrorDisabledVectorType<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub required_feature: &'a str, pub ty: Ty<'a>, @@ -83,11 +105,21 @@ pub(crate) struct AbiErrorDisabledVectorType<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_unsupported_unsized_parameter)] -#[help] +#[diag( + "this function {$is_call -> + [true] call + *[false] definition + } uses unsized type `{$ty}` which is not supported with the chosen ABI" +)] +#[help("only rustic ABIs support unsized parameters")] pub(crate) struct AbiErrorUnsupportedUnsizedParameter<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub ty: Ty<'a>, /// Whether this is a problem at a call site or at a declaration. @@ -95,10 +127,20 @@ pub(crate) struct AbiErrorUnsupportedUnsizedParameter<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_unsupported_vector_type)] +#[diag( + "this function {$is_call -> + [true] call + *[false] definition + } uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI" +)] pub(crate) struct AbiErrorUnsupportedVectorType<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub ty: Ty<'a>, /// Whether this is a problem at a call site or at a declaration. @@ -106,11 +148,24 @@ pub(crate) struct AbiErrorUnsupportedVectorType<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_required_target_feature)] -#[help] +#[diag("this function {$is_call -> + [true] call + *[false] definition +} uses ABI \"{$abi}\" which requires the `{$required_feature}` target feature, which is not enabled{$is_call -> + [true] {\" \"}in the caller + *[false] {\"\"} +}")] +#[help( + "consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable=\"{$required_feature}\")]`)" +)] pub(crate) struct AbiRequiredTargetFeature<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub required_feature: &'a str, pub abi: &'a str, @@ -119,12 +174,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_static_initializer_cyclic)] -#[note] +#[diag("static initializer forms a cycle involving `{$head}`")] +#[note("cyclic static initializers are not supported for target `{$target}`")] pub(crate) struct StaticInitializerCyclic<'a> { #[primary_span] pub span: Span, - #[label] + #[label("part of this cycle")] pub labels: Vec, pub head: &'a str, pub target: &'a str, diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 30f6934bb937..51753563b67c 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -20,8 +20,6 @@ mod mono_checks; mod partitioning; mod util; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxtAt<'tcx>, source_ty: Ty<'tcx>, diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index a86230e9ab22..d8f4e0194507 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -99,7 +99,7 @@ use std::io::Write; use std::path::{Path, PathBuf}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_data_structures::sync; +use rustc_data_structures::sync::par_join; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::LangItem; use rustc_hir::attrs::{InlineAttr, Linkage}; @@ -1145,7 +1145,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio tcx.dcx().abort_if_errors(); let (codegen_units, _) = tcx.sess.time("partition_and_assert_distinct_symbols", || { - sync::join( + par_join( || { let mut codegen_units = partition(tcx, items.iter().copied(), &usage_map); codegen_units[0].make_primary(); diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 61a2dcd226b7..ce2be24adc58 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -3,7 +3,8 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike, - Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Interner, PlaceholderConst, PlaceholderType, TypeFlags, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, }; use crate::delegate::SolverDelegate; @@ -357,13 +358,13 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }, ty::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), + PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), ), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), + PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, @@ -513,17 +514,23 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => todo!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), - ), + CanonicalizeMode::Input { .. } => { + CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => { CanonicalVarKind::PlaceholderConst(placeholder) } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), - ), + CanonicalizeMode::Input { .. } => { + CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, // FIXME: See comment above -- we could fold the region separately or something. diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 96fea09013a1..1f64f09fe787 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -177,9 +177,9 @@ where } } ty::GenericArgKind::Const(c) => { - if let ty::ConstKind::Bound(index_kind, bv) = c.kind() { + if let ty::ConstKind::Bound(index_kind, bc) = c.kind() { assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical)); - opt_values[bv.var()] = Some(*original_value); + opt_values[bc.var()] = Some(*original_value); } } } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index c8016759f239..31fce0601697 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -3,8 +3,8 @@ use core::panic; use rustc_type_ir::data_structures::IndexMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, + TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; pub struct BoundVarReplacer<'a, Infcx, I = ::Interner> @@ -16,9 +16,9 @@ where // These three maps track the bound variable that were replaced by placeholders. It might be // nice to remove these since we already have the `kind` in the placeholder; we really just need // the `var` (but we *could* bring that into scope if we were to track them as we pass them). - mapped_regions: IndexMap, - mapped_types: IndexMap, - mapped_consts: IndexMap, + mapped_regions: IndexMap, ty::BoundRegion>, + mapped_types: IndexMap, ty::BoundTy>, + mapped_consts: IndexMap, ty::BoundConst>, // The current depth relative to *this* folding, *not* the entire normalization. In other words, // the depth of binders we've passed here. current_index: ty::DebruijnIndex, @@ -40,9 +40,9 @@ where value: T, ) -> ( T, - IndexMap, - IndexMap, - IndexMap, + IndexMap, ty::BoundRegion>, + IndexMap, ty::BoundTy>, + IndexMap, ty::BoundConst>, ) { let mut replacer = BoundVarReplacer { infcx, @@ -103,7 +103,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, br); + let p = PlaceholderRegion::new(universe, br); self.mapped_regions.insert(p, br); Region::new_placeholder(self.cx(), p) } @@ -126,7 +126,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, bound_ty); + let p = PlaceholderType::new(universe, bound_ty); self.mapped_types.insert(p, bound_ty); Ty::new_placeholder(self.cx(), p) } @@ -150,7 +150,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, bound_const); + let p = PlaceholderConst::new(universe, bound_const); self.mapped_consts.insert(p, bound_const); Const::new_placeholder(self.cx(), p) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 46312be5ea9a..eb6a1b51421c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -1,4 +1,4 @@ -use rustc_type_ir::{self as ty, Interner}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -14,7 +14,18 @@ where &mut self, goal: Goal>, ) -> QueryResult { - if let Some(normalized_const) = self.evaluate_const( + if self.typing_mode() == TypingMode::Coherence + && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA + { + // During coherence, OGCA consts should be normalized ambiguously + // because they are opaque but eventually resolved to a real value. + // We don't want two OGCAs that have the same value to be treated + // as distinct for coherence purposes. (Just like opaque types.) + // + // We can't rely on evaluate_const below because that particular wrapper + // treats too-generic consts as a successful evaluation. + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } else if let Some(normalized_const) = self.evaluate_const( goal.param_env, ty::UnevaluatedConst::new( goal.predicate.alias.def_id.try_into().unwrap(), diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 003841f3af3f..dd012a5146e6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -687,6 +687,9 @@ where /// /// because these impls overlap, and I'd rather not build a coherence hack for /// this harmless overlap. + /// + /// This trait is indirectly exposed on stable, so do *not* extend the set of types that + /// implement the trait without FCP! fn consider_builtin_bikeshed_guaranteed_no_drop_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index f0c84e07a56f..28a67ae12126 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" } 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_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl deleted file mode 100644 index 449d0b964fd4..000000000000 --- a/compiler/rustc_parse/messages.ftl +++ /dev/null @@ -1,1042 +0,0 @@ -parse_add_paren = try adding parentheses - -parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation -parse_ambiguous_range_pattern_suggestion = add parentheses to clarify the precedence - -parse_array_brackets_instead_of_braces = this is a block expression, not an array - .suggestion = to make an array, use square brackets instead of curly braces - -parse_array_index_offset_of = array indexing not supported in offset_of - -parse_asm_expected_comma = expected token: `,` - .label = expected `,` - -parse_asm_expected_other = expected operand, {$is_inline_asm -> - [false] options - *[true] clobber_abi, options - }, or additional template string - -parse_asm_expected_register_class_or_explicit_register = expected register class or explicit register - -parse_asm_expected_string_literal = expected string literal - .label = not a string literal - -parse_asm_non_abi = at least one abi must be provided as an argument to `clobber_abi` - -parse_asm_requires_template = requires at least a template string argument - -parse_asm_sym_no_path = expected a path for argument to `sym` - -parse_asm_underscore_input = _ cannot be used for input operands - -parse_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!` - .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it - -parse_assignment_else_not_allowed = ... else {"{"} ... {"}"} is not allowed - -parse_associated_static_item_not_allowed = associated `static` items are not allowed - -parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later - -parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Rust 2018 or later - -parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 - .label = to use `async fn`, switch to Rust 2018 or later - -parse_async_impl = `async` trait implementations are unsupported - -parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later - -parse_async_move_order_incorrect = the order of `move` and `async` is incorrect - .suggestion = try switching the order - -parse_async_use_block_in_2015 = `async use` blocks are only allowed in Rust 2018 or later - -parse_async_use_order_incorrect = the order of `use` and `async` is incorrect - .suggestion = try switching the order - -parse_at_dot_dot_in_struct_pattern = `@ ..` is not supported in struct patterns - .suggestion = bind to each field separately or, if you don't need them, just remove `{$ident} @` - -parse_at_in_struct_pattern = unexpected `@` in struct pattern - .note = struct patterns use `field: pattern` syntax to bind to fields - .help = consider replacing `new_name @ field_name` with `field_name: new_name` if that is what you intended - -parse_attr_after_generic = trailing attribute after generic parameter - .label = attributes must go before parameters - -parse_attr_without_generics = attribute without generic parameters - .label = attributes are only permitted when preceding parameters - -parse_attribute_on_empty_type = attributes cannot be applied here - .label = attributes are not allowed here - -parse_attribute_on_generic_arg = attributes cannot be applied to generic arguments - .label = attributes are not allowed here - .suggestion = remove attribute from here - -parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type - .label = attributes are not allowed here - -parse_attribute_on_type = attributes cannot be applied to types - .label = attributes are not allowed here - .suggestion = remove attribute from here - -parse_bad_assoc_type_bounds = bounds on associated types do not belong here - .label = belongs in `where` clause - -parse_bad_item_kind = {$descr} is not supported in {$ctx} - .help = consider moving the {$descr} out to a nearby module scope - -parse_bad_return_type_notation_output = - return type not allowed with return type notation - .suggestion = remove the return type - -parse_bare_cr = {$double_quotes -> - [true] bare CR not allowed in string, use `\r` instead - *[false] character constant must be escaped: `\r` - } - .escape = escape the character - -parse_bare_cr_in_raw_string = bare CR not allowed in raw string - -parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier - .label = there is not a well-defined meaning for a higher-ranked `{$polarity}` trait - -parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers - .label = place the `for<...>` binder before any modifiers - -parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases - -parse_box_not_pat = expected pattern, found {$descr} - .note = `box` is a reserved keyword - .suggestion = escape `box` to use it as an identifier - -parse_box_syntax_removed = `box_syntax` has been removed -parse_box_syntax_removed_suggestion = use `Box::new()` instead - -parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier - -parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime - -parse_catch_after_try = keyword `catch` cannot follow a `try` block - .help = try using `match` on the result of the `try` block instead - -parse_colon_as_semi = statements are terminated with a semicolon - .suggestion = use a semicolon instead - -parse_comma_after_base_struct = cannot use a comma after the base struct - .note = the base struct must always be the last field - .suggestion = remove this comma - -parse_comparison_interpreted_as_generic = - `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison - .label_args = interpreted as generic arguments - .label_comparison = not interpreted as comparison - .suggestion = try comparing the cast value - -parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained - .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments - .sugg_split_comparison = split the comparison into two - .sugg_parenthesize = parenthesize the comparison -parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable - .suggestion = initialize the variable - .help = if you meant to overwrite, remove the `let` binding - -parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments - .suggestion = enclose the `const` expression in braces - -parse_const_global_cannot_be_mutable = const globals cannot be mutable - .label = cannot be mutable - .suggestion = you might want to declare a static instead - -parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive - .suggestion = remove `let` - -parse_cr_doc_comment = bare CR not allowed in {$block -> - [true] block doc-comment - *[false] doc-comment -} - -parse_default_not_followed_by_item = `default` is not followed by an item - .label = the `default` qualifier - .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` - -parse_delegation_non_trait_impl_reuse = only trait impls can be reused - -parse_do_catch_syntax_removed = found removed `do catch` syntax - .note = following RFC #2388, the new non-placeholder syntax is `try` - .suggestion = replace with the new syntax - -parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything - .help = doc comments must come before what they document, if a comment was intended use `//` - .suggestion = missing comma here - -parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type - .label = doc comments are not allowed here - -parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}` - .suggestion = to omit remaining fields, use `..` - -parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed - .suggestion = use `..=` instead - -parse_dot_dot_range_attribute = attributes are not allowed on range expressions starting with `..` - -parse_dotdotdot = unexpected token: `...` - .suggest_exclusive_range = use `..` for an exclusive range - .suggest_inclusive_range = or `..=` for an inclusive range - -parse_dotdotdot_rest_pattern = unexpected `...` - .label = not a valid pattern - .suggestion = for a rest pattern, use `..` instead of `...` - .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -parse_dotdotdot_rest_type = unexpected `...` - .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -parse_double_colon_in_bound = expected `:` followed by trait or lifetime - .suggestion = use single colon - -parse_dyn_after_mut = `mut` must precede `dyn` - .suggestion = place `mut` before `dyn` - -parse_empty_exponent_float = expected at least one digit in exponent - -parse_empty_unicode_escape = empty unicode escape - .label = this escape must have at least 1 hex digit - -parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern - -parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive - .suggestion = replace `enum struct` with - -parse_eq_field_init = expected `:`, found `=` - .suggestion = replace equals symbol with a colon - -parse_escape_only_char = {$byte -> - [true] byte - *[false] character - } constant must be escaped: `{$escaped_msg}` - .escape = escape the character - -parse_expect_dotdot_not_dotdotdot = expected `..`, found `...` - .suggestion = use `..` to fill in the rest of the fields - -parse_expect_eq_instead_of_eqeq = expected `=`, found `==` - .suggestion = consider using `=` here - -parse_expect_label_found_ident = expected a label, found an identifier - .suggestion = labels start with a tick - -parse_expect_path = expected a path - -parse_expected_binding_left_of_at = left-hand side of `@` must be a binding - .label_lhs = interpreted as a pattern, not a binding - .label_rhs = also a pattern - .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x` - -parse_expected_builtin_ident = expected identifier after `builtin #` - -parse_expected_comma_after_pattern_field = expected `,` - -parse_expected_else_block = expected `{"{"}`, found {$first_tok} - .label = expected an `if` or a block after this `else` - .suggestion = add an `if` if this is the condition of a chained `else if` statement - -parse_expected_expression_found_let = expected expression, found `let` statement - .note = only supported directly in conditions of `if` and `while` expressions - .not_supported_or = `||` operators are not supported in let chain expressions - .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains - -parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn` - .suggestion = use `Fn` to refer to the trait - -parse_expected_identifier = expected identifier - -parse_expected_identifier_found_doc_comment = expected identifier, found doc comment -parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}` -parse_expected_identifier_found_keyword = expected identifier, found keyword -parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}` -parse_expected_identifier_found_metavar = expected identifier, found metavariable -# This one deliberately doesn't print a token. -parse_expected_identifier_found_metavar_str = expected identifier, found metavariable -parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier -parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}` -parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword -parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}` -parse_expected_identifier_found_str = expected identifier, found `{$token}` - -parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type - .suggestion = add `mut` or `const` here - -parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}` -parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}` -# This one deliberately doesn't print a token. -parse_expected_semi_found_metavar_str = expected `;`, found metavariable -parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}` -parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}` -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_expr_rarrow_call = `->` is not valid syntax for field accesses and method calls - .suggestion = try using `.` instead - .help = the `.` operator will automatically dereference the value, except if the value is a raw pointer - -parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements - .label = dash-separated idents are not valid - .suggestion = if the original crate name uses dashes you need to use underscores in the code - -parse_extern_item_cannot_be_const = extern items cannot be `const` - .suggestion = try using a static value - .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html - -parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement - -parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword - .suggestion = remove the extra `impl` - .note = this is parsed as an `impl Trait` type, but a trait is expected at this position - - -parse_field_expression_with_generic = field expressions cannot have generic arguments - -parse_float_literal_requires_integer_part = float literals must have an integer part - .suggestion = must have an integer part - -parse_float_literal_unsupported_base = {$base} float literal is not supported - -parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async` - .label = `async` because of this - .suggestion = remove the `async` qualifier - .note = allowed qualifiers are: `unsafe` and `extern` - -parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const` - .label = `const` because of this - .suggestion = remove the `const` qualifier - .note = allowed qualifiers are: `unsafe` and `extern` - -parse_fn_ptr_with_generics = function pointer types may not have generic parameters - .suggestion = consider moving the lifetime {$arity -> - [one] parameter - *[other] parameters - } to {$for_param_list_exists -> - [true] the - *[false] a - } `for` parameter list - -parse_fn_trait_missing_paren = `Fn` bounds require arguments in parentheses - .add_paren = add the missing parentheses - -parse_forgot_paren = perhaps you forgot parentheses? - -parse_found_expr_would_be_stmt = expected expression, found `{$token}` - .label = expected expression - -parse_frontmatter_extra_characters_after_close = extra characters after frontmatter close are not allowed -parse_frontmatter_invalid_close_preceding_whitespace = invalid preceding whitespace for frontmatter close - .note = frontmatter close should not be preceded by whitespace -parse_frontmatter_invalid_infostring = invalid infostring for frontmatter - .note = frontmatter infostrings must be a single identifier immediately following the opening -parse_frontmatter_invalid_opening_preceding_whitespace = invalid preceding whitespace for frontmatter opening - .note = frontmatter opening should not be preceded by whitespace -parse_frontmatter_length_mismatch = frontmatter close does not match the opening - .label_opening = the opening here has {$len_opening} dashes... - .label_close = ...while the close has {$len_close} dashes -parse_frontmatter_too_many_dashes = too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening} -parse_frontmatter_unclosed = unclosed frontmatter - .note = frontmatter opening here was not closed - -parse_function_body_equals_expr = function body cannot be `= expression;` - .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` - -parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax - -parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets - .suggestion = surround the type parameters with angle brackets - -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_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} - .label = this {$label} contains {$count -> - [one] an invisible - *[other] invisible - } unicode text flow control {$count -> - [one] codepoint - *[other] codepoints - } - .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen - .suggestion_remove = if their presence wasn't intentional, you can remove them - .suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them - .no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped} - -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 - -parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition - .add_then_block = add a block here - .condition_possibly_unfinished = this binary operation is possibly unfinished - -parse_in_in_typo = - expected iterable, found keyword `in` - .suggestion = remove the duplicated `in` - -parse_inappropriate_default = {$article} {$descr} cannot be `default` - .label = `default` because of this - .note = only associated `fn`, `const`, and `type` items can be `default` - -parse_inclusive_range_extra_equals = unexpected `=` after inclusive range - .suggestion_remove_eq = use `..=` instead - .note = inclusive ranges end with a single equals sign (`..=`) - -parse_inclusive_range_match_arrow = unexpected `>` after inclusive range - .label = this is parsed as an inclusive range `..=` - .suggestion = add a space between the pattern and `=>` - -parse_inclusive_range_no_end = inclusive range with no end - .suggestion_open_range = use `..` instead - .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - -parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds -parse_incorrect_parens_trait_bounds_sugg = fix the parentheses - -parse_incorrect_semicolon = - expected item, found `;` - .suggestion = remove this semicolon - .help = {$name} declarations are not followed by a semicolon - -parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter - .suggestion = move the modifiers on `self` to the type - -parse_incorrect_use_of_await = incorrect use of `await` - .parentheses_suggestion = `await` is not a method call, remove the parentheses - -parse_incorrect_use_of_await_postfix_suggestion = `await` is a postfix operation - -parse_incorrect_use_of_use = incorrect use of `use` - .parentheses_suggestion = `use` is not a method call, try removing the parentheses - -parse_incorrect_visibility_restriction = incorrect visibility restriction - .help = some possible visibility restrictions are: - `pub(crate)`: visible only on the current crate - `pub(super)`: visible only in the current module's parent - `pub(in path::to::module)`: visible only on the specified path - .suggestion = make this visible only to module `{$inner_str}` with `in` - -parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -parse_inner_attr_not_permitted = an inner attribute is not permitted in this context - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute - .label_attr = not permitted following an outer attribute - .label_prev_attr = previous outer attribute - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment - .label_attr = not permitted following an outer doc comment - .label_prev_doc_comment = previous doc comment - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_doc_comment_not_permitted = expected outer doc comment - .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items - .suggestion = you might have meant to write a regular 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_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 - -parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}` - .label = {parse_invalid_char_in_escape_msg} - -parse_invalid_char_in_escape_msg = invalid character in {$is_hex -> - [true] numeric character - *[false] unicode - } escape - - -parse_invalid_comparison_operator = invalid comparison operator `{$invalid}` - .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}` - .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering` - -parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed -parse_invalid_digit_literal = invalid digit for a base {$base} literal - -parse_invalid_dyn_keyword = invalid `dyn` keyword - .help = `dyn` is only needed at the start of a trait `+`-separated list - .suggestion = remove this keyword - -parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` -parse_invalid_identifier_with_leading_number = identifiers cannot start with a number - -parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid - .label = invalid suffix `{$suffix}` - -parse_invalid_logical_operator = `{$incorrect}` is not a logical operator - .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators - .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction - .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction - -parse_invalid_meta_item = expected unsuffixed literal, found {$descr} - .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - -parse_invalid_offset_of = offset_of expects dot-separated field and variant names - -parse_invalid_path_sep_in_fn_definition = invalid path separator in function definition - .suggestion = remove invalid path separator - -parse_invalid_unicode_escape = invalid unicode character escape - .label = invalid escape - .help = unicode escape must {$surrogate -> - [true] not be a surrogate - *[false] be at most 10FFFF - } - -parse_invalid_variable_declaration = - invalid variable declaration - -parse_keyword_label = labels cannot use keyword names - -parse_keyword_lifetime = - lifetimes cannot use keyword names - -parse_kw_bad_case = keyword `{$kw}` is written in the wrong case - .suggestion = write it in {$case} - -parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item} -parse_label_unexpected_token = unexpected token - -parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here - -parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression - -parse_leading_plus_not_supported = leading `+` is not supported - .label = unexpected `+` - .suggestion_remove_plus = try removing the `+` - -parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_` -parse_leading_underscore_unicode_escape_label = invalid start of unicode escape - -parse_left_arrow_operator = unexpected token: `<-` - .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-` - -parse_let_chain_pre_2024 = let chains are only allowed in Rust 2024 or later - -parse_lifetime_after_mut = lifetime must precede `mut` - .suggestion = place the lifetime before `mut` - -parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes - .suggestion = remove the lifetime annotation - .label = annotated with lifetime here - -parse_lifetime_in_eq_constraint = lifetimes are not permitted in this context - .label = lifetime is not allowed here - .context_label = this introduces an associated item binding - .help = if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}` - .colon_sugg = you might have meant to write a bound here - -parse_lone_slash = invalid trailing slash in literal - .label = {parse_lone_slash} - -parse_loop_else = `{$loop_kind}...else` loops are not supported - .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run - .loop_keyword = `else` is attached to this loop - -parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields - -parse_macro_expands_to_enum_variant = macros cannot expand to enum variants - -parse_macro_invocation_visibility = can't qualify macro invocation with `pub` - .suggestion = remove the visibility - .help = try adjusting the macro to put `{$vis}` inside the invocation - -parse_macro_invocation_with_qualified_path = macros cannot use qualified paths - -parse_macro_name_remove_bang = macro names aren't followed by a `!` - .suggestion = remove the `!` - -parse_macro_rules_missing_bang = expected `!` after `macro_rules` - .suggestion = add a `!` - -parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}` - .suggestion = try exporting the macro - -parse_malformed_loop_label = malformed loop label - .suggestion = use the correct loop label format - -parse_match_arm_body_without_braces = `match` arm body without braces - .label_statements = {$num_statements -> - [one] this statement is not surrounded by a body - *[other] these statements are not surrounded by a body - } - .label_arrow = while parsing the `match` arm starting here - .suggestion_add_braces = surround the {$num_statements -> - [one] statement - *[other] statements - } with a body - .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression - -parse_maybe_comparison = you might have meant to compare for equality - -parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` - .suggestion = replace `fn` with `impl` here - -parse_maybe_missing_let = you might have meant to continue the let-chain - -parse_maybe_recover_from_bad_qpath_stage_2 = - missing angle brackets in associated item path - .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 `+` - -parse_maybe_report_ambiguous_plus = - ambiguous `+` in a type - .suggestion = use parentheses to disambiguate - -parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}` - .label_unmatched = mismatched closing delimiter - .label_opening_candidate = closing delimiter possibly meant for this - .label_unclosed = unclosed delimiter - -parse_misplaced_return_type = place the return type after the function parameters - -parse_missing_comma_after_match_arm = expected `,` following `match` arm - .suggestion = missing a comma here to end this `match` arm - -parse_missing_const_type = missing type for `{$kind}` item - .suggestion = provide a type for the item - -parse_missing_enum_for_enum_definition = missing `enum` for enum definition - .suggestion = add `enum` here to parse `{$ident}` as an enum - -parse_missing_enum_or_struct_for_item_definition = missing `enum` or `struct` for enum or struct definition - -parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop - .suggestion = try adding an expression to the `for` loop - -parse_missing_fn_for_function_definition = missing `fn` for function definition - .suggestion = add `fn` here to parse `{$ident}` as a function - -parse_missing_fn_for_method_definition = missing `fn` for method definition - .suggestion = add `fn` here to parse `{$ident}` as a method - -parse_missing_fn_or_struct_for_item_definition = missing `fn` or `struct` for function or struct definition - .suggestion = if you meant to call a macro, try - .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier - -parse_missing_fn_params = missing parameters for function definition - .suggestion = add a parameter list - -parse_missing_for_in_trait_impl = missing `for` in a trait impl - .suggestion = add `for` here - -parse_missing_in_in_for_loop = missing `in` in `for` loop - .use_in = try using `in` here instead - .add_in = try adding `in` here - -parse_missing_let_before_mut = missing keyword -parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym} - .suggestion = add `+` - -parse_missing_semicolon_before_array = expected `;`, found `[` - .suggestion = consider adding `;` here - -parse_missing_struct_for_struct_definition = missing `struct` for struct definition - .suggestion = add `struct` here to parse `{$ident}` as a struct - -parse_missing_trait_in_trait_impl = missing trait in a trait impl - .suggestion_add_trait = add a trait here - .suggestion_remove_for = for an inherent impl, drop this `for` - -parse_misspelled_kw = {$is_incorrect_case -> - [true] write keyword `{$similar_kw}` in lowercase - *[false] there is a keyword `{$similar_kw}` with a similar name -} - -parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds - .suggestion = remove the `{$modifier}` - -parse_modifiers_and_polarity = `{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier - .label = there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait - -parse_more_than_one_char = character literal may only contain one codepoint - .followed_by = this `{$chr}` is followed by the combining {$len -> - [one] mark - *[other] marks - } `{$escaped_marks}` - .non_printing = there are non-printing characters, the full sequence is `{$escaped}` - .consider_normalized = consider using the normalized form `{$ch}` of this character - .remove_non = consider removing the non-printing characters - .use_double_quotes = if you meant to write a {$is_byte -> - [true] byte string - *[false] string - } literal, use double quotes - -parse_multiple_skipped_lines = multiple lines skipped by escaped newline - .label = skipping everything up to and including this point - -parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item - .label = previous `where` clause starts here - .suggestion = consider joining the two `where` clauses into one - -parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding - .suggestion = add `mut` to each binding -parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding - .suggestion = remove the `mut` prefix - -parse_need_plus_after_trait_object_lifetime = lifetimes must be followed by `+` to form a trait object type - .suggestion = consider adding a trait bound after the potential lifetime bound - -parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}` - .suggestion = consider creating a new `{$kw_str}` definition instead of nesting - -parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type - -parse_no_brace_unicode_escape = incorrect unicode escape sequence - .label = {parse_no_brace_unicode_escape} - .use_braces = format of unicode escape sequences uses braces - .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}` - -parse_no_digits_literal = no valid digits found for number - -parse_non_string_abi_literal = non-string ABI literal - .suggestion = specify the ABI with a string literal - -parse_nonterminal_expected_ident = expected ident, found `{$token}` -parse_nonterminal_expected_item_keyword = expected an item keyword -parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}` - -parse_nonterminal_expected_statement = expected a statement - -parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide - -parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern` - -parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` - -parse_nul_in_c_str = null characters in C string literals are not supported - -parse_or_in_let_chain = `||` operators are not supported in let chain conditions - -parse_or_pattern_not_allowed_in_fn_parameters = function parameters require top-level or-patterns in parentheses -parse_or_pattern_not_allowed_in_let_binding = `let` bindings require top-level or-patterns in parentheses - -parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them - -parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches - .branch_label = the attributes are attached to this branch - .ctx_label = the branch belongs to this `{$ctx}` - .suggestion = remove the attributes - -parse_overlong_unicode_escape = overlong unicode escape - .label = must have at most 6 hex digits - -parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments - .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters - .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly - -parse_path_double_colon = path separator must be a double colon - .suggestion = use a double colon instead - - -parse_path_found_attribute_in_params = `Trait(...)` syntax does not support attributes in parameters - .suggestion = remove the attributes - -parse_path_found_c_variadic_params = `Trait(...)` syntax does not support c_variadic parameters - .suggestion = remove the `...` - -parse_path_found_named_params = `Trait(...)` syntax does not support named parameters - .suggestion = remove the parameter name - -parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies - .suggestion = give this argument a name or use an underscore to ignore it - -parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@` - .label_pattern = pattern on the left, should be on the right - .label_binding = binding on the right, should be on the left - .suggestion = switch the order - -parse_question_mark_in_type = invalid `?` in type - .label = `?` is only allowed on expressions, not types - .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type - -parse_recover_import_as_use = expected item, found {$token_name} - .suggestion = items are imported using the `use` keyword - -parse_remove_let = expected pattern, found `let` - .suggestion = remove the unnecessary `let` keyword - -parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated - .suggestion = remove the additional `mut`s - -parse_require_colon_after_labeled_expression = labeled expression must be followed by `:` - .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them - .label = the label - .suggestion = add `:` after the label - -parse_reserved_multihash = reserved multi-hash token is forbidden - .note = sequences of two or more # are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here - -parse_reserved_string = invalid string literal - .note = unprefixed guarded string literals are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here - -parse_return_types_use_thin_arrow = return types are denoted using `->` - .suggestion = use `->` instead - -parse_self_argument_pointer = cannot pass `self` by raw pointer - .label = cannot pass `self` by raw pointer - -parse_self_param_not_first = unexpected `self` parameter in function - .label = must be the first parameter of an associated function - -parse_shift_interpreted_as_generic = - `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift - .label_args = interpreted as generic arguments - .label_comparison = not interpreted as shift - .suggestion = try shifting the cast value - -parse_single_colon_import_path = expected `::`, found `:` - .suggestion = use double colon - .note = import paths are delimited using `::` - -parse_static_with_generics = static items may not have generic parameters - -parse_struct_literal_body_without_path = - struct literal body without path - .suggestion = you might have forgotten to add the struct literal inside the block - -parse_struct_literal_body_without_path_late = - struct literal body without path - .label = struct name missing for struct literal - .suggestion = add the correct type - -parse_struct_literal_not_allowed_here = struct literals are not allowed here - .suggestion = surround the struct literal with parentheses - -parse_struct_literal_placeholder_path = - placeholder `_` is not allowed for the path in struct literals - .label = not allowed in struct literals - .suggestion = replace it with the correct type - -parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes - .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - -parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding - -parse_sugg_add_semi = add `;` here -parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style - -parse_sugg_change_this_to_semi = change this to `;` -parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier - -parse_sugg_remove_comma = remove this comma -parse_sugg_remove_leading_vert_in_pattern = remove the `|` -parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments - -parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses - -parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro - -parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses - -parse_switch_mut_let_order = - switch the order of `mut` and `let` - -parse_switch_ref_box_order = switch the order of `ref` and `box` - .suggestion = swap them - -parse_ternary_operator = Rust has no ternary operator - -parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator - .suggestion = use `!` to perform bitwise not - -parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num} - -parse_too_short_hex_escape = numeric character escape is too short - -parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern - -parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` -parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` - -parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name} - .because = {$modifier_name} because of this - .type = inherent impl for this type - .note = only trait implementations may be annotated with `{$modifier}` - -parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before - .suggestion = move `{$kw}` before the `for<...>` - -parse_unclosed_unicode_escape = unterminated unicode escape - .label = missing a closing `{"}"}` - .terminate = terminate the unicode escape - -parse_underscore_literal_suffix = underscore literal suffix is not allowed - -parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const` - .suggestion = the `const` keyword is only needed in the definition of the type - -parse_unexpected_const_param_declaration = unexpected `const` parameter declaration - .label = expected a `const` expression, not a parameter declaration - .suggestion = `const` parameters must be declared for the `impl` - -parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter - .label = lifetime parameters cannot have default values - -parse_unexpected_expr_in_pat = - expected {$is_bound -> - [true] a pattern range bound - *[false] a pattern - }, found an expression - - .label = not a pattern - .note = arbitrary expressions are not allowed in patterns: - -parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const` - -parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard - -parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard - -parse_unexpected_if_with_if = unexpected `if` in the condition expression - .suggestion = remove the `if` - -parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern - .suggestion = remove the lifetime - -parse_unexpected_paren_in_range_pat = range pattern bounds cannot have parentheses -parse_unexpected_paren_in_range_pat_sugg = remove these parentheses - -parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head - .suggestion = remove parentheses in `for` loop - -parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surrounding `match` arm pattern - .suggestion = remove parentheses surrounding the pattern - -parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters - .note = you cannot use `Self` as a generic parameter because it is reserved for associated items - -parse_unexpected_token_after_dot = unexpected token: {$actual} - -parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label - .suggestion_remove_label = consider removing the label - .suggestion_enclose_in_block = consider enclosing expression in a block - -parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier -parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not -parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not - -parse_unexpected_token_after_not_logical = use `!` to perform logical negation -parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name -parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}` -parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}` -# This one deliberately doesn't print a token. -parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar -parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}` - -parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}` -parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}` -parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter - .suggestion = remove the `||` - -parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern - .suggestion = use a single `|` to separate multiple alternative patterns - -parse_unicode_escape_in_byte = unicode escape in byte string - .label = {parse_unicode_escape_in_byte} - .help = unicode escape sequences cannot be used as a byte or in a byte string - -parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}` - -parse_unknown_prefix = prefix `{$prefix}` is unknown - .label = unknown prefix - .note = prefixed identifiers and literals are reserved since Rust 2021 - .suggestion_br = use `br` for a raw byte string - .suggestion_cr = use `cr` for a raw C-string - .suggestion_str = if you meant to write a string literal, use double quotes - .suggestion_whitespace = consider inserting whitespace here - -parse_unknown_start_of_token = unknown start of token: {$escaped} - .sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not - .sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not - .help_null = source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used - .help_invisible_char = invisible characters like '{$escaped}' are not usually visible in text editors - .note_repeats = character appears {$repeats -> - [one] once more - *[other] {$repeats} more times - } - -parse_unmatched_angle = unmatched angle {$plural -> - [true] brackets - *[false] bracket - } - .suggestion = remove extra angle {$plural -> - [true] brackets - *[false] bracket - } - -parse_unmatched_angle_brackets = {$num_extra_brackets -> - [one] unmatched angle bracket - *[other] unmatched angle brackets - } - .suggestion = {$num_extra_brackets -> - [one] remove extra angle bracket - *[other] remove extra angle brackets - } - - -parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped - .label = {parse_unskipped_whitespace} - -parse_use_empty_block_not_semi = expected { "`{}`" }, found `;` - .suggestion = try using { "`{}`" } instead - -parse_use_eq_instead = unexpected `==` - .suggestion = try using `=` instead - -parse_use_if_else = use an `if-else` expression instead - -parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable -parse_use_let_not_var = write `let` instead of `var` to introduce a new variable - -parse_varargs_without_pattern = missing pattern for `...` argument - .suggestion = name the argument, or use `_` to continue ignoring it - -parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item - .label = the visibility - .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}` - -parse_where_clause_before_const_body = where clauses are not allowed before const item bodies - .label = unexpected where clause - .name_label = while parsing this const item - .body_label = the item body - .suggestion = move the body before the where clause - -parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies - .label = unexpected where clause - .name_label = while parsing this tuple struct - .body_label = the struct body - .suggestion = move the body before the where clause - -parse_where_generics = generic parameters on `where` clauses are reserved for future use - .label = currently unsupported - -parse_zero_chars = empty character literal - .label = {parse_zero_chars} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 42327c7e343d..0d8d403625a7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,24 +3,21 @@ use std::borrow::Cow; use std::path::PathBuf; -use rustc_ast::token::Token; +use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, Token}; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, Subdiagnostic, SuggestionStyle, + Level, Subdiagnostic, SuggestionStyle, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; -use crate::parser::{ForbiddenLetReason, TokenDescription}; - #[derive(Diagnostic)] -#[diag(parse_maybe_report_ambiguous_plus)] +#[diag("ambiguous `+` in a type")] pub(crate) struct AmbiguousPlus { #[primary_span] pub span: Span, @@ -29,7 +26,7 @@ pub(crate) struct AmbiguousPlus { } #[derive(Diagnostic)] -#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)] +#[diag("expected a path on the left-hand side of `+`", code = E0178)] pub(crate) struct BadTypePlus { #[primary_span] pub span: Span, @@ -38,7 +35,7 @@ pub(crate) struct BadTypePlus { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")] +#[multipart_suggestion("try adding parentheses", applicability = "machine-applicable")] pub(crate) struct AddParen { #[suggestion_part(code = "(")] pub lo: Span, @@ -52,12 +49,12 @@ pub(crate) enum BadTypePlusSub { #[subdiagnostic] suggestion: AddParen, }, - #[label(parse_forgot_paren)] + #[label("perhaps you forgot parentheses?")] ForgotParen { #[primary_span] span: Span, }, - #[label(parse_expect_path)] + #[label("expected a path")] ExpectPath { #[primary_span] span: Span, @@ -65,7 +62,7 @@ pub(crate) enum BadTypePlusSub { } #[derive(Diagnostic)] -#[diag(parse_maybe_recover_from_bad_qpath_stage_2)] +#[diag("missing angle brackets in associated item path")] pub(crate) struct BadQPathStage2 { #[primary_span] pub span: Span, @@ -74,21 +71,24 @@ pub(crate) struct BadQPathStage2 { } #[derive(Diagnostic)] -#[diag(parse_trait_impl_modifier_in_inherent_impl)] -#[note] +#[diag("inherent impls cannot be {$modifier_name}")] +#[note("only trait implementations may be annotated with `{$modifier}`")] pub(crate) struct TraitImplModifierInInherentImpl { #[primary_span] pub span: Span, pub modifier: &'static str, pub modifier_name: &'static str, - #[label(parse_because)] + #[label("{$modifier_name} because of this")] pub modifier_span: Span, - #[label(parse_type)] + #[label("inherent impl for this type")] pub self_ty: Span, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "types that don't start with an identifier need to be surrounded with angle brackets in qualified paths", + applicability = "machine-applicable" +)] pub(crate) struct WrapType { #[suggestion_part(code = "<")] pub lo: Span, @@ -97,22 +97,27 @@ pub(crate) struct WrapType { } #[derive(Diagnostic)] -#[diag(parse_incorrect_semicolon)] +#[diag("expected item, found `;`")] pub(crate) struct IncorrectSemicolon<'a> { #[primary_span] - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove this semicolon", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub span: Span, - #[help] + #[help("{$name} declarations are not followed by a semicolon")] pub show_help: bool, pub name: &'a str, } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_await)] +#[diag("incorrect use of `await`")] pub(crate) struct IncorrectUseOfAwait { #[primary_span] #[suggestion( - parse_parentheses_suggestion, + "`await` is not a method call, remove the parentheses", style = "verbose", code = "", applicability = "machine-applicable" @@ -121,11 +126,11 @@ pub(crate) struct IncorrectUseOfAwait { } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_use)] +#[diag("incorrect use of `use`")] pub(crate) struct IncorrectUseOfUse { #[primary_span] #[suggestion( - parse_parentheses_suggestion, + "`use` is not a method call, try removing the parentheses", style = "verbose", code = "", applicability = "machine-applicable" @@ -134,10 +139,7 @@ pub(crate) struct IncorrectUseOfUse { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_incorrect_use_of_await_postfix_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("`await` is a postfix operation", applicability = "machine-applicable")] pub(crate) struct AwaitSuggestion { #[suggestion_part(code = "")] pub removal: Span, @@ -147,7 +149,7 @@ pub(crate) struct AwaitSuggestion { } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_await)] +#[diag("incorrect use of `await`")] pub(crate) struct IncorrectAwait { #[primary_span] pub span: Span, @@ -156,16 +158,21 @@ pub(crate) struct IncorrectAwait { } #[derive(Diagnostic)] -#[diag(parse_in_in_typo)] +#[diag("expected iterable, found keyword `in`")] pub(crate) struct InInTypo { #[primary_span] pub span: Span, - #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "remove the duplicated `in`", + code = "", + style = "verbose", + applicability = "machine-applicable" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_variable_declaration)] +#[diag("invalid variable declaration")] pub(crate) struct InvalidVariableDeclaration { #[primary_span] pub span: Span, @@ -176,28 +183,28 @@ pub(crate) struct InvalidVariableDeclaration { #[derive(Subdiagnostic)] pub(crate) enum InvalidVariableDeclarationSub { #[suggestion( - parse_switch_mut_let_order, + "switch the order of `mut` and `let`", style = "verbose", applicability = "maybe-incorrect", code = "let mut" )] SwitchMutLetOrder(#[primary_span] Span), #[suggestion( - parse_missing_let_before_mut, + "missing keyword", applicability = "machine-applicable", style = "verbose", code = "let mut" )] MissingLet(#[primary_span] Span), #[suggestion( - parse_use_let_not_auto, + "write `let` instead of `auto` to introduce a new variable", style = "verbose", applicability = "machine-applicable", code = "let" )] UseLetNotAuto(#[primary_span] Span), #[suggestion( - parse_use_let_not_var, + "write `let` instead of `var` to introduce a new variable", style = "verbose", applicability = "machine-applicable", code = "let" @@ -206,15 +213,20 @@ pub(crate) enum InvalidVariableDeclarationSub { } #[derive(Diagnostic)] -#[diag(parse_switch_ref_box_order)] +#[diag("switch the order of `ref` and `box`")] pub(crate) struct SwitchRefBoxOrder { #[primary_span] - #[suggestion(applicability = "machine-applicable", style = "verbose", code = "box ref")] + #[suggestion( + "swap them", + applicability = "machine-applicable", + style = "verbose", + code = "box ref" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_comparison_operator)] +#[diag("invalid comparison operator `{$invalid}`")] pub(crate) struct InvalidComparisonOperator { #[primary_span] pub span: Span, @@ -226,7 +238,7 @@ pub(crate) struct InvalidComparisonOperator { #[derive(Subdiagnostic)] pub(crate) enum InvalidComparisonOperatorSub { #[suggestion( - parse_use_instead, + "`{$invalid}` is not a valid comparison operator, use `{$correct}`", style = "verbose", applicability = "machine-applicable", code = "{correct}" @@ -237,13 +249,13 @@ pub(crate) enum InvalidComparisonOperatorSub { invalid: String, correct: String, }, - #[label(parse_spaceship_operator_invalid)] + #[label("`<=>` is not a valid comparison operator, use `std::cmp::Ordering`")] Spaceship(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_invalid_logical_operator)] -#[note] +#[diag("`{$incorrect}` is not a logical operator")] +#[note("unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators")] pub(crate) struct InvalidLogicalOperator { #[primary_span] pub span: Span, @@ -255,14 +267,14 @@ pub(crate) struct InvalidLogicalOperator { #[derive(Subdiagnostic)] pub(crate) enum InvalidLogicalOperatorSub { #[suggestion( - parse_use_amp_amp_for_conjunction, + "use `&&` to perform logical conjunction", style = "verbose", applicability = "machine-applicable", code = "&&" )] Conjunction(#[primary_span] Span), #[suggestion( - parse_use_pipe_pipe_for_disjunction, + "use `||` to perform logical disjunction", style = "verbose", applicability = "machine-applicable", code = "||" @@ -271,15 +283,20 @@ pub(crate) enum InvalidLogicalOperatorSub { } #[derive(Diagnostic)] -#[diag(parse_tilde_is_not_unary_operator)] +#[diag("`~` cannot be used as a unary operator")] pub(crate) struct TildeAsUnaryOperator( #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "!")] + #[suggestion( + "use `!` to perform bitwise not", + style = "verbose", + applicability = "machine-applicable", + code = "!" + )] pub Span, ); #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_not)] +#[diag("unexpected {$negated_desc} after identifier")] pub(crate) struct NotAsNegationOperator { #[primary_span] pub negated: Span, @@ -291,7 +308,7 @@ pub(crate) struct NotAsNegationOperator { #[derive(Subdiagnostic)] pub(crate) enum NotAsNegationOperatorSub { #[suggestion( - parse_unexpected_token_after_not_default, + "use `!` to perform logical negation or bitwise not", style = "verbose", applicability = "machine-applicable", code = "!" @@ -299,7 +316,7 @@ pub(crate) enum NotAsNegationOperatorSub { SuggestNotDefault(#[primary_span] Span), #[suggestion( - parse_unexpected_token_after_not_bitwise, + "use `!` to perform bitwise not", style = "verbose", applicability = "machine-applicable", code = "!" @@ -307,7 +324,7 @@ pub(crate) enum NotAsNegationOperatorSub { SuggestNotBitwise(#[primary_span] Span), #[suggestion( - parse_unexpected_token_after_not_logical, + "use `!` to perform logical negation", style = "verbose", applicability = "machine-applicable", code = "!" @@ -316,46 +333,59 @@ pub(crate) enum NotAsNegationOperatorSub { } #[derive(Diagnostic)] -#[diag(parse_malformed_loop_label)] +#[diag("malformed loop label")] pub(crate) struct MalformedLoopLabel { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "'", style = "verbose")] + #[suggestion( + "use the correct loop label format", + applicability = "machine-applicable", + code = "'", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_lifetime_in_borrow_expression)] +#[diag("borrow expressions cannot be annotated with lifetimes")] pub(crate) struct LifetimeInBorrowExpression { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] - #[label] + #[suggestion( + "remove the lifetime annotation", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] + #[label("annotated with lifetime here")] pub lifetime_span: Span, } #[derive(Diagnostic)] -#[diag(parse_field_expression_with_generic)] +#[diag("field expressions cannot have generic arguments")] pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_macro_invocation_with_qualified_path)] +#[diag("macros cannot use qualified paths")] pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_label)] +#[diag("expected `while`, `for`, `loop` or `{\"{\"}` after a label")] pub(crate) struct UnexpectedTokenAfterLabel { #[primary_span] - #[label(parse_unexpected_token_after_label)] + #[label("expected `while`, `for`, `loop` or `{\"{\"}` after a label")] pub span: Span, - #[suggestion(parse_suggestion_remove_label, style = "verbose", code = "")] + #[suggestion("consider removing the label", style = "verbose", code = "")] pub remove_label: Option, #[subdiagnostic] pub enclose_in_block: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_enclose_in_block, applicability = "machine-applicable")] +#[multipart_suggestion( + "consider enclosing expression in a block", + applicability = "machine-applicable" +)] pub(crate) struct UnexpectedTokenAfterLabelSugg { #[suggestion_part(code = "{{ ")] pub left: Span, @@ -364,66 +394,91 @@ pub(crate) struct UnexpectedTokenAfterLabelSugg { } #[derive(Diagnostic)] -#[diag(parse_require_colon_after_labeled_expression)] -#[note] +#[diag("labeled expression must be followed by `:`")] +#[note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")] pub(crate) struct RequireColonAfterLabeledExpression { #[primary_span] pub span: Span, - #[label] + #[label("the label")] pub label: Span, - #[suggestion(style = "verbose", applicability = "machine-applicable", code = ": ")] + #[suggestion( + "add `:` after the label", + style = "verbose", + applicability = "machine-applicable", + code = ": " + )] pub label_end: Span, } #[derive(Diagnostic)] -#[diag(parse_do_catch_syntax_removed)] -#[note] +#[diag("found removed `do catch` syntax")] +#[note("following RFC #2388, the new non-placeholder syntax is `try`")] pub(crate) struct DoCatchSyntaxRemoved { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "try", style = "verbose")] + #[suggestion( + "replace with the new syntax", + applicability = "machine-applicable", + code = "try", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_float_literal_requires_integer_part)] +#[diag("float literals must have an integer part")] pub(crate) struct FloatLiteralRequiresIntegerPart { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "0", style = "verbose")] + #[suggestion( + "must have an integer part", + applicability = "machine-applicable", + code = "0", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_semicolon_before_array)] +#[diag("expected `;`, found `[`")] pub(crate) struct MissingSemicolonBeforeArray { #[primary_span] pub open_delim: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = ";")] + #[suggestion( + "consider adding `;` here", + style = "verbose", + applicability = "maybe-incorrect", + code = ";" + )] pub semicolon: Span, } #[derive(Diagnostic)] -#[diag(parse_expect_dotdot_not_dotdotdot)] +#[diag("expected `..`, found `...`")] pub(crate) struct MissingDotDot { #[primary_span] pub token_span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")] + #[suggestion( + "use `..` to fill in the rest of the fields", + applicability = "maybe-incorrect", + code = "..", + style = "verbose" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_block_macro_segment)] +#[diag("cannot use a `block` macro fragment here")] pub(crate) struct InvalidBlockMacroSegment { #[primary_span] pub span: Span, - #[label] + #[label("the `block` fragment is within this context")] pub context: Span, #[subdiagnostic] pub wrap: WrapInExplicitBlock, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("wrap this in another block", applicability = "machine-applicable")] pub(crate) struct WrapInExplicitBlock { #[suggestion_part(code = "{{ ")] pub lo: Span, @@ -432,7 +487,7 @@ pub(crate) struct WrapInExplicitBlock { } #[derive(Diagnostic)] -#[diag(parse_if_expression_missing_then_block)] +#[diag("this `if` expression is missing a block after the condition")] pub(crate) struct IfExpressionMissingThenBlock { #[primary_span] pub if_span: Span, @@ -444,14 +499,14 @@ pub(crate) struct IfExpressionMissingThenBlock { #[derive(Subdiagnostic)] pub(crate) enum IfExpressionMissingThenBlockSub { - #[help(parse_condition_possibly_unfinished)] + #[help("this binary operation is possibly unfinished")] UnfinishedCondition(#[primary_span] Span), - #[help(parse_add_then_block)] + #[help("add a block here")] AddThenBlock(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_ternary_operator)] +#[diag("Rust has no ternary operator")] pub(crate) struct TernaryOperator { #[primary_span] pub span: Span, @@ -459,12 +514,16 @@ pub(crate) struct TernaryOperator { #[subdiagnostic] pub sugg: Option, /// Otherwise, just print the suggestion message - #[help(parse_use_if_else)] + #[help("use an `if-else` expression instead")] pub no_sugg: bool, } #[derive(Subdiagnostic, Copy, Clone)] -#[multipart_suggestion(parse_use_if_else, applicability = "maybe-incorrect", style = "verbose")] +#[multipart_suggestion( + "use an `if-else` expression instead", + applicability = "maybe-incorrect", + style = "verbose" +)] pub(crate) struct TernaryOperatorSuggestion { #[suggestion_part(code = "if ")] pub before_cond: Span, @@ -478,7 +537,7 @@ pub(crate) struct TernaryOperatorSuggestion { #[derive(Subdiagnostic)] #[suggestion( - parse_extra_if_in_let_else, + "remove the `if` if you meant to write a `let...else` statement", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -489,18 +548,20 @@ pub(crate) struct IfExpressionLetSomeSub { } #[derive(Diagnostic)] -#[diag(parse_if_expression_missing_condition)] +#[diag("missing condition for `if` expression")] pub(crate) struct IfExpressionMissingCondition { #[primary_span] - #[label(parse_condition_label)] + #[label("expected condition here")] pub if_span: Span, - #[label(parse_block_label)] + #[label( + "if this block is the condition of the `if` expression, then it must be followed by another block" + )] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_expression_found_let)] -#[note] +#[diag("expected expression, found `let` statement")] +#[note("only supported directly in conditions of `if` and `while` expressions")] pub(crate) struct ExpectedExpressionFoundLet { #[primary_span] pub span: Span, @@ -513,7 +574,25 @@ pub(crate) struct ExpectedExpressionFoundLet { } #[derive(Diagnostic)] -#[diag(parse_or_in_let_chain)] +#[diag("let-chain with missing `let`")] +pub(crate) struct LetChainMissingLet { + #[primary_span] + pub span: Span, + #[label("expected `let` expression, found assignment")] + pub label_span: Span, + #[label("let expression later in the condition")] + pub rhs_span: Span, + #[suggestion( + "add `let` before the expression", + applicability = "maybe-incorrect", + code = "let ", + style = "verbose" + )] + pub sug_span: Span, +} + +#[derive(Diagnostic)] +#[diag("`||` operators are not supported in let chain conditions")] pub(crate) struct OrInLetChain { #[primary_span] pub span: Span, @@ -521,7 +600,7 @@ pub(crate) struct OrInLetChain { #[derive(Subdiagnostic, Clone, Copy)] #[multipart_suggestion( - parse_maybe_missing_let, + "you might have meant to continue the let-chain", applicability = "maybe-incorrect", style = "verbose" )] @@ -532,7 +611,7 @@ pub(crate) struct MaybeMissingLet { #[derive(Subdiagnostic, Clone, Copy)] #[multipart_suggestion( - parse_maybe_comparison, + "you might have meant to compare for equality", applicability = "maybe-incorrect", style = "verbose" )] @@ -542,56 +621,71 @@ pub(crate) struct MaybeComparison { } #[derive(Diagnostic)] -#[diag(parse_expect_eq_instead_of_eqeq)] +#[diag("expected `=`, found `==`")] pub(crate) struct ExpectedEqForLetExpr { #[primary_span] pub span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "=", style = "verbose")] + #[suggestion( + "consider using `=` here", + applicability = "maybe-incorrect", + code = "=", + style = "verbose" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_else_block)] +#[diag("expected `{\"{\"}`, found {$first_tok}")] pub(crate) struct ExpectedElseBlock { #[primary_span] pub first_tok_span: Span, pub first_tok: String, - #[label] + #[label("expected an `if` or a block after this `else`")] pub else_span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "if ", style = "verbose")] + #[suggestion( + "add an `if` if this is the condition of a chained `else if` statement", + applicability = "maybe-incorrect", + code = "if ", + style = "verbose" + )] pub condition_start: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_struct_field)] +#[diag("expected one of `,`, `:`, or `{\"}\"}`, found `{$token}`")] pub(crate) struct ExpectedStructField { #[primary_span] - #[label] + #[label("expected one of `,`, `:`, or `{\"}\"}`")] pub span: Span, pub token: Token, - #[label(parse_ident_label)] + #[label("while parsing this struct field")] pub ident_span: Span, } #[derive(Diagnostic)] -#[diag(parse_outer_attribute_not_allowed_on_if_else)] +#[diag("outer attributes are not allowed on `if` and `else` branches")] pub(crate) struct OuterAttributeNotAllowedOnIfElse { #[primary_span] pub last: Span, - #[label(parse_branch_label)] + #[label("the attributes are attached to this branch")] pub branch_span: Span, - #[label(parse_ctx_label)] + #[label("the branch belongs to this `{$ctx}`")] pub ctx_span: Span, pub ctx: String, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + #[suggestion( + "remove the attributes", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] pub attributes: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_in_in_for_loop)] +#[diag("missing `in` in `for` loop")] pub(crate) struct MissingInInForLoop { #[primary_span] pub span: Span, @@ -603,20 +697,36 @@ pub(crate) struct MissingInInForLoop { pub(crate) enum MissingInInForLoopSub { // User wrote `for pat of expr {}` // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect - #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")] + #[suggestion( + "try using `in` here instead", + style = "verbose", + applicability = "maybe-incorrect", + code = "in" + )] InNotOf(#[primary_span] Span), // User wrote `for pat = expr {}` - #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")] + #[suggestion( + "try using `in` here instead", + style = "verbose", + applicability = "maybe-incorrect", + code = "in" + )] InNotEq(#[primary_span] Span), - #[suggestion(parse_add_in, style = "verbose", applicability = "maybe-incorrect", code = " in ")] + #[suggestion( + "try adding `in` here", + style = "verbose", + applicability = "maybe-incorrect", + code = " in " + )] AddIn(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_missing_expression_in_for_loop)] +#[diag("missing expression to iterate on in `for` loop")] pub(crate) struct MissingExpressionInForLoop { #[primary_span] #[suggestion( + "try adding an expression to the `for` loop", code = "/* expression */ ", applicability = "has-placeholders", style = "verbose" @@ -625,63 +735,80 @@ pub(crate) struct MissingExpressionInForLoop { } #[derive(Diagnostic)] -#[diag(parse_loop_else)] -#[note] +#[diag("`{$loop_kind}...else` loops are not supported")] +#[note( + "consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run" +)] pub(crate) struct LoopElseNotSupported { #[primary_span] pub span: Span, pub loop_kind: &'static str, - #[label(parse_loop_keyword)] + #[label("`else` is attached to this loop")] pub loop_kw: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_comma_after_match_arm)] +#[diag("expected `,` following `match` arm")] pub(crate) struct MissingCommaAfterMatchArm { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = ",", style = "verbose")] + #[suggestion( + "missing a comma here to end this `match` arm", + applicability = "machine-applicable", + code = ",", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_catch_after_try)] -#[help] +#[diag("keyword `catch` cannot follow a `try` block")] +#[help("try using `match` on the result of the `try` block instead")] pub(crate) struct CatchAfterTry { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_comma_after_base_struct)] -#[note] +#[diag("cannot use a comma after the base struct")] +#[note("the base struct must always be the last field")] pub(crate) struct CommaAfterBaseStruct { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this comma", + style = "verbose", + applicability = "machine-applicable", + code = "" + )] pub comma: Span, } #[derive(Diagnostic)] -#[diag(parse_eq_field_init)] +#[diag("expected `:`, found `=`")] pub(crate) struct EqFieldInit { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")] + #[suggestion( + "replace equals symbol with a colon", + applicability = "machine-applicable", + code = ":", + style = "verbose" + )] pub eq: Span, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot)] +#[diag("unexpected token: `...`")] pub(crate) struct DotDotDot { #[primary_span] #[suggestion( - parse_suggest_exclusive_range, + "use `..` for an exclusive range", applicability = "maybe-incorrect", code = "..", style = "verbose" )] #[suggestion( - parse_suggest_inclusive_range, + "or `..=` for an inclusive range", applicability = "maybe-incorrect", code = "..=", style = "verbose" @@ -690,67 +817,74 @@ pub(crate) struct DotDotDot { } #[derive(Diagnostic)] -#[diag(parse_left_arrow_operator)] +#[diag("unexpected token: `<-`")] pub(crate) struct LeftArrowOperator { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "< -", style = "verbose")] + #[suggestion( + "if you meant to write a comparison against a negative value, add a space in between `<` and `-`", + applicability = "maybe-incorrect", + code = "< -", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_remove_let)] +#[diag("expected pattern, found `let`")] pub(crate) struct RemoveLet { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + #[suggestion( + "remove the unnecessary `let` keyword", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_use_eq_instead)] +#[diag("unexpected `==`")] pub(crate) struct UseEqInstead { #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "=")] + #[suggestion( + "try using `=` instead", + style = "verbose", + applicability = "machine-applicable", + code = "=" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_use_empty_block_not_semi)] +#[diag("expected { \"`{}`\" }, found `;`")] pub(crate) struct UseEmptyBlockNotSemi { #[primary_span] - #[suggestion(style = "hidden", applicability = "machine-applicable", code = "{{}}")] + #[suggestion( + r#"try using { "`{}`" } instead"#, + style = "hidden", + applicability = "machine-applicable", + code = "{{}}" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_comparison_interpreted_as_generic)] +#[diag("`<` is interpreted as a start of generic arguments for `{$type}`, not a comparison")] pub(crate) struct ComparisonInterpretedAsGeneric { #[primary_span] - #[label(parse_label_comparison)] + #[label("not interpreted as comparison")] pub comparison: Span, pub r#type: Path, - #[label(parse_label_args)] + #[label("interpreted as generic arguments")] pub args: Span, #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, -} - -#[derive(Diagnostic)] -#[diag(parse_shift_interpreted_as_generic)] -pub(crate) struct ShiftInterpretedAsGeneric { - #[primary_span] - #[label(parse_label_comparison)] - pub shift: Span, - pub r#type: Path, - #[label(parse_label_args)] - pub args: Span, - #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, + pub suggestion: ComparisonInterpretedAsGenericSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] -pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { +#[multipart_suggestion("try comparing the cast value", applicability = "machine-applicable")] +pub(crate) struct ComparisonInterpretedAsGenericSugg { #[suggestion_part(code = "(")] pub left: Span, #[suggestion_part(code = ")")] @@ -758,10 +892,32 @@ pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { } #[derive(Diagnostic)] -#[diag(parse_found_expr_would_be_stmt)] +#[diag("`<<` is interpreted as a start of generic arguments for `{$type}`, not a shift")] +pub(crate) struct ShiftInterpretedAsGeneric { + #[primary_span] + #[label("not interpreted as shift")] + pub shift: Span, + pub r#type: Path, + #[label("interpreted as generic arguments")] + pub args: Span, + #[subdiagnostic] + pub suggestion: ShiftInterpretedAsGenericSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("try shifting the cast value", applicability = "machine-applicable")] +pub(crate) struct ShiftInterpretedAsGenericSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag("expected expression, found `{$token}`")] pub(crate) struct FoundExprWouldBeStmt { #[primary_span] - #[label] + #[label("expected expression")] pub span: Span, pub token: Token, #[subdiagnostic] @@ -769,74 +925,83 @@ pub(crate) struct FoundExprWouldBeStmt { } #[derive(Diagnostic)] -#[diag(parse_frontmatter_extra_characters_after_close)] +#[diag("extra characters after frontmatter close are not allowed")] pub(crate) struct FrontmatterExtraCharactersAfterClose { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_infostring)] -#[note] +#[diag("invalid infostring for frontmatter")] +#[note("frontmatter infostrings must be a single identifier immediately following the opening")] pub(crate) struct FrontmatterInvalidInfostring { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_opening_preceding_whitespace)] +#[diag("invalid preceding whitespace for frontmatter opening")] pub(crate) struct FrontmatterInvalidOpeningPrecedingWhitespace { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter opening should not be preceded by whitespace")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_unclosed)] +#[diag("unclosed frontmatter")] pub(crate) struct FrontmatterUnclosed { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter opening here was not closed")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_close_preceding_whitespace)] +#[diag("invalid preceding whitespace for frontmatter close")] pub(crate) struct FrontmatterInvalidClosingPrecedingWhitespace { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter close should not be preceded by whitespace")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_length_mismatch)] +#[diag("frontmatter close does not match the opening")] pub(crate) struct FrontmatterLengthMismatch { #[primary_span] pub span: Span, - #[label(parse_label_opening)] + #[label("the opening here has {$len_opening} dashes...")] pub opening: Span, - #[label(parse_label_close)] + #[label("...while the close has {$len_close} dashes")] pub close: Span, pub len_opening: usize, pub len_close: usize, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_too_many_dashes)] +#[diag( + "too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening}" +)] pub(crate) struct FrontmatterTooManyDashes { pub len_opening: usize, } #[derive(Diagnostic)] -#[diag(parse_leading_plus_not_supported)] +#[diag("bare CR not allowed in frontmatter")] +pub(crate) struct BareCrFrontmatter { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("leading `+` is not supported")] pub(crate) struct LeadingPlusNotSupported { #[primary_span] - #[label] + #[label("unexpected `+`")] pub span: Span, #[suggestion( - parse_suggestion_remove_plus, + "try removing the `+`", style = "verbose", code = "", applicability = "machine-applicable" @@ -847,7 +1012,7 @@ pub(crate) struct LeadingPlusNotSupported { } #[derive(Diagnostic)] -#[diag(parse_parentheses_with_struct_fields)] +#[diag("invalid `struct` delimiters or `fn` call arguments")] pub(crate) struct ParenthesesWithStructFields { #[primary_span] pub span: Span, @@ -859,7 +1024,10 @@ pub(crate) struct ParenthesesWithStructFields { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_braces_for_struct, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$type}` is a struct, use braces as delimiters", + applicability = "maybe-incorrect" +)] pub(crate) struct BracesForStructLiteral { #[suggestion_part(code = " {{ ")] pub first: Span, @@ -868,14 +1036,19 @@ pub(crate) struct BracesForStructLiteral { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_no_fields_for_fn, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$type}` is a function, use the arguments directly", + applicability = "maybe-incorrect" +)] pub(crate) struct NoFieldsForFnCall { #[suggestion_part(code = "")] pub fields: Vec, } #[derive(Diagnostic)] -#[diag(parse_labeled_loop_in_break)] +#[diag( + "parentheses are required around this expression to avoid confusion with a labeled break expression" +)] pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, @@ -886,7 +1059,7 @@ pub(crate) struct LabeledLoopInBreak { #[derive(Subdiagnostic)] pub(crate) enum WrapInParentheses { #[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, + "wrap the expression in parentheses", applicability = "machine-applicable" )] Expression { @@ -896,7 +1069,7 @@ pub(crate) enum WrapInParentheses { right: Span, }, #[multipart_suggestion( - parse_sugg_wrap_macro_in_parentheses, + "use parentheses instead of braces for this macro", applicability = "machine-applicable" )] MacroArgs { @@ -908,7 +1081,7 @@ pub(crate) enum WrapInParentheses { } #[derive(Diagnostic)] -#[diag(parse_array_brackets_instead_of_braces)] +#[diag("this is a block expression, not an array")] pub(crate) struct ArrayBracketsInsteadOfBraces { #[primary_span] pub span: Span, @@ -917,7 +1090,10 @@ pub(crate) struct ArrayBracketsInsteadOfBraces { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "to make an array, use square brackets instead of curly braces", + applicability = "maybe-incorrect" +)] pub(crate) struct ArrayBracketsInsteadOfBracesSugg { #[suggestion_part(code = "[")] pub left: Span, @@ -926,12 +1102,17 @@ pub(crate) struct ArrayBracketsInsteadOfBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_match_arm_body_without_braces)] +#[diag("`match` arm body without braces")] pub(crate) struct MatchArmBodyWithoutBraces { #[primary_span] - #[label(parse_label_statements)] + #[label( + "{$num_statements -> + [one] this statement is not surrounded by a body + *[other] these statements are not surrounded by a body + }" + )] pub statements: Span, - #[label(parse_label_arrow)] + #[label("while parsing the `match` arm starting here")] pub arrow: Span, pub num_statements: usize, #[subdiagnostic] @@ -939,12 +1120,12 @@ pub(crate) struct MatchArmBodyWithoutBraces { } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_extra_equals)] -#[note] +#[diag("unexpected `=` after inclusive range")] +#[note("inclusive ranges end with a single equals sign (`..=`)")] pub(crate) struct InclusiveRangeExtraEquals { #[primary_span] #[suggestion( - parse_suggestion_remove_eq, + "use `..=` instead", style = "verbose", code = "..=", applicability = "maybe-incorrect" @@ -953,24 +1134,29 @@ pub(crate) struct InclusiveRangeExtraEquals { } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_match_arrow)] +#[diag("unexpected `>` after inclusive range")] pub(crate) struct InclusiveRangeMatchArrow { #[primary_span] pub arrow: Span, - #[label] + #[label("this is parsed as an inclusive range `..=`")] pub span: Span, - #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")] + #[suggestion( + "add a space between the pattern and `=>`", + style = "verbose", + code = " ", + applicability = "machine-applicable" + )] pub after_pat: Span, } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_no_end, code = E0586)] -#[note] +#[diag("inclusive range with no end", code = E0586)] +#[note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")] pub(crate) struct InclusiveRangeNoEnd { #[primary_span] pub span: Span, #[suggestion( - parse_suggestion_open_range, + "use `..` instead", code = "", applicability = "machine-applicable", style = "verbose" @@ -980,7 +1166,13 @@ pub(crate) struct InclusiveRangeNoEnd { #[derive(Subdiagnostic)] pub(crate) enum MatchArmBodyWithoutBracesSugg { - #[multipart_suggestion(parse_suggestion_add_braces, applicability = "machine-applicable")] + #[multipart_suggestion( + "surround the {$num_statements -> + [one] statement + *[other] statements + } with a body", + applicability = "machine-applicable" + )] AddBraces { #[suggestion_part(code = "{{ ")] left: Span, @@ -988,7 +1180,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { right: Span, }, #[suggestion( - parse_suggestion_use_comma_not_semicolon, + "replace `;` with `,` to end a `match` arm expression", code = ",", applicability = "machine-applicable", style = "verbose" @@ -1000,7 +1192,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_struct_literal_not_allowed_here)] +#[diag("struct literals are not allowed here")] pub(crate) struct StructLiteralNotAllowedHere { #[primary_span] pub span: Span, @@ -1009,7 +1201,10 @@ pub(crate) struct StructLiteralNotAllowedHere { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the struct literal with parentheses", + applicability = "machine-applicable" +)] pub(crate) struct StructLiteralNotAllowedHereSugg { #[suggestion_part(code = "(")] pub left: Span, @@ -1018,80 +1213,105 @@ pub(crate) struct StructLiteralNotAllowedHereSugg { } #[derive(Diagnostic)] -#[diag(parse_invalid_literal_suffix_on_tuple_index)] +#[diag("suffixes on a tuple index are invalid")] pub(crate) struct InvalidLiteralSuffixOnTupleIndex { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] pub span: Span, pub suffix: Symbol, } #[derive(Diagnostic)] -#[diag(parse_non_string_abi_literal)] +#[diag("non-string ABI literal")] pub(crate) struct NonStringAbiLiteral { #[primary_span] - #[suggestion(code = "\"C\"", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "specify the ABI with a string literal", + code = "\"C\"", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_mismatched_closing_delimiter)] +#[diag("mismatched closing delimiter: `{$delimiter}`")] pub(crate) struct MismatchedClosingDelimiter { #[primary_span] pub spans: Vec, pub delimiter: String, - #[label(parse_label_unmatched)] + #[label("mismatched closing delimiter")] pub unmatched: Span, - #[label(parse_label_opening_candidate)] + #[label("closing delimiter possibly meant for this")] pub opening_candidate: Option, - #[label(parse_label_unclosed)] + #[label("unclosed delimiter")] pub unclosed: Option, } #[derive(Diagnostic)] -#[diag(parse_incorrect_visibility_restriction, code = E0704)] -#[help] +#[diag("incorrect visibility restriction", code = E0704)] +#[help( + "some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path" +)] pub(crate) struct IncorrectVisibilityRestriction { #[primary_span] - #[suggestion(code = "in {inner_str}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "make this visible only to module `{$inner_str}` with `in`", + code = "in {inner_str}", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub inner_str: String, } #[derive(Diagnostic)] -#[diag(parse_assignment_else_not_allowed)] +#[diag(" ... else {\"{\"} ... {\"}\"} is not allowed")] pub(crate) struct AssignmentElseNotAllowed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_statement_after_outer_attr)] +#[diag("expected statement after outer attribute")] pub(crate) struct ExpectedStatementAfterOuterAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_doc_comment_does_not_document_anything, code = E0585)] -#[help] +#[diag("found a documentation comment that doesn't document anything", code = E0585)] +#[help("doc comments must come before what they document, if a comment was intended use `//`")] pub(crate) struct DocCommentDoesNotDocumentAnything { #[primary_span] pub span: Span, - #[suggestion(code = ",", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "missing comma here", + code = ",", + applicability = "machine-applicable", + style = "verbose" + )] pub missing_comma: Option, } #[derive(Diagnostic)] -#[diag(parse_const_let_mutually_exclusive)] +#[diag("`const` and `let` are mutually exclusive")] pub(crate) struct ConstLetMutuallyExclusive { #[primary_span] - #[suggestion(code = "const", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove `let`", + code = "const", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_expression_in_let_else)] +#[diag("a `{$operator}` expression cannot be directly assigned in `let...else`")] pub(crate) struct InvalidExpressionInLetElse { #[primary_span] pub span: Span, @@ -1101,7 +1321,7 @@ pub(crate) struct InvalidExpressionInLetElse { } #[derive(Diagnostic)] -#[diag(parse_invalid_curly_in_let_else)] +#[diag("right curly brace `{\"}\"}` before `else` in a `let...else` statement not allowed")] pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, @@ -1110,25 +1330,32 @@ pub(crate) struct InvalidCurlyInLetElse { } #[derive(Diagnostic)] -#[diag(parse_compound_assignment_expression_in_let)] -#[help] +#[diag("can't reassign to an uninitialized variable")] +#[help("if you meant to overwrite, remove the `let` binding")] pub(crate) struct CompoundAssignmentExpressionInLet { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "initialize the variable", + style = "verbose", + code = "", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_suffixed_literal_in_attribute)] -#[help] +#[diag("suffixed literals are not allowed in attributes")] +#[help( + "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" +)] pub(crate) struct SuffixedLiteralInAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_meta_item)] +#[diag("expected unsuffixed literal, found {$descr}")] pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, @@ -1138,7 +1365,10 @@ pub(crate) struct InvalidMetaItem { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the identifier with quotation marks to make it into a string literal", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[suggestion_part(code = "\"")] pub before: Span, @@ -1148,7 +1378,7 @@ pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_escape_identifier, + "escape `{$ident_name}` to use it as an identifier", style = "verbose", applicability = "maybe-incorrect", code = "r#" @@ -1161,7 +1391,7 @@ pub(crate) struct SuggEscapeIdentifier { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_remove_comma, + "remove this comma", applicability = "machine-applicable", code = "", style = "verbose" @@ -1173,7 +1403,7 @@ pub(crate) struct SuggRemoveComma { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_add_let_for_stmt, + "you might have meant to introduce a new binding", style = "verbose", applicability = "maybe-incorrect", code = "let " @@ -1185,17 +1415,17 @@ pub(crate) struct SuggAddMissingLetStmt { #[derive(Subdiagnostic)] pub(crate) enum ExpectedIdentifierFound { - #[label(parse_expected_identifier_found_reserved_identifier)] + #[label("expected identifier, found reserved identifier")] ReservedIdentifier(#[primary_span] Span), - #[label(parse_expected_identifier_found_keyword)] + #[label("expected identifier, found keyword")] Keyword(#[primary_span] Span), - #[label(parse_expected_identifier_found_reserved_keyword)] + #[label("expected identifier, found reserved keyword")] ReservedKeyword(#[primary_span] Span), - #[label(parse_expected_identifier_found_doc_comment)] + #[label("expected identifier, found doc comment")] DocComment(#[primary_span] Span), - #[label(parse_expected_identifier_found_metavar)] + #[label("expected identifier, found metavariable")] MetaVar(#[primary_span] Span), - #[label(parse_expected_identifier)] + #[label("expected identifier")] Other(#[primary_span] Span), } @@ -1233,22 +1463,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_identifier_found_reserved_identifier_str + msg!("expected identifier, found reserved identifier `{$token}`") } Some(TokenDescription::Keyword) => { - fluent::parse_expected_identifier_found_keyword_str + msg!("expected identifier, found keyword `{$token}`") } Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_identifier_found_reserved_keyword_str + msg!("expected identifier, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - fluent::parse_expected_identifier_found_doc_comment_str + msg!("expected identifier, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - fluent::parse_expected_identifier_found_metavar_str + msg!("expected identifier, found metavariable") } - None => fluent::parse_expected_identifier_found_str, + None => msg!("expected identifier, found `{$token}`"), }, ); diag.span(self.span); @@ -1275,7 +1505,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { } #[derive(Subdiagnostic)] -#[help(parse_invalid_identifier_with_leading_number)] +#[help("identifiers cannot start with a number")] pub(crate) struct HelpIdentifierStartsWithNumber { #[primary_span] pub num_span: Span, @@ -1300,20 +1530,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_semi_found_reserved_identifier_str + msg!("expected `;`, found reserved identifier `{$token}`") + } + Some(TokenDescription::Keyword) => { + msg!("expected `;`, found keyword `{$token}`") } - Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_semi_found_reserved_keyword_str + msg!("expected `;`, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - fluent::parse_expected_semi_found_doc_comment_str + msg!("expected `;`, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - fluent::parse_expected_semi_found_metavar_str + msg!("expected `;`, found metavariable") } - None => fluent::parse_expected_semi_found_str, + None => msg!("expected `;`, found `{$token}`"), }, ); diag.span(self.span); @@ -1322,7 +1554,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { } if let Some(unexpected_token_label) = self.unexpected_token_label { - diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token); + diag.span_label(unexpected_token_label, msg!("unexpected token")); } self.sugg.add_to_diag(&mut diag); @@ -1334,23 +1566,18 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { #[derive(Subdiagnostic)] pub(crate) enum ExpectedSemiSugg { #[suggestion( - parse_sugg_change_this_to_semi, + "change this to `;`", code = ";", applicability = "machine-applicable", style = "short" )] ChangeToSemi(#[primary_span] Span), - #[suggestion( - parse_sugg_add_semi, - code = ";", - applicability = "machine-applicable", - style = "short" - )] + #[suggestion("add `;` here", code = ";", applicability = "machine-applicable", style = "short")] AddSemi(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_struct_literal_body_without_path)] +#[diag("struct literal body without path")] pub(crate) struct StructLiteralBodyWithoutPath { #[primary_span] pub span: Span, @@ -1359,7 +1586,10 @@ pub(crate) struct StructLiteralBodyWithoutPath { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "has-placeholders")] +#[multipart_suggestion( + "you might have forgotten to add the struct literal inside the block", + applicability = "has-placeholders" +)] pub(crate) struct StructLiteralBodyWithoutPathSugg { #[suggestion_part(code = "{{ SomeStruct ")] pub before: Span, @@ -1368,16 +1598,29 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg { } #[derive(Diagnostic)] -#[diag(parse_unmatched_angle_brackets)] +#[diag( + "{$num_extra_brackets -> + [one] unmatched angle bracket + *[other] unmatched angle brackets + }" +)] pub(crate) struct UnmatchedAngleBrackets { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "{$num_extra_brackets -> + [one] remove extra angle bracket + *[other] remove extra angle brackets + }", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub num_extra_brackets: usize, } #[derive(Diagnostic)] -#[diag(parse_generic_parameters_without_angle_brackets)] +#[diag("generic parameters without surrounding angle brackets")] pub(crate) struct GenericParamsWithoutAngleBrackets { #[primary_span] pub span: Span, @@ -1386,7 +1629,10 @@ pub(crate) struct GenericParamsWithoutAngleBrackets { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the type parameters with angle brackets", + applicability = "machine-applicable" +)] pub(crate) struct GenericParamsWithoutAngleBracketsSugg { #[suggestion_part(code = "<")] pub left: Span, @@ -1395,19 +1641,19 @@ pub(crate) struct GenericParamsWithoutAngleBracketsSugg { } #[derive(Diagnostic)] -#[diag(parse_comparison_operators_cannot_be_chained)] +#[diag("comparison operators cannot be chained")] pub(crate) struct ComparisonOperatorsCannotBeChained { #[primary_span] pub span: Vec, #[suggestion( - parse_sugg_turbofish_syntax, + "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments", style = "verbose", code = "::", applicability = "maybe-incorrect" )] pub suggest_turbofish: Option, - #[help(parse_sugg_turbofish_syntax)] - #[help(parse_sugg_parentheses_for_function_args)] + #[help("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments")] + #[help("or use `(...)` if you meant to specify fn arguments")] pub help_turbofish: bool, #[subdiagnostic] pub chaining_sugg: Option, @@ -1416,7 +1662,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained { #[derive(Subdiagnostic)] pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { #[suggestion( - parse_sugg_split_comparison, + "split the comparison into two", style = "verbose", code = " && {middle_term}", applicability = "maybe-incorrect" @@ -1426,7 +1672,7 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { span: Span, middle_term: String, }, - #[multipart_suggestion(parse_sugg_parenthesize, applicability = "maybe-incorrect")] + #[multipart_suggestion("parenthesize the comparison", applicability = "maybe-incorrect")] Parenthesize { #[suggestion_part(code = "(")] left: Span, @@ -1436,17 +1682,20 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { } #[derive(Diagnostic)] -#[diag(parse_question_mark_in_type)] +#[diag("invalid `?` in type")] pub(crate) struct QuestionMarkInType { #[primary_span] - #[label] + #[label("`?` is only allowed on expressions, not types")] pub span: Span, #[subdiagnostic] pub sugg: QuestionMarkInTypeSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "if you meant to express that the type might not contain a value, use the `Option` wrapper type", + applicability = "machine-applicable" +)] pub(crate) struct QuestionMarkInTypeSugg { #[suggestion_part(code = "Option<")] pub left: Span, @@ -1455,7 +1704,7 @@ pub(crate) struct QuestionMarkInTypeSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_parentheses_in_for_head)] +#[diag("unexpected parentheses surrounding `for` loop head")] pub(crate) struct ParenthesesInForHead { #[primary_span] pub span: Vec, @@ -1464,7 +1713,7 @@ pub(crate) struct ParenthesesInForHead { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("remove parentheses in `for` loop", applicability = "machine-applicable")] pub(crate) struct ParenthesesInForHeadSugg { #[suggestion_part(code = " ")] pub left: Span, @@ -1473,7 +1722,7 @@ pub(crate) struct ParenthesesInForHeadSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_parentheses_in_match_arm_pattern)] +#[diag("unexpected parentheses surrounding `match` arm pattern")] pub(crate) struct ParenthesesInMatchPat { #[primary_span] pub span: Vec, @@ -1482,7 +1731,10 @@ pub(crate) struct ParenthesesInMatchPat { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "remove parentheses surrounding the pattern", + applicability = "machine-applicable" +)] pub(crate) struct ParenthesesInMatchPatSugg { #[suggestion_part(code = "")] pub left: Span, @@ -1491,67 +1743,82 @@ pub(crate) struct ParenthesesInMatchPatSugg { } #[derive(Diagnostic)] -#[diag(parse_doc_comment_on_param_type)] +#[diag("documentation comments cannot be applied to a function parameter's type")] pub(crate) struct DocCommentOnParamType { #[primary_span] - #[label] + #[label("doc comments are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_param_type)] +#[diag("attributes cannot be applied to a function parameter's type")] pub(crate) struct AttributeOnParamType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_type)] +#[diag("attributes cannot be applied to types")] pub(crate) struct AttributeOnType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove attribute from here", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub fix_span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_generic_arg)] +#[diag("attributes cannot be applied to generic arguments")] pub(crate) struct AttributeOnGenericArg { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove attribute from here", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub fix_span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_empty_type)] +#[diag("attributes cannot be applied here")] pub(crate) struct AttributeOnEmptyType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_pattern_method_param_without_body, code = E0642)] +#[diag("patterns aren't allowed in methods without bodies", code = E0642)] pub(crate) struct PatternMethodParamWithoutBody { #[primary_span] - #[suggestion(code = "_", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "give this argument a name or use an underscore to ignore it", + code = "_", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_self_param_not_first)] +#[diag("unexpected `self` parameter in function")] pub(crate) struct SelfParamNotFirst { #[primary_span] - #[label] + #[label("must be the first parameter of an associated function")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_const_generic_without_braces)] +#[diag("expressions must be enclosed in braces to be used as const generic arguments")] pub(crate) struct ConstGenericWithoutBraces { #[primary_span] pub span: Span, @@ -1560,7 +1827,10 @@ pub(crate) struct ConstGenericWithoutBraces { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "enclose the `const` expression in braces", + applicability = "machine-applicable" +)] pub(crate) struct ConstGenericWithoutBracesSugg { #[suggestion_part(code = "{{ ")] pub left: Span, @@ -1569,10 +1839,10 @@ pub(crate) struct ConstGenericWithoutBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_const_param_declaration)] +#[diag("unexpected `const` parameter declaration")] pub(crate) struct UnexpectedConstParamDeclaration { #[primary_span] - #[label] + #[label("expected a `const` expression, not a parameter declaration")] pub span: Span, #[subdiagnostic] pub sugg: Option, @@ -1580,7 +1850,10 @@ pub(crate) struct UnexpectedConstParamDeclaration { #[derive(Subdiagnostic)] pub(crate) enum UnexpectedConstParamDeclarationSugg { - #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion( + "`const` parameters must be declared for the `impl`", + applicability = "machine-applicable" + )] AddParam { #[suggestion_part(code = "<{snippet}>")] impl_generics: Span, @@ -1589,7 +1862,10 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg { snippet: String, ident: String, }, - #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion( + "`const` parameters must be declared for the `impl`", + applicability = "machine-applicable" + )] AppendParam { #[suggestion_part(code = ", {snippet}")] impl_generics_end: Span, @@ -1601,41 +1877,61 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_const_in_generic_param)] +#[diag("expected lifetime, type, or constant, found keyword `const`")] pub(crate) struct UnexpectedConstInGenericParam { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "the `const` keyword is only needed in the definition of the type", + style = "verbose", + code = "", + applicability = "maybe-incorrect" + )] pub to_remove: Option, } #[derive(Diagnostic)] -#[diag(parse_async_move_order_incorrect)] +#[diag("the order of `move` and `async` is incorrect")] pub(crate) struct AsyncMoveOrderIncorrect { #[primary_span] - #[suggestion(style = "verbose", code = "async move", applicability = "maybe-incorrect")] + #[suggestion( + "try switching the order", + style = "verbose", + code = "async move", + applicability = "maybe-incorrect" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_use_order_incorrect)] +#[diag("the order of `use` and `async` is incorrect")] pub(crate) struct AsyncUseOrderIncorrect { #[primary_span] - #[suggestion(style = "verbose", code = "async use", applicability = "maybe-incorrect")] + #[suggestion( + "try switching the order", + style = "verbose", + code = "async use", + applicability = "maybe-incorrect" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_double_colon_in_bound)] +#[diag("expected `:` followed by trait or lifetime")] pub(crate) struct DoubleColonInBound { #[primary_span] pub span: Span, - #[suggestion(code = ": ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use single colon", + code = ": ", + applicability = "machine-applicable", + style = "verbose" + )] pub between: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_ptr_with_generics)] +#[diag("function pointer types may not have generic parameters")] pub(crate) struct FnPtrWithGenerics { #[primary_span] pub span: Span, @@ -1645,7 +1941,7 @@ pub(crate) struct FnPtrWithGenerics { #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_misplaced_return_type, + "place the return type after the function parameters", style = "verbose", applicability = "maybe-incorrect" )] @@ -1658,7 +1954,16 @@ pub(crate) struct MisplacedReturnType { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider moving the lifetime {$arity -> + [one] parameter + *[other] parameters + } to {$for_param_list_exists -> + [true] the + *[false] a + } `for` parameter list", + applicability = "maybe-incorrect" +)] pub(crate) struct FnPtrWithGenericsSugg { #[suggestion_part(code = "{snippet}")] pub left: Span, @@ -1675,10 +1980,10 @@ pub(crate) struct FnTraitMissingParen { impl Subdiagnostic for FnTraitMissingParen { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); + diag.span_label(self.span, msg!("`Fn` bounds require arguments in parentheses")); diag.span_suggestion_short( self.span.shrink_to_hi(), - crate::fluent_generated::parse_add_paren, + msg!("try adding parentheses"), "()", Applicability::MachineApplicable, ); @@ -1686,95 +1991,128 @@ impl Subdiagnostic for FnTraitMissingParen { } #[derive(Diagnostic)] -#[diag(parse_unexpected_if_with_if)] +#[diag("unexpected `if` in the condition expression")] pub(crate) struct UnexpectedIfWithIf( #[primary_span] - #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")] + #[suggestion( + "remove the `if`", + applicability = "machine-applicable", + code = " ", + style = "verbose" + )] pub Span, ); #[derive(Diagnostic)] -#[diag(parse_maybe_fn_typo_with_impl)] +#[diag("you might have meant to write `impl` instead of `fn`")] pub(crate) struct FnTypoWithImpl { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")] + #[suggestion( + "replace `fn` with `impl` here", + applicability = "maybe-incorrect", + code = "impl", + style = "verbose" + )] pub fn_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_fn_path_found_fn_keyword)] +#[diag("expected identifier, found keyword `fn`")] pub(crate) struct ExpectedFnPathFoundFnKeyword { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")] + #[suggestion( + "use `Fn` to refer to the trait", + applicability = "machine-applicable", + code = "Fn", + style = "verbose" + )] pub fn_token_span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_named_params)] +#[diag("`Trait(...)` syntax does not support named parameters")] pub(crate) struct FnPathFoundNamedParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the parameter name", applicability = "machine-applicable", code = "")] pub named_param_span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_c_variadic_params)] +#[diag("`Trait(...)` syntax does not support c_variadic parameters")] pub(crate) struct PathFoundCVariadicParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the `...`", applicability = "machine-applicable", code = "")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_attribute_in_params)] +#[diag("`Trait(...)` syntax does not support attributes in parameters")] pub(crate) struct PathFoundAttributeInParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the attributes", applicability = "machine-applicable", code = "")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_double_colon)] +#[diag("path separator must be a double colon")] pub(crate) struct PathSingleColon { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")] + #[suggestion( + "use a double colon instead", + applicability = "machine-applicable", + code = ":", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_path_double_colon)] +#[diag("path separator must be a double colon")] pub(crate) struct PathTripleColon { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "", style = "verbose")] + #[suggestion( + "use a double colon instead", + applicability = "maybe-incorrect", + code = "", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_colon_as_semi)] +#[diag("statements are terminated with a semicolon")] pub(crate) struct ColonAsSemi { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = ";", style = "verbose")] + #[suggestion( + "use a semicolon instead", + applicability = "machine-applicable", + code = ";", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_clause_before_tuple_struct_body)] +#[diag("where clauses are not allowed before tuple struct bodies")] pub(crate) struct WhereClauseBeforeTupleStructBody { #[primary_span] - #[label] + #[label("unexpected where clause")] pub span: Span, - #[label(parse_name_label)] + #[label("while parsing this tuple struct")] pub name: Span, - #[label(parse_body_label)] + #[label("the struct body")] pub body: Span, #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the body before the where clause", + applicability = "machine-applicable" +)] pub(crate) struct WhereClauseBeforeTupleStructBodySugg { #[suggestion_part(code = "{snippet}")] pub left: Span, @@ -1784,38 +2122,38 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg { } #[derive(Diagnostic)] -#[diag(parse_async_fn_in_2015, code = E0670)] +#[diag("`async fn` is not permitted in Rust 2015", code = E0670)] pub(crate) struct AsyncFnIn2015 { #[primary_span] - #[label] + #[label("to use `async fn`, switch to Rust 2018 or later")] pub span: Span, #[subdiagnostic] pub help: HelpUseLatestEdition, } #[derive(Subdiagnostic)] -#[label(parse_async_block_in_2015)] +#[label("`async` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_move_block_in_2015)] +#[diag("`async move` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncMoveBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_use_block_in_2015)] +#[diag("`async use` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncUseBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_bound_modifier_in_2015)] +#[diag("`async` trait bounds are only allowed in Rust 2018 or later")] pub(crate) struct AsyncBoundModifierIn2015 { #[primary_span] pub span: Span, @@ -1824,22 +2162,22 @@ pub(crate) struct AsyncBoundModifierIn2015 { } #[derive(Diagnostic)] -#[diag(parse_let_chain_pre_2024)] +#[diag("let chains are only allowed in Rust 2024 or later")] pub(crate) struct LetChainPre2024 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_self_argument_pointer)] +#[diag("cannot pass `self` by raw pointer")] pub(crate) struct SelfArgumentPointer { #[primary_span] - #[label] + #[label("cannot pass `self` by raw pointer")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_dot)] +#[diag("unexpected token: {$actual}")] pub(crate) struct UnexpectedTokenAfterDot { #[primary_span] pub span: Span, @@ -1847,64 +2185,84 @@ pub(crate) struct UnexpectedTokenAfterDot { } #[derive(Diagnostic)] -#[diag(parse_visibility_not_followed_by_item)] -#[help] +#[diag("visibility `{$vis}` is not followed by an item")] +#[help("you likely meant to define an item, e.g., `{$vis} fn foo() {\"{}\"}`")] pub(crate) struct VisibilityNotFollowedByItem { #[primary_span] - #[label] + #[label("the visibility")] pub span: Span, pub vis: Visibility, } #[derive(Diagnostic)] -#[diag(parse_default_not_followed_by_item)] -#[note] +#[diag("`default` is not followed by an item")] +#[note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")] pub(crate) struct DefaultNotFollowedByItem { #[primary_span] - #[label] + #[label("the `default` qualifier")] pub span: Span, } #[derive(Diagnostic)] pub(crate) enum MissingKeywordForItemDefinition { - #[diag(parse_missing_enum_for_enum_definition)] + #[diag("missing `enum` for enum definition")] Enum { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "enum ")] + #[suggestion( + "add `enum` here to parse `{$ident}` as an enum", + style = "verbose", + applicability = "maybe-incorrect", + code = "enum " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_enum_or_struct_for_item_definition)] + #[diag("missing `enum` or `struct` for enum or struct definition")] EnumOrStruct { #[primary_span] span: Span, }, - #[diag(parse_missing_struct_for_struct_definition)] + #[diag("missing `struct` for struct definition")] Struct { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "struct ")] + #[suggestion( + "add `struct` here to parse `{$ident}` as a struct", + style = "verbose", + applicability = "maybe-incorrect", + code = "struct " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_for_function_definition)] + #[diag("missing `fn` for function definition")] Function { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "fn ")] + #[suggestion( + "add `fn` here to parse `{$ident}` as a function", + style = "verbose", + applicability = "maybe-incorrect", + code = "fn " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_for_method_definition)] + #[diag("missing `fn` for method definition")] Method { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "fn ")] + #[suggestion( + "add `fn` here to parse `{$ident}` as a method", + style = "verbose", + applicability = "maybe-incorrect", + code = "fn " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_or_struct_for_item_definition)] + #[diag("missing `fn` or `struct` for function or struct definition")] Ambiguous { #[primary_span] span: Span, @@ -1916,7 +2274,7 @@ pub(crate) enum MissingKeywordForItemDefinition { #[derive(Subdiagnostic)] pub(crate) enum AmbiguousMissingKwForItemSub { #[suggestion( - parse_suggestion, + "if you meant to call a macro, try", applicability = "maybe-incorrect", code = "{snippet}!", style = "verbose" @@ -1926,39 +2284,51 @@ pub(crate) enum AmbiguousMissingKwForItemSub { span: Span, snippet: String, }, - #[help(parse_help)] + #[help( + "if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier" + )] HelpMacro, } #[derive(Diagnostic)] -#[diag(parse_missing_fn_params)] +#[diag("missing parameters for function definition")] pub(crate) struct MissingFnParams { #[primary_span] - #[suggestion(code = "()", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add a parameter list", + code = "()", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_path_sep_in_fn_definition)] +#[diag("invalid path separator in function definition")] pub(crate) struct InvalidPathSepInFnDefinition { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove invalid path separator", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_trait_in_trait_impl)] +#[diag("missing trait in a trait impl")] pub(crate) struct MissingTraitInTraitImpl { #[primary_span] #[suggestion( - parse_suggestion_add_trait, + "add a trait here", code = " Trait ", applicability = "has-placeholders", style = "verbose" )] pub span: Span, #[suggestion( - parse_suggestion_remove_for, + "for an inherent impl, drop this `for`", code = "", applicability = "maybe-incorrect", style = "verbose" @@ -1967,102 +2337,130 @@ pub(crate) struct MissingTraitInTraitImpl { } #[derive(Diagnostic)] -#[diag(parse_missing_for_in_trait_impl)] +#[diag("missing `for` in a trait impl")] pub(crate) struct MissingForInTraitImpl { #[primary_span] - #[suggestion(style = "verbose", code = " for ", applicability = "machine-applicable")] + #[suggestion( + "add `for` here", + style = "verbose", + code = " for ", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_trait_in_trait_impl_found_type)] +#[diag("expected a trait, found type")] pub(crate) struct ExpectedTraitInTraitImplFoundType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_extra_impl_keyword_in_trait_impl)] +#[diag("unexpected `impl` keyword")] pub(crate) struct ExtraImplKeywordInTraitImpl { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "remove the extra `impl`", + code = "", + applicability = "maybe-incorrect", + style = "short" + )] pub extra_impl_kw: Span, - #[note] + #[note("this is parsed as an `impl Trait` type, but a trait is expected at this position")] pub impl_trait_span: Span, } #[derive(Diagnostic)] -#[diag(parse_bounds_not_allowed_on_trait_aliases)] +#[diag("bounds are not allowed on trait aliases")] pub(crate) struct BoundsNotAllowedOnTraitAliases { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_auto)] +#[diag("trait aliases cannot be `auto`")] pub(crate) struct TraitAliasCannotBeAuto { #[primary_span] - #[label(parse_trait_alias_cannot_be_auto)] + #[label("trait aliases cannot be `auto`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_unsafe)] +#[diag("trait aliases cannot be `unsafe`")] pub(crate) struct TraitAliasCannotBeUnsafe { #[primary_span] - #[label(parse_trait_alias_cannot_be_unsafe)] + #[label("trait aliases cannot be `unsafe`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_associated_static_item_not_allowed)] +#[diag("associated `static` items are not allowed")] pub(crate) struct AssociatedStaticItemNotAllowed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_extern_crate_name_with_dashes)] +#[diag("crate name using dashes are not valid in `extern crate` statements")] pub(crate) struct ExternCrateNameWithDashes { #[primary_span] - #[label] + #[label("dash-separated idents are not valid")] pub span: Span, #[subdiagnostic] pub sugg: ExternCrateNameWithDashesSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "if the original crate name uses dashes you need to use underscores in the code", + applicability = "machine-applicable" +)] pub(crate) struct ExternCrateNameWithDashesSugg { #[suggestion_part(code = "_")] pub dashes: Vec, } #[derive(Diagnostic)] -#[diag(parse_extern_item_cannot_be_const)] -#[note] +#[diag("extern items cannot be `const`")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct ExternItemCannotBeConst { #[primary_span] pub ident_span: Span, - #[suggestion(code = "static ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "try using a static value", + code = "static ", + applicability = "machine-applicable", + style = "verbose" + )] pub const_span: Option, } #[derive(Diagnostic)] -#[diag(parse_const_global_cannot_be_mutable)] +#[diag("const globals cannot be mutable")] pub(crate) struct ConstGlobalCannotBeMutable { #[primary_span] - #[label] + #[label("cannot be mutable")] pub ident_span: Span, - #[suggestion(code = "static", style = "verbose", applicability = "maybe-incorrect")] + #[suggestion( + "you might want to declare a static instead", + code = "static", + style = "verbose", + applicability = "maybe-incorrect" + )] pub const_span: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_const_type)] +#[diag("missing type for `{$kind}` item")] pub(crate) struct MissingConstType { #[primary_span] - #[suggestion(code = "{colon} ", style = "verbose", applicability = "has-placeholders")] + #[suggestion( + "provide a type for the item", + code = "{colon} ", + style = "verbose", + applicability = "has-placeholders" + )] pub span: Span, pub kind: &'static str, @@ -2070,53 +2468,64 @@ pub(crate) struct MissingConstType { } #[derive(Diagnostic)] -#[diag(parse_enum_struct_mutually_exclusive)] +#[diag("`enum` and `struct` are mutually exclusive")] pub(crate) struct EnumStructMutuallyExclusive { #[primary_span] - #[suggestion(code = "enum", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "replace `enum struct` with", + code = "enum", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] pub(crate) enum UnexpectedTokenAfterStructName { - #[diag(parse_unexpected_token_after_struct_name_found_reserved_identifier)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`" + )] ReservedIdentifier { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_keyword)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found keyword `{$token}`")] Keyword { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_reserved_keyword)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`" + )] ReservedKeyword { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_doc_comment)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found doc comment `{$token}`" + )] DocComment { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_metavar)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found metavar")] MetaVar { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, }, - #[diag(parse_unexpected_token_after_struct_name_found_other)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found `{$token}`")] Other { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, @@ -2136,45 +2545,50 @@ impl UnexpectedTokenAfterStructName { } #[derive(Diagnostic)] -#[diag(parse_unexpected_self_in_generic_parameters)] -#[note] +#[diag("unexpected keyword `Self` in generic parameters")] +#[note("you cannot use `Self` as a generic parameter because it is reserved for associated items")] pub(crate) struct UnexpectedSelfInGenericParameters { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)] +#[diag("unexpected default lifetime parameter")] pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters { #[primary_span] - #[label] + #[label("lifetime parameters cannot have default values")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_multiple_where_clauses)] +#[diag("cannot define duplicate `where` clauses on an item")] pub(crate) struct MultipleWhereClauses { #[primary_span] pub span: Span, - #[label] + #[label("previous `where` clause starts here")] pub previous: Span, - #[suggestion(style = "verbose", code = ",", applicability = "maybe-incorrect")] + #[suggestion( + "consider joining the two `where` clauses into one", + style = "verbose", + code = ",", + applicability = "maybe-incorrect" + )] pub between: Span, } #[derive(Diagnostic)] pub(crate) enum UnexpectedNonterminal { - #[diag(parse_nonterminal_expected_item_keyword)] + #[diag("expected an item keyword")] Item(#[primary_span] Span), - #[diag(parse_nonterminal_expected_statement)] + #[diag("expected a statement")] Statement(#[primary_span] Span), - #[diag(parse_nonterminal_expected_ident)] + #[diag("expected ident, found `{$token}`")] Ident { #[primary_span] span: Span, token: Token, }, - #[diag(parse_nonterminal_expected_lifetime)] + #[diag("expected a lifetime, found `{$token}`")] Lifetime { #[primary_span] span: Span, @@ -2184,14 +2598,14 @@ pub(crate) enum UnexpectedNonterminal { #[derive(Diagnostic)] pub(crate) enum TopLevelOrPatternNotAllowed { - #[diag(parse_or_pattern_not_allowed_in_let_binding)] + #[diag("`let` bindings require top-level or-patterns in parentheses")] LetBinding { #[primary_span] span: Span, #[subdiagnostic] sub: Option, }, - #[diag(parse_or_pattern_not_allowed_in_fn_parameters)] + #[diag("function parameters require top-level or-patterns in parentheses")] FunctionParameter { #[primary_span] span: Span, @@ -2201,7 +2615,7 @@ pub(crate) enum TopLevelOrPatternNotAllowed { } #[derive(Diagnostic)] -#[diag(parse_cannot_be_raw_ident)] +#[diag("`{$ident}` cannot be a raw identifier")] pub(crate) struct CannotBeRawIdent { #[primary_span] pub span: Span, @@ -2209,7 +2623,7 @@ pub(crate) struct CannotBeRawIdent { } #[derive(Diagnostic)] -#[diag(parse_cannot_be_raw_lifetime)] +#[diag("`{$ident}` cannot be a raw lifetime")] pub(crate) struct CannotBeRawLifetime { #[primary_span] pub span: Span, @@ -2217,21 +2631,26 @@ pub(crate) struct CannotBeRawLifetime { } #[derive(Diagnostic)] -#[diag(parse_keyword_lifetime)] +#[diag("lifetimes cannot use keyword names")] pub(crate) struct KeywordLifetime { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_keyword_label)] +#[diag("labels cannot use keyword names")] pub(crate) struct KeywordLabel { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_cr_doc_comment)] +#[diag( + "bare CR not allowed in {$block -> + [true] block doc-comment + *[false] doc-comment + }" +)] pub(crate) struct CrDocComment { #[primary_span] pub span: Span, @@ -2239,14 +2658,14 @@ pub(crate) struct CrDocComment { } #[derive(Diagnostic)] -#[diag(parse_no_digits_literal, code = E0768)] +#[diag("no valid digits found for number", code = E0768)] pub(crate) struct NoDigitsLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_digit_literal)] +#[diag("invalid digit for a base {$base} literal")] pub(crate) struct InvalidDigitLiteral { #[primary_span] pub span: Span, @@ -2254,14 +2673,14 @@ pub(crate) struct InvalidDigitLiteral { } #[derive(Diagnostic)] -#[diag(parse_empty_exponent_float)] +#[diag("expected at least one digit in exponent")] pub(crate) struct EmptyExponentFloat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_float_literal_unsupported_base)] +#[diag("{$base} float literal is not supported")] pub(crate) struct FloatLiteralUnsupportedBase { #[primary_span] pub span: Span, @@ -2269,11 +2688,11 @@ pub(crate) struct FloatLiteralUnsupportedBase { } #[derive(Diagnostic)] -#[diag(parse_unknown_prefix)] -#[note] +#[diag("prefix `{$prefix}` is unknown")] +#[note("prefixed identifiers and literals are reserved since Rust 2021")] pub(crate) struct UnknownPrefix<'a> { #[primary_span] - #[label] + #[label("unknown prefix")] pub span: Span, pub prefix: &'a str, #[subdiagnostic] @@ -2281,7 +2700,7 @@ pub(crate) struct UnknownPrefix<'a> { } #[derive(Subdiagnostic)] -#[note(parse_macro_expands_to_adt_field)] +#[note("macros cannot expand to {$adt_ty} fields")] pub(crate) struct MacroExpandsToAdtField<'a> { pub adt_ty: &'a str, } @@ -2289,28 +2708,28 @@ pub(crate) struct MacroExpandsToAdtField<'a> { #[derive(Subdiagnostic)] pub(crate) enum UnknownPrefixSugg { #[suggestion( - parse_suggestion_br, + "use `br` for a raw byte string", code = "br", applicability = "maybe-incorrect", style = "verbose" )] UseBr(#[primary_span] Span), #[suggestion( - parse_suggestion_cr, + "use `cr` for a raw C-string", code = "cr", applicability = "maybe-incorrect", style = "verbose" )] UseCr(#[primary_span] Span), #[suggestion( - parse_suggestion_whitespace, + "consider inserting whitespace here", code = " ", applicability = "maybe-incorrect", style = "verbose" )] Whitespace(#[primary_span] Span), #[multipart_suggestion( - parse_suggestion_str, + "if you meant to write a string literal, use double quotes", applicability = "maybe-incorrect", style = "verbose" )] @@ -2323,8 +2742,8 @@ pub(crate) enum UnknownPrefixSugg { } #[derive(Diagnostic)] -#[diag(parse_reserved_multihash)] -#[note] +#[diag("reserved multi-hash token is forbidden")] +#[note("sequences of two or more # are reserved for future use since Rust 2024")] pub(crate) struct ReservedMultihash { #[primary_span] pub span: Span, @@ -2332,8 +2751,8 @@ pub(crate) struct ReservedMultihash { pub sugg: Option, } #[derive(Diagnostic)] -#[diag(parse_reserved_string)] -#[note] +#[diag("invalid string literal")] +#[note("unprefixed guarded string literals are reserved for future use since Rust 2024")] pub(crate) struct ReservedString { #[primary_span] pub span: Span, @@ -2342,7 +2761,7 @@ pub(crate) struct ReservedString { } #[derive(Subdiagnostic)] #[suggestion( - parse_suggestion_whitespace, + "consider inserting whitespace here", code = " ", applicability = "maybe-incorrect", style = "verbose" @@ -2350,7 +2769,9 @@ pub(crate) struct ReservedString { pub(crate) struct GuardedStringSugg(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_too_many_hashes)] +#[diag( + "too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}" +)] pub(crate) struct TooManyHashes { #[primary_span] pub span: Span, @@ -2358,25 +2779,27 @@ pub(crate) struct TooManyHashes { } #[derive(Diagnostic)] -#[diag(parse_unknown_start_of_token)] +#[diag("unknown start of token: {$escaped}")] pub(crate) struct UnknownTokenStart { #[primary_span] pub span: Span, pub escaped: String, #[subdiagnostic] pub sugg: Option, - #[subdiagnostic] - pub null: Option, + #[help( + "source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used" + )] + pub null: bool, #[subdiagnostic] pub repeat: Option, - #[subdiagnostic] - pub invisible: Option, + #[help("invisible characters like '{$escaped}' are not usually visible in text editors")] + pub invisible: bool, } #[derive(Subdiagnostic)] pub(crate) enum TokenSubstitution { #[suggestion( - parse_sugg_quotes, + "Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2389,7 +2812,7 @@ pub(crate) enum TokenSubstitution { ascii_name: &'static str, }, #[suggestion( - parse_sugg_other, + "Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2406,35 +2829,42 @@ pub(crate) enum TokenSubstitution { } #[derive(Subdiagnostic)] -#[note(parse_note_repeats)] +#[note( + "character appears {$repeats -> + [one] once more + *[other] {$repeats} more times + }" +)] pub(crate) struct UnknownTokenRepeat { pub repeats: usize, } -#[derive(Subdiagnostic)] -#[help(parse_help_invisible_char)] -pub(crate) struct InvisibleCharacter; - -#[derive(Subdiagnostic)] -#[help(parse_help_null)] -pub(crate) struct UnknownTokenNull; - #[derive(Diagnostic)] pub(crate) enum UnescapeError { - #[diag(parse_invalid_unicode_escape)] - #[help] + #[diag("invalid unicode character escape")] + #[help( + "unicode escape must {$surrogate -> + [true] not be a surrogate + *[false] be at most 10FFFF + }" + )] InvalidUnicodeEscape { #[primary_span] - #[label] + #[label("invalid escape")] span: Span, surrogate: bool, }, - #[diag(parse_escape_only_char)] + #[diag( + "{$byte -> + [true] byte + *[false] character + } constant must be escaped: `{$escaped_msg}`" + )] EscapeOnlyChar { #[primary_span] span: Span, #[suggestion( - parse_escape, + "escape the character", applicability = "machine-applicable", code = "{escaped_sugg}", style = "verbose" @@ -2444,11 +2874,16 @@ pub(crate) enum UnescapeError { escaped_msg: String, byte: bool, }, - #[diag(parse_bare_cr)] + #[diag( + r#"{$double_quotes -> + [true] bare CR not allowed in string, use `\r` instead + *[false] character constant must be escaped: `\r` + }"# + )] BareCr { #[primary_span] #[suggestion( - parse_escape, + "escape the character", applicability = "machine-applicable", code = "\\r", style = "verbose" @@ -2456,93 +2891,103 @@ pub(crate) enum UnescapeError { span: Span, double_quotes: bool, }, - #[diag(parse_bare_cr_in_raw_string)] + #[diag("bare CR not allowed in raw string")] BareCrRawString(#[primary_span] Span), - #[diag(parse_too_short_hex_escape)] + #[diag("numeric character escape is too short")] TooShortHexEscape(#[primary_span] Span), - #[diag(parse_invalid_char_in_escape)] + #[diag( + "invalid character in {$is_hex -> + [true] numeric character + *[false] unicode + } escape: `{$ch}`" + )] InvalidCharInEscape { #[primary_span] - #[label] + #[label( + "invalid character in {$is_hex -> + [true] numeric character + *[false] unicode + } escape" + )] span: Span, is_hex: bool, ch: String, }, - #[diag(parse_leading_underscore_unicode_escape)] + #[diag("invalid start of unicode escape: `_`")] LeadingUnderscoreUnicodeEscape { #[primary_span] - #[label(parse_leading_underscore_unicode_escape_label)] + #[label("invalid start of unicode escape")] span: Span, ch: String, }, - #[diag(parse_overlong_unicode_escape)] + #[diag("overlong unicode escape")] OverlongUnicodeEscape( #[primary_span] - #[label] + #[label("must have at most 6 hex digits")] Span, ), - #[diag(parse_unclosed_unicode_escape)] + #[diag("unterminated unicode escape")] UnclosedUnicodeEscape( #[primary_span] - #[label] + #[label(r#"missing a closing `{"}"}`"#)] Span, #[suggestion( - parse_terminate, + "terminate the unicode escape", code = "}}", applicability = "maybe-incorrect", style = "verbose" )] Span, ), - #[diag(parse_no_brace_unicode_escape)] + #[diag("incorrect unicode escape sequence")] NoBraceInUnicodeEscape { #[primary_span] span: Span, - #[label] + #[label("incorrect unicode escape sequence")] label: Option, #[subdiagnostic] sub: NoBraceUnicodeSub, }, - #[diag(parse_unicode_escape_in_byte)] - #[help] + #[diag("unicode escape in byte string")] + #[help("unicode escape sequences cannot be used as a byte or in a byte string")] UnicodeEscapeInByte( #[primary_span] - #[label] + #[label("unicode escape in byte string")] Span, ), - #[diag(parse_empty_unicode_escape)] + #[diag("empty unicode escape")] EmptyUnicodeEscape( #[primary_span] - #[label] + #[label("this escape must have at least 1 hex digit")] Span, ), - #[diag(parse_zero_chars)] + #[diag("empty character literal")] ZeroChars( #[primary_span] - #[label] + #[label("empty character literal")] Span, ), - #[diag(parse_lone_slash)] + #[diag("invalid trailing slash in literal")] LoneSlash( #[primary_span] - #[label] + #[label("invalid trailing slash in literal")] Span, ), - #[diag(parse_unskipped_whitespace)] + #[diag("whitespace symbol '{$ch}' is not skipped")] UnskippedWhitespace { #[primary_span] span: Span, - #[label] + #[label("whitespace symbol '{$ch}' is not skipped")] char_span: Span, ch: String, }, - #[diag(parse_multiple_skipped_lines)] + #[diag("multiple lines skipped by escaped newline")] MultipleSkippedLinesWarning( #[primary_span] - #[label] + #[label("skipping everything up to and including this point")] Span, ), - #[diag(parse_more_than_one_char)] + #[diag("character literal may only contain one codepoint")] MoreThanOneChar { #[primary_span] span: Span, @@ -2551,7 +2996,7 @@ pub(crate) enum UnescapeError { #[subdiagnostic] suggestion: MoreThanOneCharSugg, }, - #[diag(parse_nul_in_c_str)] + #[diag("null characters in C string literals are not supported")] NulInCStr { #[primary_span] span: Span, @@ -2561,7 +3006,7 @@ pub(crate) enum UnescapeError { #[derive(Subdiagnostic)] pub(crate) enum MoreThanOneCharSugg { #[suggestion( - parse_consider_normalized, + "consider using the normalized form `{$ch}` of this character", code = "{normalized}", applicability = "machine-applicable", style = "verbose" @@ -2573,7 +3018,7 @@ pub(crate) enum MoreThanOneCharSugg { normalized: String, }, #[suggestion( - parse_remove_non, + "consider removing the non-printing characters", code = "{ch}", applicability = "maybe-incorrect", style = "verbose" @@ -2584,7 +3029,10 @@ pub(crate) enum MoreThanOneCharSugg { ch: String, }, #[suggestion( - parse_use_double_quotes, + "if you meant to write a {$is_byte -> + [true] byte string + *[false] string + } literal, use double quotes", code = "{sugg}", applicability = "machine-applicable", style = "verbose" @@ -2595,7 +3043,13 @@ pub(crate) enum MoreThanOneCharSugg { is_byte: bool, sugg: String, }, - #[multipart_suggestion(parse_use_double_quotes, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a {$is_byte -> + [true] byte string + *[false] string + } literal, use double quotes", + applicability = "machine-applicable" + )] Quotes { #[suggestion_part(code = "{prefix}\"")] start: Span, @@ -2608,7 +3062,12 @@ pub(crate) enum MoreThanOneCharSugg { #[derive(Subdiagnostic)] pub(crate) enum MoreThanOneCharNote { - #[note(parse_followed_by)] + #[note( + "this `{$chr}` is followed by the combining {$len -> + [one] mark + *[other] marks + } `{$escaped_marks}`" + )] AllCombining { #[primary_span] span: Span, @@ -2616,7 +3075,7 @@ pub(crate) enum MoreThanOneCharNote { len: usize, escaped_marks: String, }, - #[note(parse_non_printing)] + #[note("there are non-printing characters, the full sequence is `{$escaped}`")] NonPrinting { #[primary_span] span: Span, @@ -2627,7 +3086,7 @@ pub(crate) enum MoreThanOneCharNote { #[derive(Subdiagnostic)] pub(crate) enum NoBraceUnicodeSub { #[suggestion( - parse_use_braces, + "format of unicode escape sequences uses braces", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2637,12 +3096,12 @@ pub(crate) enum NoBraceUnicodeSub { span: Span, suggestion: String, }, - #[help(parse_format_of_unicode)] + #[help(r#"format of unicode escape sequences is `\u{"{...}"}`"#)] Help, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_sugg_wrap_pattern_in_parens, applicability = "machine-applicable")] +#[multipart_suggestion("wrap the pattern in parentheses", applicability = "machine-applicable")] pub(crate) struct WrapInParens { #[suggestion_part(code = "(")] pub(crate) lo: Span, @@ -2653,7 +3112,7 @@ pub(crate) struct WrapInParens { #[derive(Subdiagnostic)] pub(crate) enum TopLevelOrPatternNotAllowedSugg { #[suggestion( - parse_sugg_remove_leading_vert_in_pattern, + "remove the `|`", code = "", applicability = "machine-applicable", style = "tool-only" @@ -2671,27 +3130,37 @@ pub(crate) enum TopLevelOrPatternNotAllowedSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_vert_vert_before_function_parameter)] -#[note(parse_note_pattern_alternatives_use_single_vert)] +#[diag("unexpected `||` before function parameter")] +#[note("alternatives in or-patterns are separated with `|`, not `||`")] pub(crate) struct UnexpectedVertVertBeforeFunctionParam { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the `||`", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_vert_vert_in_pattern)] +#[diag("unexpected token `||` in pattern")] pub(crate) struct UnexpectedVertVertInPattern { #[primary_span] - #[suggestion(code = "|", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use a single `|` to separate multiple alternative patterns", + code = "|", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, - #[label(parse_label_while_parsing_or_pattern_here)] + #[label("while parsing this or-pattern starting here")] pub start: Option, } #[derive(Subdiagnostic)] #[suggestion( - parse_trailing_vert_not_allowed, + "a trailing `{$token}` is not allowed in an or-pattern", code = "", applicability = "machine-applicable", style = "tool-only" @@ -2702,59 +3171,71 @@ pub(crate) struct TrailingVertSuggestion { } #[derive(Diagnostic)] -#[diag(parse_trailing_vert_not_allowed)] +#[diag("a trailing `{$token}` is not allowed in an or-pattern")] pub(crate) struct TrailingVertNotAllowed { #[primary_span] pub span: Span, #[subdiagnostic] pub suggestion: TrailingVertSuggestion, - #[label(parse_label_while_parsing_or_pattern_here)] + #[label("while parsing this or-pattern starting here")] pub start: Option, pub token: Token, - #[note(parse_note_pattern_alternatives_use_single_vert)] + #[note("alternatives in or-patterns are separated with `|`, not `||`")] pub note_double_vert: bool, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot_rest_pattern)] +#[diag("unexpected `...`")] pub(crate) struct DotDotDotRestPattern { #[primary_span] - #[label] + #[label("not a valid pattern")] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "for a rest pattern, use `..` instead of `...`", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub suggestion: Option, - #[note] + #[note( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" + )] pub var_args: Option<()>, } #[derive(Diagnostic)] -#[diag(parse_pattern_on_wrong_side_of_at)] +#[diag("pattern on wrong side of `@`")] pub(crate) struct PatternOnWrongSideOfAt { #[primary_span] - #[suggestion(code = "{whole_pat}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "switch the order", + code = "{whole_pat}", + applicability = "machine-applicable", + style = "verbose" + )] pub whole_span: Span, pub whole_pat: String, - #[label(parse_label_pattern)] + #[label("pattern on the left, should be on the right")] pub pattern: Span, - #[label(parse_label_binding)] + #[label("binding on the right, should be on the left")] pub binding: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_binding_left_of_at)] -#[note] +#[diag("left-hand side of `@` must be a binding")] +#[note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")] pub(crate) struct ExpectedBindingLeftOfAt { #[primary_span] pub whole_span: Span, - #[label(parse_label_lhs)] + #[label("interpreted as a pattern, not a binding")] pub lhs: Span, - #[label(parse_label_rhs)] + #[label("also a pattern")] pub rhs: Span, } #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_ambiguous_range_pattern_suggestion, + "add parentheses to clarify the precedence", applicability = "machine-applicable" )] pub(crate) struct ParenRangeSuggestion { @@ -2765,7 +3246,7 @@ pub(crate) struct ParenRangeSuggestion { } #[derive(Diagnostic)] -#[diag(parse_ambiguous_range_pattern)] +#[diag("the range pattern here has ambiguous interpretation")] pub(crate) struct AmbiguousRangePattern { #[primary_span] pub span: Span, @@ -2774,100 +3255,144 @@ pub(crate) struct AmbiguousRangePattern { } #[derive(Diagnostic)] -#[diag(parse_unexpected_lifetime_in_pattern)] +#[diag("unexpected lifetime `{$symbol}` in pattern")] pub(crate) struct UnexpectedLifetimeInPattern { #[primary_span] pub span: Span, pub symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the lifetime", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] pub(crate) enum InvalidMutInPattern { - #[diag(parse_mut_on_nested_ident_pattern)] - #[note(parse_note_mut_pattern_usage)] + #[diag("`mut` must be attached to each individual binding")] + #[note("`mut` may be followed by `variable` and `variable @ pattern`")] NestedIdent { #[primary_span] - #[suggestion(code = "{pat}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add `mut` to each binding", + code = "{pat}", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, pat: String, }, - #[diag(parse_mut_on_non_ident_pattern)] - #[note(parse_note_mut_pattern_usage)] + #[diag("`mut` must be followed by a named binding")] + #[note("`mut` may be followed by `variable` and `variable @ pattern`")] NonIdent { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the `mut` prefix", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, } #[derive(Diagnostic)] -#[diag(parse_repeated_mut_in_pattern)] +#[diag("`mut` on a binding may not be repeated")] pub(crate) struct RepeatedMutInPattern { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the additional `mut`s", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_dot_range_to_pattern_not_allowed)] +#[diag("range-to patterns with `...` are not allowed")] pub(crate) struct DotDotDotRangeToPatternNotAllowed { #[primary_span] - #[suggestion(style = "verbose", code = "..=", applicability = "machine-applicable")] + #[suggestion( + "use `..=` instead", + style = "verbose", + code = "..=", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_enum_pattern_instead_of_identifier)] +#[diag("expected identifier, found enum pattern")] pub(crate) struct EnumPatternInsteadOfIdentifier { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_at_dot_dot_in_struct_pattern)] +#[diag("`@ ..` is not supported in struct patterns")] pub(crate) struct AtDotDotInStructPattern { #[primary_span] pub span: Span, - #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "bind to each field separately or, if you don't need them, just remove `{$ident} @`", + code = "", + style = "verbose", + applicability = "machine-applicable" + )] pub remove: Span, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(parse_at_in_struct_pattern)] -#[note] -#[help] +#[diag("unexpected `@` in struct pattern")] +#[note("struct patterns use `field: pattern` syntax to bind to fields")] +#[help( + "consider replacing `new_name @ field_name` with `field_name: new_name` if that is what you intended" +)] pub(crate) struct AtInStructPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_dot_for_remaining_fields)] +#[diag("expected field pattern, found `{$token_str}`")] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] - #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "to omit remaining fields, use `..`", + code = "..", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, pub token_str: Cow<'static, str>, } #[derive(Diagnostic)] -#[diag(parse_expected_comma_after_pattern_field)] +#[diag("expected `,`")] pub(crate) struct ExpectedCommaAfterPatternField { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_expr_in_pat)] -#[note] +#[diag( + "expected {$is_bound -> + [true] a pattern range bound + *[false] a pattern + }, found an expression" +)] +#[note( + "arbitrary expressions are not allowed in patterns: " +)] pub(crate) struct UnexpectedExpressionInPattern { /// The unexpected expr's span. #[primary_span] - #[label] + #[label("not a pattern")] pub span: Span, /// Was a `RangePatternBound` expected? pub is_bound: bool, @@ -2878,7 +3403,7 @@ pub(crate) struct UnexpectedExpressionInPattern { #[derive(Subdiagnostic)] pub(crate) enum UnexpectedExpressionInPatternSugg { #[multipart_suggestion( - parse_unexpected_expr_in_pat_create_guard_sugg, + "consider moving the expression to a match arm guard", applicability = "maybe-incorrect" )] CreateGuard { @@ -2895,7 +3420,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { }, #[multipart_suggestion( - parse_unexpected_expr_in_pat_update_guard_sugg, + "consider moving the expression to the match arm guard", applicability = "maybe-incorrect" )] UpdateGuard { @@ -2917,7 +3442,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { }, #[multipart_suggestion( - parse_unexpected_expr_in_pat_const_sugg, + "consider extracting the expression into a `const`", applicability = "has-placeholders" )] Const { @@ -2937,7 +3462,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_paren_in_range_pat)] +#[diag("range pattern bounds cannot have parentheses")] pub(crate) struct UnexpectedParenInRangePat { #[primary_span] pub span: Vec, @@ -2946,10 +3471,7 @@ pub(crate) struct UnexpectedParenInRangePat { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_unexpected_paren_in_range_pat_sugg, - applicability = "machine-applicable" -)] +#[multipart_suggestion("remove these parentheses", applicability = "machine-applicable")] pub(crate) struct UnexpectedParenInRangePatSugg { #[suggestion_part(code = "")] pub start_span: Span, @@ -2958,104 +3480,145 @@ pub(crate) struct UnexpectedParenInRangePatSugg { } #[derive(Diagnostic)] -#[diag(parse_return_types_use_thin_arrow)] +#[diag("return types are denoted using `->`")] pub(crate) struct ReturnTypesUseThinArrow { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = " -> ", applicability = "machine-applicable")] + #[suggestion( + "use `->` instead", + style = "verbose", + code = " -> ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_need_plus_after_trait_object_lifetime)] +#[diag("lifetimes must be followed by `+` to form a trait object type")] pub(crate) struct NeedPlusAfterTraitObjectLifetime { #[primary_span] pub span: Span, - #[suggestion(code = " + /* Trait */", applicability = "has-placeholders")] + #[suggestion( + "consider adding a trait bound after the potential lifetime bound", + code = " + /* Trait */", + applicability = "has-placeholders" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_mut_or_const_in_raw_pointer_type)] +#[diag("expected `mut` or `const` keyword in raw pointer type")] pub(crate) struct ExpectedMutOrConstInRawPointerType { #[primary_span] pub span: Span, - #[suggestion(code("mut ", "const "), applicability = "has-placeholders", style = "verbose")] + #[suggestion( + "add `mut` or `const` here", + code("mut ", "const "), + applicability = "has-placeholders", + style = "verbose" + )] pub after_asterisk: Span, } #[derive(Diagnostic)] -#[diag(parse_lifetime_after_mut)] +#[diag("lifetime must precede `mut`")] pub(crate) struct LifetimeAfterMut { #[primary_span] pub span: Span, - #[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "place the lifetime before `mut`", + code = "&{snippet} mut", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggest_lifetime: Option, pub snippet: String, } #[derive(Diagnostic)] -#[diag(parse_dyn_after_mut)] +#[diag("`mut` must precede `dyn`")] pub(crate) struct DynAfterMut { #[primary_span] - #[suggestion(code = "&mut dyn", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "place `mut` before `dyn`", + code = "&mut dyn", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_pointer_cannot_be_const)] -#[note] +#[diag("an `fn` pointer type cannot be `const`")] +#[note("allowed qualifiers are: `unsafe` and `extern`")] pub(crate) struct FnPointerCannotBeConst { #[primary_span] - #[label] + #[label("`const` because of this")] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the `const` qualifier", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_pointer_cannot_be_async)] -#[note] +#[diag("an `fn` pointer type cannot be `async`")] +#[note("allowed qualifiers are: `unsafe` and `extern`")] pub(crate) struct FnPointerCannotBeAsync { #[primary_span] - #[label] + #[label("`async` because of this")] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the `async` qualifier", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_nested_c_variadic_type, code = E0743)] +#[diag("C-variadic type `...` may not be nested inside another type", code = E0743)] pub(crate) struct NestedCVariadicType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot_rest_type)] -#[note] +#[diag("unexpected `...`")] +#[note( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct InvalidCVariadicType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_dyn_keyword)] -#[help] +#[diag("invalid `dyn` keyword")] +#[help("`dyn` is only needed at the start of a trait `+`-separated list")] pub(crate) struct InvalidDynKeyword { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove this keyword", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Subdiagnostic)] pub(crate) enum HelpUseLatestEdition { - #[help(parse_help_set_edition_cargo)] - #[note(parse_note_edition_guide)] + #[help("set `edition = \"{$edition}\"` in `Cargo.toml`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Cargo { edition: Edition }, - #[help(parse_help_set_edition_standalone)] - #[note(parse_note_edition_guide)] + #[help("pass `--edition {$edition}` to `rustc`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Standalone { edition: Edition }, } @@ -3071,7 +3634,7 @@ impl HelpUseLatestEdition { } #[derive(Diagnostic)] -#[diag(parse_box_syntax_removed)] +#[diag("`box_syntax` has been removed")] pub(crate) struct BoxSyntaxRemoved { #[primary_span] pub span: Span, @@ -3081,7 +3644,7 @@ pub(crate) struct BoxSyntaxRemoved { #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_box_syntax_removed_suggestion, + "use `Box::new()` instead", applicability = "machine-applicable", style = "verbose" )] @@ -3093,65 +3656,70 @@ pub(crate) struct AddBoxNew { } #[derive(Diagnostic)] -#[diag(parse_bad_return_type_notation_output)] +#[diag("return type not allowed with return type notation")] pub(crate) struct BadReturnTypeNotationOutput { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the return type", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_bad_assoc_type_bounds)] +#[diag("bounds on associated types do not belong here")] pub(crate) struct BadAssocTypeBounds { #[primary_span] - #[label] + #[label("belongs in `where` clause")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attr_after_generic)] +#[diag("trailing attribute after generic parameter")] pub(crate) struct AttrAfterGeneric { #[primary_span] - #[label] + #[label("attributes must go before parameters")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attr_without_generics)] +#[diag("attribute without generic parameters")] pub(crate) struct AttrWithoutGenerics { #[primary_span] - #[label] + #[label("attributes are only permitted when preceding parameters")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_generics)] +#[diag("generic parameters on `where` clauses are reserved for future use")] pub(crate) struct WhereOnGenerics { #[primary_span] - #[label] + #[label("currently unsupported")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_generics_in_path)] +#[diag("unexpected generic arguments in path")] pub(crate) struct GenericsInPath { #[primary_span] pub span: Vec, } #[derive(Diagnostic)] -#[diag(parse_lifetime_in_eq_constraint)] -#[help] +#[diag("lifetimes are not permitted in this context")] +#[help("if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}`")] pub(crate) struct LifetimeInEqConstraint { #[primary_span] - #[label] + #[label("lifetime is not allowed here")] pub span: Span, pub lifetime: Ident, - #[label(parse_context_label)] + #[label("this introduces an associated item binding")] pub binding_label: Span, #[suggestion( - parse_colon_sugg, + "you might have meant to write a bound here", style = "verbose", applicability = "maybe-incorrect", code = ": " @@ -3160,119 +3728,159 @@ pub(crate) struct LifetimeInEqConstraint { } #[derive(Diagnostic)] -#[diag(parse_modifier_lifetime)] +#[diag("`{$modifier}` may only modify trait bounds, not lifetime bounds")] pub(crate) struct ModifierLifetime { #[primary_span] - #[suggestion(style = "tool-only", applicability = "maybe-incorrect", code = "")] + #[suggestion( + "remove the `{$modifier}`", + style = "tool-only", + applicability = "maybe-incorrect", + code = "" + )] pub span: Span, pub modifier: &'static str, } #[derive(Diagnostic)] -#[diag(parse_underscore_literal_suffix)] +#[diag("underscore literal suffix is not allowed")] pub(crate) struct UnderscoreLiteralSuffix { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expect_label_found_ident)] +#[diag("expected a label, found an identifier")] pub(crate) struct ExpectedLabelFoundIdent { #[primary_span] pub span: Span, - #[suggestion(code = "'", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "labels start with a tick", + code = "'", + applicability = "machine-applicable", + style = "verbose" + )] pub start: Span, } #[derive(Diagnostic)] -#[diag(parse_inappropriate_default)] -#[note] +#[diag("{$article} {$descr} cannot be `default`")] +#[note("only associated `fn`, `const`, and `type` items can be `default`")] pub(crate) struct InappropriateDefault { #[primary_span] - #[label] + #[label("`default` because of this")] pub span: Span, pub article: &'static str, pub descr: &'static str, } #[derive(Diagnostic)] -#[diag(parse_recover_import_as_use)] +#[diag("expected item, found {$token_name}")] pub(crate) struct RecoverImportAsUse { #[primary_span] - #[suggestion(code = "use", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "items are imported using the `use` keyword", + code = "use", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub token_name: String, } #[derive(Diagnostic)] -#[diag(parse_single_colon_import_path)] -#[note] +#[diag("expected `::`, found `:`")] +#[note("import paths are delimited using `::`")] pub(crate) struct SingleColonImportPath { #[primary_span] - #[suggestion(code = "::", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use double colon", + code = "::", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_bad_item_kind)] +#[diag("{$descr} is not supported in {$ctx}")] pub(crate) struct BadItemKind { #[primary_span] pub span: Span, pub descr: &'static str, pub ctx: &'static str, - #[help] + #[help("consider moving the {$descr} out to a nearby module scope")] pub help: bool, } #[derive(Diagnostic)] -#[diag(parse_macro_rules_missing_bang)] +#[diag("expected `!` after `macro_rules`")] pub(crate) struct MacroRulesMissingBang { #[primary_span] pub span: Span, - #[suggestion(code = "!", applicability = "machine-applicable", style = "verbose")] + #[suggestion("add a `!`", code = "!", applicability = "machine-applicable", style = "verbose")] pub hi: Span, } #[derive(Diagnostic)] -#[diag(parse_macro_name_remove_bang)] +#[diag("macro names aren't followed by a `!`")] pub(crate) struct MacroNameRemoveBang { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "short")] + #[suggestion( + "remove the `!`", + code = "", + applicability = "machine-applicable", + style = "short" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_macro_rules_visibility)] +#[diag("can't qualify macro_rules invocation with `{$vis}`")] pub(crate) struct MacroRulesVisibility<'a> { #[primary_span] - #[suggestion(code = "#[macro_export]", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "try exporting the macro", + code = "#[macro_export]", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, pub vis: &'a str, } #[derive(Diagnostic)] -#[diag(parse_macro_invocation_visibility)] -#[help] +#[diag("can't qualify macro invocation with `pub`")] +#[help("try adjusting the macro to put `{$vis}` inside the invocation")] pub(crate) struct MacroInvocationVisibility<'a> { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the visibility", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub vis: &'a str, } #[derive(Diagnostic)] -#[diag(parse_nested_adt)] +#[diag("`{$kw_str}` definition cannot be nested inside `{$keyword}`")] pub(crate) struct NestedAdt<'a> { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "consider creating a new `{$kw_str}` definition instead of nesting", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub item: Span, pub keyword: &'a str, pub kw_str: Cow<'a, str>, } #[derive(Diagnostic)] -#[diag(parse_function_body_equals_expr)] +#[diag("function body cannot be `= expression;`")] pub(crate) struct FunctionBodyEqualsExpr { #[primary_span] pub span: Span, @@ -3281,7 +3889,10 @@ pub(crate) struct FunctionBodyEqualsExpr { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + r#"surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`"#, + applicability = "machine-applicable" +)] pub(crate) struct FunctionBodyEqualsExprSugg { #[suggestion_part(code = "{{")] pub eq: Span, @@ -3290,38 +3901,56 @@ pub(crate) struct FunctionBodyEqualsExprSugg { } #[derive(Diagnostic)] -#[diag(parse_box_not_pat)] +#[diag("expected pattern, found {$descr}")] pub(crate) struct BoxNotPat { #[primary_span] pub span: Span, - #[note] + #[note("`box` is a reserved keyword")] pub kw: Span, - #[suggestion(code = "r#", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "escape `box` to use it as an identifier", + code = "r#", + applicability = "maybe-incorrect", + style = "verbose" + )] pub lo: Span, pub descr: String, } #[derive(Diagnostic)] -#[diag(parse_unmatched_angle)] +#[diag( + "unmatched angle {$plural -> + [true] brackets + *[false] bracket + }" +)] pub(crate) struct UnmatchedAngle { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove extra angle {$plural -> + [true] brackets + *[false] bracket + }", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub plural: bool, } #[derive(Diagnostic)] -#[diag(parse_missing_plus_in_bounds)] +#[diag("expected `+` between lifetime and {$sym}")] pub(crate) struct MissingPlusBounds { #[primary_span] pub span: Span, - #[suggestion(code = " +", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion("add `+`", code = " +", applicability = "maybe-incorrect", style = "verbose")] pub hi: Span, pub sym: Symbol, } #[derive(Diagnostic)] -#[diag(parse_incorrect_parens_trait_bounds)] +#[diag("incorrect parentheses around trait bounds")] pub(crate) struct IncorrectParensTraitBounds { #[primary_span] pub span: Vec, @@ -3330,10 +3959,7 @@ pub(crate) struct IncorrectParensTraitBounds { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_incorrect_parens_trait_bounds_sugg, - applicability = "machine-applicable" -)] +#[multipart_suggestion("fix the parentheses", applicability = "machine-applicable")] pub(crate) struct IncorrectParensTraitBoundsSugg { #[suggestion_part(code = " ")] pub wrong_span: Span, @@ -3342,10 +3968,15 @@ pub(crate) struct IncorrectParensTraitBoundsSugg { } #[derive(Diagnostic)] -#[diag(parse_kw_bad_case)] +#[diag("keyword `{$kw}` is written in the wrong case")] pub(crate) struct KwBadCase<'a> { #[primary_span] - #[suggestion(code = "{kw}", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "write it in {$case}", + code = "{kw}", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, pub kw: &'a str, pub case: Case, @@ -3369,7 +4000,7 @@ impl IntoDiagArg for Case { } #[derive(Diagnostic)] -#[diag(parse_unknown_builtin_construct)] +#[diag("unknown `builtin #` construct `{$name}`")] pub(crate) struct UnknownBuiltinConstruct { #[primary_span] pub span: Span, @@ -3377,35 +4008,38 @@ pub(crate) struct UnknownBuiltinConstruct { } #[derive(Diagnostic)] -#[diag(parse_expected_builtin_ident)] +#[diag("expected identifier after `builtin #`")] pub(crate) struct ExpectedBuiltinIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_static_with_generics)] +#[diag("static items may not have generic parameters")] pub(crate) struct StaticWithGenerics { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_clause_before_const_body)] +#[diag("where clauses are not allowed before const item bodies")] pub(crate) struct WhereClauseBeforeConstBody { #[primary_span] - #[label] + #[label("unexpected where clause")] pub span: Span, - #[label(parse_name_label)] + #[label("while parsing this const item")] pub name: Span, - #[label(parse_body_label)] + #[label("the item body")] pub body: Span, #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the body before the where clause", + applicability = "machine-applicable" +)] pub(crate) struct WhereClauseBeforeConstBodySugg { #[suggestion_part(code = "= {snippet} ")] pub left: Span, @@ -3415,12 +4049,12 @@ pub(crate) struct WhereClauseBeforeConstBodySugg { } #[derive(Diagnostic)] -#[diag(parse_generic_args_in_pat_require_turbofish_syntax)] +#[diag("generic args in patterns require the turbofish syntax")] pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { #[primary_span] pub span: Span, #[suggestion( - parse_sugg_turbofish_syntax, + "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments", style = "verbose", code = "::", applicability = "maybe-incorrect" @@ -3429,7 +4063,7 @@ pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { } #[derive(Diagnostic)] -#[diag(parse_transpose_dyn_or_impl)] +#[diag("`for<...>` expected after `{$kw}`, not before")] pub(crate) struct TransposeDynOrImpl<'a> { #[primary_span] pub span: Span, @@ -3439,7 +4073,7 @@ pub(crate) struct TransposeDynOrImpl<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("move `{$kw}` before the `for<...>`", applicability = "machine-applicable")] pub(crate) struct TransposeDynOrImplSugg<'a> { #[suggestion_part(code = "")] pub removal_span: Span, @@ -3449,68 +4083,77 @@ pub(crate) struct TransposeDynOrImplSugg<'a> { } #[derive(Diagnostic)] -#[diag(parse_array_index_offset_of)] +#[diag("array indexing not supported in offset_of")] pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_invalid_offset_of)] +#[diag("offset_of expects dot-separated field and variant names")] pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_async_impl)] +#[diag("`async` trait implementations are unsupported")] pub(crate) struct AsyncImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expr_rarrow_call)] -#[help] +#[diag("`->` is not valid syntax for field accesses and method calls")] +#[help( + "the `.` operator will automatically dereference the value, except if the value is a raw pointer" +)] pub(crate) struct ExprRArrowCall { #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = ".")] + #[suggestion( + "try using `.` instead", + style = "verbose", + applicability = "machine-applicable", + code = "." + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_range_attribute)] +#[diag("attributes are not allowed on range expressions starting with `..`")] pub(crate) struct DotDotRangeAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_binder_before_modifiers)] +#[diag("`for<...>` binder should be placed before trait bound modifiers")] pub(crate) struct BinderBeforeModifiers { #[primary_span] pub binder_span: Span, - #[label] + #[label("place the `for<...>` binder before any modifiers")] pub modifiers_span: Span, } #[derive(Diagnostic)] -#[diag(parse_binder_and_polarity)] +#[diag("`for<...>` binder not allowed with `{$polarity}` trait polarity modifier")] pub(crate) struct BinderAndPolarity { #[primary_span] pub polarity_span: Span, - #[label] + #[label("there is not a well-defined meaning for a higher-ranked `{$polarity}` trait")] pub binder_span: Span, pub polarity: &'static str, } #[derive(Diagnostic)] -#[diag(parse_modifiers_and_polarity)] +#[diag("`{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier")] pub(crate) struct PolarityAndModifiers { #[primary_span] pub polarity_span: Span, - #[label] + #[label( + "there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait" + )] pub modifiers_span: Span, pub polarity: &'static str, pub modifiers_concatenated: String, } #[derive(Diagnostic)] -#[diag(parse_incorrect_type_on_self)] +#[diag("type not allowed for shorthand `self` parameter")] pub(crate) struct IncorrectTypeOnSelf { #[primary_span] pub span: Span, @@ -3519,7 +4162,10 @@ pub(crate) struct IncorrectTypeOnSelf { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the modifiers on `self` to the type", + applicability = "machine-applicable" +)] pub(crate) struct MoveSelfModifier { #[suggestion_part(code = "")] pub removal_span: Span, @@ -3529,82 +4175,104 @@ pub(crate) struct MoveSelfModifier { } #[derive(Diagnostic)] -#[diag(parse_asm_unsupported_operand)] +#[diag("the `{$symbol}` operand cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedOperand<'a> { #[primary_span] - #[label] + #[label( + "the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it" + )] pub(crate) span: Span, pub(crate) symbol: &'a str, pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] -#[diag(parse_asm_underscore_input)] +#[diag("_ cannot be used for input operands")] pub(crate) struct AsmUnderscoreInput { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_sym_no_path)] +#[diag("expected a path for argument to `sym`")] pub(crate) struct AsmSymNoPath { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_requires_template)] +#[diag("requires at least a template string argument")] pub(crate) struct AsmRequiresTemplate { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_comma)] +#[diag("expected token: `,`")] pub(crate) struct AsmExpectedComma { #[primary_span] - #[label] + #[label("expected `,`")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_other)] +#[diag( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" +)] pub(crate) struct AsmExpectedOther { #[primary_span] - #[label(parse_asm_expected_other)] + #[label( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" + )] pub(crate) span: Span, pub(crate) is_inline_asm: bool, } #[derive(Diagnostic)] -#[diag(parse_asm_non_abi)] +#[diag("at least one abi must be provided as an argument to `clobber_abi`")] pub(crate) struct NonABI { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_string_literal)] +#[diag("expected string literal")] pub(crate) struct AsmExpectedStringLiteral { #[primary_span] - #[label] + #[label("not a string literal")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_register_class_or_explicit_register)] +#[diag("expected register class or explicit register")] pub(crate) struct ExpectedRegisterClassOrExplicitRegister { #[primary_span] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(parse_hidden_unicode_codepoints)] -#[note] +#[diag("unicode codepoint changing visible direction of text present in {$label}")] +#[note( + "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen" +)] pub(crate) struct HiddenUnicodeCodepointsDiag { pub label: String, pub count: usize, - #[label] + #[label( + "this {$label} contains {$count -> + [one] an invisible + *[other] invisible + } unicode text flow control {$count -> + [one] codepoint + *[other] codepoints + }" + )] pub span_label: Span, #[subdiagnostic] pub labels: Option, @@ -3635,13 +4303,13 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( - fluent::parse_suggestion_remove, + msg!("if their presence wasn't intentional, you can remove them"), spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), Applicability::MachineApplicable, SuggestionStyle::HideCodeAlways, ); diag.multipart_suggestion( - fluent::parse_suggestion_escape, + msg!("if you want to keep them but make them visible in your source code, you can escape them"), spans .into_iter() .map(|(c, span)| { @@ -3664,42 +4332,120 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { .collect::>() .join(", "), ); - diag.note(fluent::parse_suggestion_remove); - diag.note(fluent::parse_no_suggestion_note_escape); + diag.note(msg!("if their presence wasn't intentional, you can remove them")); + diag.note(msg!("if you want to keep them but make them visible in your source code, you can escape them: {$escaped}")); } } } } #[derive(LintDiagnostic)] -#[diag(parse_varargs_without_pattern)] +#[diag("missing pattern for `...` argument")] pub(crate) struct VarargsWithoutPattern { - #[suggestion(code = "_: ...", applicability = "machine-applicable")] + #[suggestion( + "name the argument, or use `_` to continue ignoring it", + code = "_: ...", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_delegation_non_trait_impl_reuse)] +#[diag("only trait impls can be reused")] pub(crate) struct ImplReuseInherentImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_struct_literal_placeholder_path)] +#[diag("placeholder `_` is not allowed for the path in struct literals")] pub(crate) struct StructLiteralPlaceholderPath { #[primary_span] - #[label] - #[suggestion(applicability = "has-placeholders", code = "/* Type */", style = "verbose")] + #[label("not allowed in struct literals")] + #[suggestion( + "replace it with the correct type", + applicability = "has-placeholders", + code = "/* Type */", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_struct_literal_body_without_path_late)] +#[diag("struct literal body without path")] pub(crate) struct StructLiteralWithoutPathLate { #[primary_span] - #[label] + #[label("struct name missing for struct literal")] pub span: Span, - #[suggestion(applicability = "has-placeholders", code = "/* Type */ ", style = "verbose")] + #[suggestion( + "add the correct type", + applicability = "has-placeholders", + code = "/* Type */ ", + style = "verbose" + )] pub suggestion_span: Span, } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy, Subdiagnostic)] +pub(crate) enum ForbiddenLetReason { + /// `let` is not valid and the source environment is not important + OtherForbidden, + /// A let chain with the `||` operator + #[note("`||` operators are not supported in let chain expressions")] + NotSupportedOr(#[primary_span] Span), + /// A let chain with invalid parentheses + /// + /// For example, `let 1 = 1 && (expr && expr)` is allowed + /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not + #[note("`let`s wrapped in parentheses are not supported in a context with let chains")] + NotSupportedParentheses(#[primary_span] Span), +} + +#[derive(Debug, rustc_macros::Subdiagnostic)] +#[suggestion( + "{$is_incorrect_case -> + [true] write keyword `{$similar_kw}` in lowercase + *[false] there is a keyword `{$similar_kw}` with a similar name + }", + applicability = "machine-applicable", + code = "{similar_kw}", + style = "verbose" +)] +pub(crate) struct MisspelledKw { + // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which + // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. + pub similar_kw: String, + #[primary_span] + pub span: Span, + pub is_incorrect_case: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(super) enum TokenDescription { + ReservedIdentifier, + Keyword, + ReservedKeyword, + DocComment, + + // Expanded metavariables are wrapped in invisible delimiters which aren't + // pretty-printed. In error messages we must handle these specially + // otherwise we get confusing things in messages like "expected `(`, found + // ``". It's better to say e.g. "expected `(`, found type metavariable". + MetaVar(MetaVarKind), +} + +impl TokenDescription { + pub(super) fn from_token(token: &Token) -> Option { + match token.kind { + _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescription::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), + token::DocComment(..) => Some(TokenDescription::DocComment), + token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { + Some(TokenDescription::MetaVar(kind)) + } + _ => None, + } + } +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7c969dd7f9f4..cd90655125b2 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -459,8 +459,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> { span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())), escaped: escaped_char(c), sugg, - null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None }, - invisible: if INVISIBLE_CHARACTERS.contains(&c) { Some(errors::InvisibleCharacter) } else { None }, + null: c == '\x00', + invisible: INVISIBLE_CHARACTERS.contains(&c), repeat: if repeats > 0 { swallow_next_invalid = repeats; Some(errors::UnknownTokenRepeat { repeats }) @@ -598,9 +598,9 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let s = self.str_from(start); let real_start = s.find("---").unwrap(); let frontmatter_opening_pos = BytePos(real_start as u32) + start; - let s_new = &s[real_start..]; - let within = s_new.trim_start_matches('-'); - let len_opening = s_new.len() - within.len(); + let real_s = &s[real_start..]; + let within = real_s.trim_start_matches('-'); + let len_opening = real_s.len() - within.len(); let frontmatter_opening_end_pos = frontmatter_opening_pos + BytePos(len_opening as u32); if has_invalid_preceding_whitespace { @@ -614,8 +614,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> { }); } + let line_end = real_s.find('\n').unwrap_or(real_s.len()); if invalid_infostring { - let line_end = s[real_start..].find('\n').unwrap_or(s[real_start..].len()); let span = self.mk_sp( frontmatter_opening_end_pos, frontmatter_opening_pos + BytePos(line_end as u32), @@ -623,10 +623,18 @@ impl<'psess, 'src> Lexer<'psess, 'src> { self.dcx().emit_err(errors::FrontmatterInvalidInfostring { span }); } - let last_line_start = within.rfind('\n').map_or(0, |i| i + 1); - let last_line = &within[last_line_start..]; + let last_line_start = real_s.rfind('\n').map_or(line_end, |i| i + 1); + + let content = &real_s[line_end..last_line_start]; + if let Some(cr_offset) = content.find('\r') { + let cr_pos = start + BytePos((real_start + line_end + cr_offset) as u32); + let span = self.mk_sp(cr_pos, cr_pos + BytePos(1 as u32)); + self.dcx().emit_err(errors::BareCrFrontmatter { span }); + } + + let last_line = &real_s[last_line_start..]; let last_line_trimmed = last_line.trim_start_matches(is_horizontal_whitespace); - let last_line_start_pos = frontmatter_opening_end_pos + BytePos(last_line_start as u32); + let last_line_start_pos = frontmatter_opening_pos + BytePos(last_line_start as u32); let frontmatter_span = self.mk_sp(frontmatter_opening_pos, self.pos); self.psess.gated_spans.gate(sym::frontmatter, frontmatter_span); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index c836d52a71e4..31506ae38fa0 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,13 +1,13 @@ //! The main parser interface. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] +#![cfg_attr(test, feature(iter_order_by))] #![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(default_field_values)] #![feature(if_let_guard)] #![feature(iter_intersperse)] -#![feature(iter_order_by)] #![recursion_limit = "256"] // tidy-alphabetical-end @@ -75,8 +75,6 @@ const _: () = { } }; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - // Unwrap the result if `Ok`, otherwise emit the diagnostics and abort. pub fn unwrap_or_emit_fatal(expr: Result>>) -> T { match expr { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index fe8c1deedff7..78b42ee11e2d 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -3,7 +3,7 @@ use rustc_ast::token::{self, MetaVarKind}; use rustc_ast::tokenstream::ParserRange; use rustc_ast::{AttrItemKind, Attribute, attr}; use rustc_errors::codes::*; -use rustc_errors::{Diag, PResult}; +use rustc_errors::{Diag, PResult, msg}; use rustc_span::{BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -13,7 +13,7 @@ use super::{ Trailing, UsePreAttrPos, }; use crate::parser::FnContext; -use crate::{errors, exp, fluent_generated as fluent}; +use crate::{errors, exp}; // Public for rustfmt usage #[derive(Debug)] @@ -66,9 +66,8 @@ impl<'a> Parser<'a> { } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style != ast::AttrStyle::Outer { let span = self.token.span; - let mut err = self - .dcx() - .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted); + let mut err = + self.dcx().struct_span_err(span, msg!("expected outer doc comment")); err.code(E0753); if let Some(replacement_span) = self.annotate_following_item_if_applicable( &mut err, @@ -79,10 +78,12 @@ impl<'a> Parser<'a> { }, true, ) { - err.note(fluent::parse_note); + err.note(msg!( + "inner doc comments like this (starting with `//!` or `/*!`) can only appear before items" + )); err.span_suggestion_verbose( replacement_span, - fluent::parse_suggestion, + msg!("you might have meant to write a regular comment"), "", rustc_errors::Applicability::MachineApplicable, ); @@ -207,13 +208,25 @@ impl<'a> Parser<'a> { AllowConstBlockItems::Yes, ) { Ok(Some(item)) => { - // FIXME(#100717) err.arg("item", item.kind.descr()); - err.span_label(item.span, fluent::parse_label_does_not_annotate_this); + err.span_label( + item.span, + match attr_type { + OuterAttributeType::Attribute => { + msg!("the inner attribute doesn't annotate this {$item}") + } + OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => { + msg!("the inner doc comment doesn't annotate this {$item}") + } + }, + ); if suggest_to_outer { err.span_suggestion_verbose( replacement_span, - fluent::parse_sugg_change_inner_to_outer, + match attr_type { + OuterAttributeType::Attribute => msg!("to annotate the {$item}, change the attribute from inner to outer style"), + OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => msg!("to annotate the {$item}, change the doc comment from inner to outer style"), + }, match attr_type { OuterAttributeType::Attribute => "", OuterAttributeType::DocBlockComment => "*", @@ -244,28 +257,31 @@ impl<'a> Parser<'a> { self.dcx() .struct_span_err( attr_sp, - fluent::parse_inner_attr_not_permitted_after_outer_doc_comment, + msg!( + "an inner attribute is not permitted following an outer doc comment" + ), ) - .with_span_label(attr_sp, fluent::parse_label_attr) .with_span_label( - prev_doc_comment_span, - fluent::parse_label_prev_doc_comment, + attr_sp, + msg!("not permitted following an outer doc comment"), ) + .with_span_label(prev_doc_comment_span, msg!("previous doc comment")) } Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self .dcx() .struct_span_err( attr_sp, - fluent::parse_inner_attr_not_permitted_after_outer_attr, + msg!("an inner attribute is not permitted following an outer attribute"), ) - .with_span_label(attr_sp, fluent::parse_label_attr) - .with_span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr), - Some(InnerAttrForbiddenReason::InCodeBlock) | None => { - self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted) - } + .with_span_label(attr_sp, msg!("not permitted following an outer attribute")) + .with_span_label(prev_outer_attr_sp, msg!("previous outer attribute")), + Some(InnerAttrForbiddenReason::InCodeBlock) | None => self.dcx().struct_span_err( + attr_sp, + msg!("an inner attribute is not permitted in this context"), + ), }; - diag.note(fluent::parse_inner_attr_explanation); + diag.note(msg!("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files")); if self .annotate_following_item_if_applicable( &mut diag, @@ -275,7 +291,9 @@ impl<'a> Parser<'a> { ) .is_some() { - diag.note(fluent::parse_outer_attr_explanation); + diag.note(msg!( + "outer attributes, like `#[test]`, annotate the item following them" + )); }; diag.emit(); } diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 9692d2c70893..b12209f0b92e 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -7,14 +7,19 @@ use crate::exp; use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; impl<'a> Parser<'a> { - /// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an - /// expression followed by a comma (and strip the comma). + /// Parses a `TokenTree` consisting either of `{ /* ... */ }` optionally followed by a comma + /// (and strip the braces and the optional comma) or an expression followed by a comma + /// (and strip the comma). pub fn parse_delimited_token_tree(&mut self) -> PResult<'a, TokenStream> { if self.token == token::OpenBrace { // Strip the outer '{' and '}'. match self.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => return Ok(tts), + TokenTree::Token(..) => unreachable!("because the current token is a '{{'"), + TokenTree::Delimited(.., tts) => { + // Optionally end with a comma. + let _ = self.eat(exp!(Comma)); + return Ok(tts); + } } } let expr = self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 60e12fa05adf..b8672f6cafdf 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -12,7 +12,7 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions, + Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions, msg, pluralize, }; use rustc_session::errors::ExprParenthesesNeeded; @@ -35,16 +35,16 @@ use crate::errors::{ ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, - SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion, - UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, + TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; +use crate::exp; use crate::parser::FnContext; use crate::parser::attr::InnerAttrPolicy; use crate::parser::item::IsDotDotDot; -use crate::{exp, fluent_generated as fluent}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { @@ -212,22 +212,6 @@ impl std::fmt::Display for UnaryFixity { } } -#[derive(Debug, rustc_macros::Subdiagnostic)] -#[suggestion( - parse_misspelled_kw, - applicability = "machine-applicable", - code = "{similar_kw}", - style = "verbose" -)] -struct MisspelledKw { - // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which - // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. - similar_kw: String, - #[primary_span] - span: Span, - is_incorrect_case: bool, -} - /// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. /// /// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a @@ -1288,7 +1272,7 @@ impl<'a> Parser<'a> { // We made sense of it. Improve the error message. e.span_suggestion_verbose( binop.span.shrink_to_lo(), - fluent::parse_sugg_turbofish_syntax, + msg!("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"), "::", Applicability::MaybeIncorrect, ); @@ -3039,27 +3023,53 @@ impl<'a> Parser<'a> { long_kind: &TokenKind, short_kind: &TokenKind, ) -> bool { - (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) - && self.look_ahead(3, |tok| tok == short_kind) + if long_kind == short_kind { + // For conflict marker chars like `%` and `\`. + (0..7).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + } else { + // For conflict marker chars like `<` and `|`. + (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + && self.look_ahead(3, |tok| tok == short_kind || tok == long_kind) + } } - fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option { + fn conflict_marker( + &mut self, + long_kind: &TokenKind, + short_kind: &TokenKind, + expected: Option, + ) -> Option<(Span, usize)> { if self.is_vcs_conflict_marker(long_kind, short_kind) { let lo = self.token.span; - for _ in 0..4 { - self.bump(); + if self.psess.source_map().span_to_margin(lo) != Some(0) { + return None; } - return Some(lo.to(self.prev_token.span)); + let mut len = 0; + while self.token.kind == *long_kind || self.token.kind == *short_kind { + if self.token.kind.break_two_token_op(1).is_some() { + len += 2; + } else { + len += 1; + } + self.bump(); + if expected == Some(len) { + break; + } + } + if expected.is_some() && expected != Some(len) { + return None; + } + return Some((lo.to(self.prev_token.span), len)); } None } pub(super) fn recover_vcs_conflict_marker(&mut self) { // <<<<<<< - let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else { + let Some((start, len)) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt, None) else { return; }; - let mut spans = Vec::with_capacity(3); + let mut spans = Vec::with_capacity(2); spans.push(start); // ||||||| let mut middlediff3 = None; @@ -3071,13 +3081,19 @@ impl<'a> Parser<'a> { if self.token == TokenKind::Eof { break; } - if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or, Some(len)) + { middlediff3 = Some(span); } - if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq, Some(len)) + { middle = Some(span); } - if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt, Some(len)) + { spans.push(span); end = Some(span); break; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 44c6acec8866..5c44bfb0cf3f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,7 +21,6 @@ use rustc_ast::{ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_literal_escaper::unescape_char; -use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; @@ -728,25 +727,26 @@ impl<'a> Parser<'a> { ); let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); - let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg { - left: expr.span.shrink_to_lo(), - right: expr.span.shrink_to_hi(), - }; - match self.token.kind { token::Lt => { self.dcx().emit_err(errors::ComparisonInterpretedAsGeneric { comparison: self.token.span, r#type: path, args: args_span, - suggestion, + suggestion: errors::ComparisonInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, }) } token::Shl => self.dcx().emit_err(errors::ShiftInterpretedAsGeneric { shift: self.token.span, r#type: path, args: args_span, - suggestion, + suggestion: errors::ShiftInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, }), _ => { // We can end up here even without `<` being the next token, for @@ -1524,7 +1524,7 @@ impl<'a> Parser<'a> { }, ) } else if this.check_inline_const(0) { - this.parse_const_block(lo) + this.parse_const_block(lo, false) } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { @@ -1628,16 +1628,8 @@ impl<'a> Parser<'a> { let first_expr = self.parse_expr()?; if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` - let count = if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - self.parse_mgca_const_block(false)? - } else { - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))? - }; + let count = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; self.expect(close)?; ExprKind::Repeat(first_expr, count) } else if self.eat(exp!(Comma)) { @@ -2774,7 +2766,7 @@ impl<'a> Parser<'a> { let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, - reason: ForbiddenLetReason::OtherForbidden, + reason: errors::ForbiddenLetReason::OtherForbidden, missing_let: None, comparison: None, }; @@ -4189,22 +4181,6 @@ pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool { && unescape_char(ident.without_first_quote().name.as_str()).is_ok() } -/// Used to forbid `let` expressions in certain syntactic locations. -#[derive(Clone, Copy, Subdiagnostic)] -pub(crate) enum ForbiddenLetReason { - /// `let` is not valid and the source environment is not important - OtherForbidden, - /// A let chain with the `||` operator - #[note(parse_not_supported_or)] - NotSupportedOr(#[primary_span] Span), - /// A let chain with invalid parentheses - /// - /// For example, `let 1 = 1 && (expr && expr)` is allowed - /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - #[note(parse_not_supported_parentheses)] - NotSupportedParentheses(#[primary_span] Span), -} - /// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on /// 2024 and later). In case of edition dependence, specify the currently present edition. pub enum LetChainsPolicy { @@ -4225,7 +4201,7 @@ struct CondChecker<'a> { parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy, depth: u32, - forbid_let_reason: Option, + forbid_let_reason: Option, missing_let: Option, comparison: Option, found_incorrect_let_chain: Option, @@ -4248,14 +4224,13 @@ impl<'a> CondChecker<'a> { impl MutVisitor for CondChecker<'_> { fn visit_expr(&mut self, e: &mut Expr) { self.depth += 1; - use ForbiddenLetReason::*; let span = e.span; match e.kind { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { let error = match reason { - NotSupportedOr(or_span) => { + errors::ForbiddenLetReason::NotSupportedOr(or_span) => { self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span }) } _ => { @@ -4289,24 +4264,72 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); } ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _) - if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedOr(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedOr(or_span)); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::NotSupportedOr(or_span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Paren(ref inner) - if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedParentheses(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedParentheses(inner.span)); + self.forbid_let_reason = + Some(errors::ForbiddenLetReason::NotSupportedParentheses(inner.span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } - ExprKind::Assign(ref lhs, _, span) => { + ExprKind::Assign(ref lhs, ref rhs, span) => { + if let ExprKind::Call(_, _) = &lhs.kind { + fn get_path_from_rhs(e: &Expr) -> Option<(u32, &Path)> { + fn inner(e: &Expr, depth: u32) -> Option<(u32, &Path)> { + match &e.kind { + ExprKind::Binary(_, lhs, _) => inner(lhs, depth + 1), + ExprKind::Path(_, path) => Some((depth, path)), + _ => None, + } + } + + inner(e, 0) + } + + if let Some((depth, path)) = get_path_from_rhs(rhs) { + // For cases like if Some(_) = x && let Some(_) = y && let Some(_) = z + // This return let Some(_) = y expression + fn find_let_some(expr: &Expr) -> Option<&Expr> { + match &expr.kind { + ExprKind::Let(..) => Some(expr), + + ExprKind::Binary(op, lhs, rhs) if op.node == BinOpKind::And => { + find_let_some(lhs).or_else(|| find_let_some(rhs)) + } + + _ => None, + } + } + + let expr_span = lhs.span.to(path.span); + + if let Some(later_rhs) = find_let_some(rhs) + && depth > 0 + { + let guar = self.parser.dcx().emit_err(errors::LetChainMissingLet { + span: lhs.span, + label_span: expr_span, + rhs_span: later_rhs.span, + sug_span: lhs.span.shrink_to_lo(), + }); + + self.found_incorrect_let_chain = Some(guar); + } + } + } + let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; if let ExprKind::Binary(_, _, rhs) = &lhs.kind && let ExprKind::Path(_, _) @@ -4339,7 +4362,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Tup(_) | ExprKind::Paren(_) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4347,7 +4370,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Type(ref mut op, _) | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); self.visit_expr(op); self.forbid_let_reason = forbid_let_reason; } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6b61504f2327..c0f5afb952fd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -6,12 +6,10 @@ use rustc_ast::ast::*; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; -use rustc_ast::{ - attr, {self as ast}, -}; +use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; -use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err}; +use rustc_errors::{Applicability, PResult, StashKey, msg, struct_span_code_err}; use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; @@ -26,7 +24,7 @@ use super::{ Parser, PathStyle, Recovered, Trailing, UsePreAttrPos, }; use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField}; -use crate::{exp, fluent_generated as fluent}; +use crate::exp; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. @@ -286,13 +284,13 @@ impl<'a> Parser<'a> { // CONST ITEM self.recover_const_mut(const_span); self.recover_missing_kw_before_item()?; - let (ident, generics, ty, rhs) = self.parse_const_item(attrs)?; + let (ident, generics, ty, rhs_kind) = self.parse_const_item(false)?; ItemKind::Const(Box::new(ConstItem { defaultness: def_(), ident, generics, ty, - rhs, + rhs_kind, define_opaque: None, })) } else if let Some(kind) = self.is_reuse_item() { @@ -303,8 +301,26 @@ impl<'a> Parser<'a> { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword_case(exp!(Type), case) { - // TYPE ITEM - self.parse_type_alias(def_())? + if let Const::Yes(const_span) = self.parse_constness(case) { + // TYPE CONST (mgca) + self.recover_const_mut(const_span); + self.recover_missing_kw_before_item()?; + let (ident, generics, ty, rhs_kind) = self.parse_const_item(true)?; + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(mgca_type_const_syntax)] + self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span)); + ItemKind::Const(Box::new(ConstItem { + defaultness: def_(), + ident, + generics, + ty, + rhs_kind, + define_opaque: None, + })) + } else { + // TYPE ITEM + self.parse_type_alias(def_())? + } } else if self.eat_keyword_case(exp!(Enum), case) { // ENUM ITEM self.parse_item_enum()? @@ -518,7 +534,7 @@ impl<'a> Parser<'a> { match self.parse_delim_args() { // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. Ok(args) => { - self.eat_semi_for_macro_if_needed(&args); + self.eat_semi_for_macro_if_needed(&args, Some(&path)); self.complain_if_pub_macro(vis, false); Ok(MacCall { path, args }) } @@ -1113,13 +1129,12 @@ impl<'a> Parser<'a> { define_opaque, }) => { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); - let rhs = expr.map(ConstItemRhs::Body); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, ident, generics: Generics::default(), ty, - rhs, + rhs_kind: ConstItemRhsKind::Body { rhs: expr }, define_opaque, })) } @@ -1360,7 +1375,7 @@ impl<'a> Parser<'a> { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(box ConstItem { ident, ty, rhs, .. }) => { + ItemKind::Const(box ConstItem { ident, ty, rhs_kind, .. }) => { let const_span = Some(span.with_hi(ident.span.lo())) .filter(|span| span.can_be_used_for_suggestions()); self.dcx().emit_err(errors::ExternItemCannotBeConst { @@ -1371,10 +1386,13 @@ impl<'a> Parser<'a> { ident, ty, mutability: Mutability::Not, - expr: rhs.map(|b| match b { - ConstItemRhs::TypeConst(anon_const) => anon_const.value, - ConstItemRhs::Body(expr) => expr, - }), + expr: match rhs_kind { + ConstItemRhsKind::Body { rhs } => rhs, + ConstItemRhsKind::TypeConst { rhs: Some(anon) } => { + Some(anon.value) + } + ConstItemRhsKind::TypeConst { rhs: None } => None, + }, safety: Safety::Default, define_opaque: None, })) @@ -1516,13 +1534,16 @@ impl<'a> Parser<'a> { /// Parse a constant item with the prefix `"const"` already parsed. /// + /// If `const_arg` is true, any expression assigned to the const will be parsed + /// as a const_arg instead of a body expression. + /// /// ```ebnf /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ; /// ``` fn parse_const_item( &mut self, - attrs: &[Attribute], - ) -> PResult<'a, (Ident, Generics, Box, Option)> { + const_arg: bool, + ) -> PResult<'a, (Ident, Generics, Box, ConstItemRhsKind)> { let ident = self.parse_ident_or_underscore()?; let mut generics = self.parse_generics()?; @@ -1549,14 +1570,15 @@ impl<'a> Parser<'a> { let before_where_clause = if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() }; - let rhs = if self.eat(exp!(Eq)) { - if attr::contains_name(attrs, sym::type_const) { - Some(ConstItemRhs::TypeConst(self.parse_const_arg()?)) - } else { - Some(ConstItemRhs::Body(self.parse_expr()?)) - } - } else { - None + let rhs = match (self.eat(exp!(Eq)), const_arg) { + (true, true) => ConstItemRhsKind::TypeConst { + rhs: Some( + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?, + ), + }, + (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) }, + (false, true) => ConstItemRhsKind::TypeConst { rhs: None }, + (false, false) => ConstItemRhsKind::Body { rhs: None }, }; let after_where_clause = self.parse_where_clause()?; @@ -1565,18 +1587,18 @@ impl<'a> Parser<'a> { // Users may be tempted to write such code if they are still used to the deprecated // where-clause location on type aliases and associated types. See also #89122. if before_where_clause.has_where_token - && let Some(rhs) = &rhs + && let Some(rhs_span) = rhs.span() { self.dcx().emit_err(errors::WhereClauseBeforeConstBody { span: before_where_clause.span, name: ident.span, - body: rhs.span(), + body: rhs_span, sugg: if !after_where_clause.has_where_token { - self.psess.source_map().span_to_snippet(rhs.span()).ok().map(|body_s| { + self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| { errors::WhereClauseBeforeConstBodySugg { left: before_where_clause.span.shrink_to_lo(), snippet: body_s, - right: before_where_clause.span.shrink_to_hi().to(rhs.span()), + right: before_where_clause.span.shrink_to_hi().to(rhs_span), } }) } else { @@ -1721,7 +1743,7 @@ impl<'a> Parser<'a> { if this.token == token::Bang { if let Err(err) = this.unexpected() { - err.with_note(fluent::parse_macro_expands_to_enum_variant).emit(); + err.with_note(msg!("macros cannot expand to enum variants")).emit(); } this.bump(); @@ -2370,7 +2392,7 @@ impl<'a> Parser<'a> { } let body = self.parse_delim_args()?; - self.eat_semi_for_macro_if_needed(&body); + self.eat_semi_for_macro_if_needed(&body, None); self.complain_if_pub_macro(vis, true); Ok(ItemKind::MacroDef( @@ -2395,13 +2417,13 @@ impl<'a> Parser<'a> { } } - fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs) { + fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) { if args.need_semicolon() && !self.eat(exp!(Semi)) { - self.report_invalid_macro_expansion_item(args); + self.report_invalid_macro_expansion_item(args, path); } } - fn report_invalid_macro_expansion_item(&self, args: &DelimArgs) { + fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) { let span = args.dspan.entire(); let mut err = self.dcx().struct_span_err( span, @@ -2411,17 +2433,32 @@ impl<'a> Parser<'a> { // macros within the same crate (that we can fix), which is sad. if !span.from_expansion() { let DelimSpan { open, close } = args.dspan; - err.multipart_suggestion( - "change the delimiters to curly braces", - vec![(open, "{".to_string()), (close, '}'.to_string())], - Applicability::MaybeIncorrect, - ); - err.span_suggestion( - span.with_neighbor(self.token.span).shrink_to_hi(), - "add a semicolon", - ';', - Applicability::MaybeIncorrect, - ); + // Check if this looks like `macro_rules!(name) { ... }` + // a common mistake when trying to define a macro. + if let Some(path) = path + && path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules) + && args.delim == Delimiter::Parenthesis + { + let replace = + if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " }; + err.multipart_suggestion( + "to define a macro, remove the parentheses around the macro name", + vec![(open, replace.to_string()), (close, String::new())], + Applicability::MachineApplicable, + ); + } else { + err.multipart_suggestion( + "change the delimiters to curly braces", + vec![(open, "{".to_string()), (close, '}'.to_string())], + Applicability::MaybeIncorrect, + ); + err.span_suggestion( + span.with_neighbor(self.token.span).shrink_to_hi(), + "add a semicolon", + ';', + Applicability::MaybeIncorrect, + ); + } } err.emit(); } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3ef73a55d47d..f95fe61b0abd 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -20,7 +20,6 @@ use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; -pub(crate) use expr::ForbiddenLetReason; // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt pub use expr::LetChainsPolicy; pub(crate) use item::{FnContext, FnParseMode}; @@ -34,9 +33,9 @@ use rustc_ast::tokenstream::{ }; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, AttrId, BlockCheckMode, ByRef, Const, CoroutineKind, - DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, - Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, + self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, + DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, Mutability, + Recovered, Safety, StrLit, Visibility, VisibilityKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::debug_assert_matches; @@ -50,7 +49,7 @@ use token_type::TokenTypeSet; pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType}; use tracing::debug; -use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral}; +use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral, TokenDescription}; use crate::exp; #[cfg(test)] @@ -308,35 +307,6 @@ impl From for Trailing { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(super) enum TokenDescription { - ReservedIdentifier, - Keyword, - ReservedKeyword, - DocComment, - - // Expanded metavariables are wrapped in invisible delimiters which aren't - // pretty-printed. In error messages we must handle these specially - // otherwise we get confusing things in messages like "expected `(`, found - // ``". It's better to say e.g. "expected `(`, found type metavariable". - MetaVar(MetaVarKind), -} - -impl TokenDescription { - pub(super) fn from_token(token: &Token) -> Option { - match token.kind { - _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), - _ if token.is_used_keyword() => Some(TokenDescription::Keyword), - _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), - token::DocComment(..) => Some(TokenDescription::DocComment), - token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { - Some(TokenDescription::MetaVar(kind)) - } - _ => None, - } - } -} - pub fn token_descr(token: &Token) -> String { let s = pprust::token_to_string(token).to_string(); @@ -1299,21 +1269,8 @@ impl<'a> Parser<'a> { } } - fn parse_mgca_const_block(&mut self, gate_syntax: bool) -> PResult<'a, AnonConst> { - let kw_span = self.prev_token.span; - let value = self.parse_expr_block(None, kw_span, BlockCheckMode::Default)?; - if gate_syntax { - self.psess.gated_spans.gate(sym::min_generic_const_args, kw_span.to(value.span)); - } - Ok(AnonConst { - id: ast::DUMMY_NODE_ID, - value, - mgca_disambiguation: MgcaDisambiguation::AnonConst, - }) - } - /// Parses inline const expressions. - fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box> { + fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box> { self.expect_keyword(exp!(Const))?; let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { @@ -1322,7 +1279,18 @@ impl<'a> Parser<'a> { mgca_disambiguation: MgcaDisambiguation::AnonConst, }; let blk_span = anon_const.value.span; - let kind = ExprKind::ConstBlock(anon_const); + let kind = if pat { + let guar = self + .dcx() + .struct_span_err(blk_span, "const blocks cannot be used as patterns") + .with_help( + "use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead", + ) + .emit(); + ExprKind::Err(guar) + } else { + ExprKind::ConstBlock(anon_const) + }; Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs)) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b6608779787b..bc73c3a2007a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -785,10 +785,8 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(exp!(Box)) { self.parse_pat_box()? } else if self.check_inline_const(0) { - // Parse `const pat`. - // NOTE: This will always error later during AST lowering because - // inline const cannot be used as patterns. - let const_expr = self.parse_const_block(lo.to(self.token.span))?; + // Parse `const pat` + let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; if let Some(re) = self.parse_range_end() { self.parse_pat_range_begin_with(const_expr, re)? @@ -1283,7 +1281,7 @@ impl<'a> Parser<'a> { .then_some(self.prev_token.span); let bound = if self.check_inline_const(0) { - self.parse_const_block(self.token.span) + self.parse_const_block(self.token.span, true) } else if self.check_path() { let lo = self.token.span; let (qself, path) = if self.eat_lt() { @@ -1749,6 +1747,12 @@ impl<'a> Parser<'a> { hi = self.prev_token.span; let ann = BindingMode(by_ref, mutability); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname); + if matches!( + fieldpat.kind, + PatKind::Ident(BindingMode(ByRef::Yes(..), Mutability::Mut), ..) + ) { + self.psess.gated_spans.gate(sym::mut_ref, fieldpat.span); + } let subpat = if is_box { self.mk_pat(lo.to(hi), PatKind::Box(Box::new(fieldpat))) } else { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index dd190707c42b..9196d8d156d8 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -847,6 +847,7 @@ impl<'a> Parser<'a> { /// - A literal. /// - A numeric literal prefixed by `-`. /// - A single-segment path. + /// - A const block (under mGCA) pub(super) fn expr_is_valid_const_arg(&self, expr: &Box) -> bool { match &expr.kind { ast::ExprKind::Block(_, _) @@ -863,6 +864,10 @@ impl<'a> Parser<'a> { { true } + ast::ExprKind::ConstBlock(_) => { + self.psess.gated_spans.gate(sym::min_generic_const_args, expr.span); + true + } _ => false, } } @@ -874,14 +879,6 @@ impl<'a> Parser<'a> { let (value, mgca_disambiguation) = if self.token.kind == token::OpenBrace { let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?; (value, MgcaDisambiguation::Direct) - } else if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - let value = self.parse_mgca_const_block(true)?; - (value.value, MgcaDisambiguation::AnonConst) } else { self.parse_unambiguous_unbraced_const_arg()? }; diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 61b498431b04..ac9c3e63e853 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -25,10 +25,6 @@ use crate::lexer::StripTokens; use crate::parser::{AllowConstBlockItems, ForceCollect, Parser}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; -fn psess() -> ParseSess { - ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE]) -} - fn filename(sm: &SourceMap, path: &str) -> FileName { FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path))) } @@ -46,7 +42,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc, Arc>>) { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); - let translator = Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::new(); let shared: Box = Box::new(Shared { data: output.clone() }); let auto_stream = AutoStream::never(shared); let dcx = DiagCtxt::new(Box::new( @@ -93,7 +89,7 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { - let psess = psess(); + let psess = ParseSess::new(); unwrap_or_emit_fatal(source_str_to_stream( &psess, filename(psess.source_map(), "bogofile"), @@ -2243,12 +2239,12 @@ fn sp(a: u32, b: u32) -> Span { /// Parses a string, return an expression. fn string_to_expr(source_str: String) -> Box { - with_error_checking_parse(source_str, &psess(), |p| p.parse_expr()) + with_error_checking_parse(source_str, &ParseSess::new(), |p| p.parse_expr()) } /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option> { - with_error_checking_parse(source_str, &psess(), |p| { + with_error_checking_parse(source_str, &ParseSess::new(), |p| { p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) }) } @@ -2484,7 +2480,7 @@ let mut fflags: c_int = wb(); #[test] fn crlf_doc_comments() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(); let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); @@ -2519,7 +2515,7 @@ fn ttdelim_span() { } create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(); let expr = parse_expr_from_source_str( filename(psess.source_map(), "foo"), "foo!( fn main() { body } )".to_string(), @@ -2555,7 +2551,7 @@ fn look_ahead() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = psess(); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2630,7 +2626,7 @@ fn look_ahead_non_outermost_stream() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = psess(); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "mod m { fn f(x: u32) { x } struct S; }".to_string()); // Move forward to the `fn`, which is not within the outermost token @@ -2662,7 +2658,7 @@ fn look_ahead_non_outermost_stream() { #[test] fn debug_lookahead() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2883,7 +2879,7 @@ fn debug_lookahead() { #[test] fn out_of_line_mod() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(); let item = parse_item_from_source_str( filename(psess.source_map(), "foo"), "mod foo { struct S; mod this_does_not_exist; }".to_owned(), diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 380b6a214846..6ff165eb22b7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -658,16 +658,8 @@ impl<'a> Parser<'a> { }; let ty = if self.eat(exp!(Semi)) { - let mut length = if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - self.parse_mgca_const_block(false)? - } else { - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))? - }; + let mut length = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; if let Err(e) = self.expect(exp!(CloseBracket)) { // Try to recover from `X` when `X::` works diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 3d8b97b2fde3..2338268a874f 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -187,6 +187,9 @@ pub enum Suggestion { /// Add missing colon: /// `format!("{foo?}")` -> `format!("{foo:?}")` AddMissingColon(Range), + /// Use Rust format string: + /// `format!("{x=}")` -> `dbg!(x)` + UseRustDebugPrintingMacro, } /// The parser structure for interpreting the input format string. This is @@ -462,6 +465,7 @@ impl<'input> Parser<'input> { ('?', _) => self.suggest_format_debug(), ('<' | '^' | '>', _) => self.suggest_format_align(c), (',', _) => self.suggest_unsupported_python_numeric_grouping(), + ('=', '}') => self.suggest_rust_debug_printing_macro(), _ => self.suggest_positional_arg_instead_of_captured_arg(arg), } } @@ -871,6 +875,27 @@ impl<'input> Parser<'input> { } } + fn suggest_rust_debug_printing_macro(&mut self) { + if let Some((range, _)) = self.consume_pos('=') { + self.errors.insert( + 0, + ParseError { + description: + "python's f-string debug `=` is not supported in rust, use `dbg(x)` instead" + .to_owned(), + note: Some(format!("to print `{{`, you can escape it using `{{{{`",)), + label: "expected `}`".to_owned(), + span: range, + secondary_label: self + .last_open_brace + .clone() + .map(|sp| ("because of this opening brace".to_owned(), sp)), + suggestion: Suggestion::UseRustDebugPrintingMacro, + }, + ); + } + } + fn suggest_format_align(&mut self, alignment: char) { if let Some((range, _)) = self.consume_pos(alignment) { self.errors.insert( diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 10da57f56ecf..b65a0ad404a5 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl deleted file mode 100644 index 395d940ddae6..000000000000 --- a/compiler/rustc_passes/messages.ftl +++ /dev/null @@ -1,576 +0,0 @@ --passes_previously_accepted = - this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - --passes_see_issue = - see issue #{$issue} for more information - -passes_abi_invalid_attribute = - `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions -passes_abi_ne = - ABIs are not compatible - left ABI = {$left} - right ABI = {$right} -passes_abi_of = - fn_abi_of({$fn_name}) = {$fn_abi} - -passes_attr_application_enum = - attribute should be applied to an enum - .label = not an enum - -passes_attr_application_struct = - attribute should be applied to a struct - .label = not a struct - -passes_attr_application_struct_enum_union = - attribute should be applied to a struct, enum, or union - .label = not a struct, enum, or union - -passes_attr_application_struct_union = - attribute should be applied to a struct or union - .label = not a struct or union - -passes_autodiff_attr = - `#[autodiff]` should be applied to a function - .label = not a function - -passes_both_ffi_const_and_pure = - `#[ffi_const]` function cannot be `#[ffi_pure]` - -passes_cannot_stabilize_deprecated = - an API can't be stabilized after it is deprecated - .label = invalid version - .item = the stability attribute annotates this item - -passes_change_fields_to_be_of_unit_type = - consider changing the { $num -> - [one] field - *[other] fields - } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num -> - [one] field - *[other] fields - } - -passes_const_continue_attr = - `#[const_continue]` should be applied to a break expression - .label = not a break expression - -passes_const_stable_not_stable = - attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]` - .label = attribute specified here - -passes_custom_mir_incompatible_dialect_and_phase = - the {$dialect} dialect is not compatible with the {$phase} phase - .dialect_span = this dialect... - .phase_span = ... is not compatible with this phase - -passes_custom_mir_phase_requires_dialect = - `dialect` key required - .phase_span = `phase` argument requires a `dialect` argument - - -passes_dead_codes = - { $multiple -> - *[true] multiple {$descr}s are - [false] { $num -> - [one] {$descr} {$name_list} is - *[other] {$descr}s {$name_list} are - } - } never {$participle} - -passes_debug_visualizer_unreadable = - couldn't read {$file}: {$error} - -passes_deprecated_annotation_has_no_effect = - this `#[deprecated]` annotation has no effect - .suggestion = remove the unnecessary deprecation attribute - -passes_deprecated_attribute = - deprecated attribute must be paired with either stable or unstable attribute - -passes_diagnostic_diagnostic_on_const_only_for_trait_impls = - `#[diagnostic::on_const]` can only be applied to trait impls - .label = not a trait impl - -passes_diagnostic_diagnostic_on_unimplemented_only_for_traits = - `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - -passes_diagnostic_item_first_defined = - the diagnostic item is first defined here - -passes_doc_alias_bad_location = - `#[doc(alias = "...")]` isn't allowed on {$location} - -passes_doc_alias_not_an_alias = - `#[doc(alias = "{$attr_str}"]` is the same as the item's name - -passes_doc_fake_variadic_not_valid = - `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity - -passes_doc_inline_conflict = - conflicting doc inlining attributes - .help = remove one of the conflicting attributes - -passes_doc_inline_conflict_first = - this attribute... - -passes_doc_inline_conflict_second = - {"."}..conflicts with this attribute - -passes_doc_inline_only_use = - this attribute can only be applied to a `use` item - .label = only applicable on `use` items - .not_a_use_item_label = not a `use` item - .note = read for more information - -passes_doc_keyword_attribute_empty_mod = - `#[doc({$attr_name} = "...")]` should be used on empty modules - -passes_doc_keyword_attribute_not_mod = - `#[doc({$attr_name} = "...")]` should be used on modules - -passes_doc_keyword_only_impl = - `#[doc(keyword = "...")]` should be used on impl blocks - -passes_doc_masked_not_extern_crate_self = - this attribute cannot be applied to an `extern crate self` item - .label = not applicable on `extern crate self` items - .extern_crate_self_label = `extern crate self` defined here - -passes_doc_masked_only_extern_crate = - this attribute can only be applied to an `extern crate` item - .label = only applicable on `extern crate` items - .not_an_extern_crate_label = not an `extern crate` item - .note = read for more information - -passes_doc_rust_logo = - the `#[doc(rust_logo)]` attribute is used for Rust branding - -passes_doc_search_unbox_invalid = - `#[doc(search_unbox)]` should be used on generic structs and enums - -passes_duplicate_diagnostic_item_in_crate = - duplicate diagnostic item in crate `{$crate_name}`: `{$name}` - .note = the diagnostic item is first defined in crate `{$orig_crate_name}` - -passes_duplicate_eii_impls = - multiple implementations of `#[{$name}]` - .first = first implemented here in crate `{$first_crate}` - .second = also implemented here in crate `{$second_crate}` - .note = in addition to these two, { $num_additional_crates -> - [one] another implementation was found in crate {$additional_crate_names} - *[other] more implementations were also found in the following crates: {$additional_crate_names} - } - - .help = an "externally implementable item" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict - -passes_duplicate_feature_err = - the feature `{$feature}` has already been enabled - -passes_duplicate_lang_item = - found duplicate lang item `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_duplicate_lang_item_crate = - duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_duplicate_lang_item_crate_depends = - duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_eii_fn_with_track_caller = - `#[{$name}]` is not allowed to have `#[track_caller]` - .label = `#[{$name}]` is not allowed to have `#[track_caller]` - -passes_eii_impl_not_function = - `eii_macro_for` is only valid on functions - -passes_eii_impl_requires_unsafe = - `#[{$name}]` is unsafe to implement -passes_eii_impl_requires_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -passes_eii_without_impl = - `#[{$name}]` required, but not found - .label = expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}` - .help = expected at least one implementation in crate `{$current_crate_name}` or any of its dependencies - -passes_enum_variant_same_name = - it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name - -passes_extern_main = - the `main` function cannot be declared in an `extern` block - -passes_feature_previously_declared = - feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared} - -passes_feature_stable_twice = - feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since} - -passes_function_not_found_in_trait = function not found in this trait - -passes_function_not_have_default_implementation = function doesn't have a default implementation - .note = required by this annotation - -passes_functions_names_duplicated = functions names are duplicated - .note = all `#[rustc_must_implement_one_of]` arguments must be unique - -passes_ignored_derived_impls = - `{$name}` has {$trait_list_len -> - [one] a derived impl - *[other] derived impls - } for the {$trait_list_len -> - [one] trait {$trait_list}, but this is - *[other] traits {$trait_list}, but these are - } intentionally ignored during dead code analysis - -passes_implied_feature_not_exist = - feature `{$implied_by}` implying `{$feature}` does not exist - -passes_incorrect_crate_type = lang items are not allowed in stable dylibs - -passes_incorrect_do_not_recommend_location = - `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - -passes_incorrect_target = - `{$name}` lang item must be applied to a {$kind} with {$at_least -> - [true] at least {$num} - *[false] {$num} - } generic {$num -> - [one] argument - *[other] arguments - } - .label = this {$kind} has {$actual_num} generic {$actual_num -> - [one] argument - *[other] arguments - } - -passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect - .note = see issue #55436 for more information - -passes_inline_ignored_for_exported = - `#[inline]` is ignored on externally exported functions - .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` - -passes_inner_crate_level_attr = - crate-level attribute should be in the root module - -passes_invalid_attr_at_crate_level = - `{$name}` attribute cannot be used at crate level - .suggestion = perhaps you meant to use an outer attribute - -passes_invalid_attr_at_crate_level_item = - the inner attribute doesn't annotate this {$kind} - -passes_lang_item_fn = {$name -> - [panic_impl] `#[panic_handler]` - *[other] `{$name}` lang item -} function - -passes_lang_item_fn_with_target_feature = - {passes_lang_item_fn} is not allowed to have `#[target_feature]` - .label = {passes_lang_item_fn} is not allowed to have `#[target_feature]` - -passes_lang_item_fn_with_track_caller = - {passes_lang_item_fn} is not allowed to have `#[track_caller]` - .label = {passes_lang_item_fn} is not allowed to have `#[track_caller]` - -passes_lang_item_on_incorrect_target = - `{$name}` lang item must be applied to a {$expected_target} - .label = attribute should be applied to a {$expected_target}, not a {$actual_target} - -passes_layout_abi = - abi: {$abi} -passes_layout_align = - align: {$align} -passes_layout_homogeneous_aggregate = - homogeneous_aggregate: {$homogeneous_aggregate} -passes_layout_invalid_attribute = - `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases -passes_layout_of = - layout_of({$normalized_ty}) = {$ty_layout} -passes_layout_size = - size: {$size} - -passes_link = - attribute should be applied to an `extern` block with non-Rust ABI - .warn = {-passes_previously_accepted} - .label = not an `extern` block - -passes_loop_match_attr = - `#[loop_match]` should be applied to a loop - .label = not a loop - -passes_macro_export_on_decl_macro = - `#[macro_export]` has no effect on declarative macro definitions - .note = declarative macros follow the same exporting rules as regular items - -passes_macro_only_attribute = - attribute should be applied to a macro - .label = not a macro - -passes_may_dangle = - `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl - -passes_missing_const_err = - attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const` - .help = make the function or method const - -passes_missing_const_stab_attr = - {$descr} has missing const stability attribute - -passes_missing_lang_item = - lang item required, but not found: `{$name}` - .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library - .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config` - -passes_missing_panic_handler = - `#[panic_handler]` function required, but not found - -passes_missing_stability_attr = - {$descr} has missing stability attribute - -passes_misspelled_feature = there is a feature with a similar name: `{$actual_name}` - -passes_mixed_export_name_and_no_mangle = `{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}` - .label = `{$no_mangle_attr}` is ignored - .note = `{$export_name_attr}` takes precedence - .suggestion = remove the `{$no_mangle_attr}` attribute - -passes_multiple_rustc_main = - multiple functions with a `#[rustc_main]` attribute - .first = first `#[rustc_main]` function - .additional = additional `#[rustc_main]` function - -passes_must_implement_not_function = not a function - -passes_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names - -passes_must_implement_not_function_span_note = required by this annotation - -passes_no_main_function = - `main` function not found in crate `{$crate_name}` - .here_is_main = here is a function named `main` - .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level - .consider_moving_main = consider moving the `main` function definitions - .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename -> - [true] {" "}(in `{$filename}`) - *[false] {""} - } - .consider_adding_main_to_file = consider adding a `main` function to `{$filename}` - .consider_adding_main_at_crate = consider adding a `main` function at the crate level - .teach_note = if you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ - .non_function_main = non-function item at `crate::main` is found - -passes_non_exhaustive_with_default_field_values = - `#[non_exhaustive]` can't be used to annotate items with default field values - .label = this struct has default field values - -passes_non_exported_macro_invalid_attrs = - attribute should be applied to function or closure - .label = not a function or closure - -passes_object_lifetime_err = - {$repr} - -passes_outer_crate_level_attr = - crate-level attribute should be an inner attribute - -passes_outer_crate_level_attr_suggestion = - add a `!` - -passes_panic_unwind_without_std = - unwinding panics are not supported without std - .note = since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - .help = using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - -passes_parent_info = - {$num -> - [one] {$descr} - *[other] {$descr}s - } in this {$parent_descr} - -passes_proc_macro_bad_sig = {$kind} has incorrect signature - -passes_remove_fields = - consider removing { $num -> - [one] this - *[other] these - } { $num -> - [one] field - *[other] fields - } - -passes_repr_align_greater_than_target_max = - alignment must not be greater than `isize::MAX` bytes - .note = `isize::MAX` is {$size} for the current target - -passes_repr_align_should_be_align = - `#[repr(align(...))]` is not supported on {$item} - .help = use `#[rustc_align(...)]` instead - -passes_repr_align_should_be_align_static = - `#[repr(align(...))]` is not supported on {$item} - .help = use `#[rustc_align_static(...)]` instead - -passes_repr_conflicting = - conflicting representation hints - -passes_rustc_allow_const_fn_unstable = - attribute should be applied to `const fn` - .label = not a `const fn` - -passes_rustc_const_stable_indirect_pairing = - `const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied -passes_rustc_dirty_clean = - attribute requires -Z query-dep-graph to be enabled - -passes_rustc_force_inline_coro = - attribute cannot be applied to a `async`, `gen` or `async gen` function - .label = `async`, `gen` or `async gen` function - -passes_rustc_legacy_const_generics_index = - #[rustc_legacy_const_generics] must have one index for each generic parameter - .label = generic parameters - -passes_rustc_legacy_const_generics_index_exceed = - index exceeds number of arguments - .label = there {$arg_count -> - [one] is - *[other] are - } only {$arg_count} {$arg_count -> - [one] argument - *[other] arguments - } - -passes_rustc_legacy_const_generics_only = - #[rustc_legacy_const_generics] functions must only have const generics - .label = non-const generic parameter - - -passes_rustc_pub_transparent = - attribute should be applied to `#[repr(transparent)]` types - .label = not a `#[repr(transparent)]` type - -passes_sanitize_attribute_not_allowed = - sanitize attribute not allowed here - .not_fn_impl_mod = not a function, impl block, or module - .no_body = function has no body - .help = sanitize attribute can be applied to a function (with body), impl block, or module - -passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait -passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable... -passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable... -passes_trait_impl_const_stability_mismatch_trait_stable = ...but the trait is stable -passes_trait_impl_const_stability_mismatch_trait_unstable = ...but the trait is unstable - -passes_trait_impl_const_stable = - trait implementations cannot be const stable yet - .note = see issue #143874 for more information - -passes_transparent_incompatible = - transparent {$target} cannot have other repr hints - -passes_unexportable_adt_with_private_fields = ADT types with private fields are not exportable - .note = `{$field_name}` is private - -passes_unexportable_fn_abi = only functions with "C" ABI are exportable - -passes_unexportable_generic_fn = generic functions are not exportable - -passes_unexportable_item = {$descr}'s are not exportable - -passes_unexportable_priv_item = private items are not exportable - .note = is only usable at visibility `{$vis_descr}` - -passes_unexportable_type_in_interface = {$desc} with `#[export_stable]` attribute uses type `{$ty}`, which is not exportable - .label = not exportable - -passes_unexportable_type_repr = types with unstable layout are not exportable - -passes_unknown_external_lang_item = - unknown external lang item: `{$lang_item}` - -passes_unknown_feature = - unknown feature `{$feature}` - -passes_unknown_feature_alias = - feature `{$alias}` has been renamed to `{$feature}` - -passes_unknown_lang_item = - definition of an unknown lang item: `{$name}` - .label = definition of unknown lang item `{$name}` - -passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}` - .suggestion = if you are using features which are still unstable, change to using `{$implies}` - .suggestion_remove = if you are using features which are now stable, remove this line - -passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable - -passes_unrecognized_argument = - unrecognized argument - -passes_unstable_attr_for_already_stable_feature = - can't mark as unstable using an already stable feature - .label = this feature is already stable - .item = the stability attribute annotates this item - .help = consider removing the attribute - -passes_unsupported_attributes_in_where = - most attributes are not supported in `where` clauses - .help = only `#[cfg]` and `#[cfg_attr]` are supported - -passes_unused = - unused attribute - .suggestion = remove this attribute - -passes_unused_default_method_body_const_note = - `default_method_body_is_const` has been replaced with `const` on traits - -passes_unused_duplicate = - unused attribute - .suggestion = remove this attribute - .note = attribute also specified here - .warn = {-passes_previously_accepted} - -passes_unused_empty_lints_note = - attribute `{$name}` with an empty list has no effect - -passes_unused_linker_messages_note = - the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked - -passes_unused_multiple = - multiple `{$name}` attributes - .suggestion = remove this attribute - .note = attribute also specified here - -passes_unused_no_lints_note = - attribute `{$name}` without any lints has no effect - -passes_useless_assignment = - useless assignment of {$is_field_assign -> - [true] field - *[false] variable - } of type `{$ty}` to itself - -passes_useless_stability = - this stability annotation is useless - .label = useless stability annotation - .item = the stability attribute annotates this item diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 0ac42f03eb2f..c3e80208e2d5 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -1,11 +1,12 @@ -use rustc_hir::Attribute; +use rustc_hir::attrs::{AttributeKind, RustcAbiAttrKind}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::sym; use rustc_target::callconv::FnAbi; use super::layout_test::ensure_wf; @@ -17,17 +18,19 @@ pub fn test_abi(tcx: TyCtxt<'_>) { return; } for id in tcx.hir_crate_items(()).definitions() { - for attr in tcx.get_attrs(id, sym::rustc_abi) { - match tcx.def_kind(id) { - DefKind::Fn | DefKind::AssocFn => { - dump_abi_of_fn_item(tcx, id, attr); - } - DefKind::TyAlias => { - dump_abi_of_fn_type(tcx, id, attr); - } - _ => { - tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); - } + let Some((attr_span, attr_kind)) = find_attr!(tcx.get_all_attrs(id), AttributeKind::RustcAbi{ attr_span, kind } => (*attr_span, *kind)) + else { + continue; + }; + match tcx.def_kind(id) { + DefKind::Fn | DefKind::AssocFn => { + dump_abi_of_fn_item(tcx, id, attr_span, attr_kind); + } + DefKind::TyAlias => { + dump_abi_of_fn_type(tcx, id, attr_span, attr_kind); + } + _ => { + tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); } } } @@ -49,7 +52,12 @@ fn unwrap_fn_abi<'tcx>( } } -fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_item( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let args = GenericArgs::identity_for_item(tcx, item_def_id); let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) { @@ -75,22 +83,18 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut // Check out the `#[rustc_abi(..)]` attribute to tell what to dump. // The `..` are the names of fields to dump. - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { - span: tcx.def_span(item_def_id), - fn_name, - // FIXME: using the `Debug` impl here isn't ideal. - fn_abi: format!("{:#?}", abi), - }); - } - - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); - } + match attr_kind { + RustcAbiAttrKind::Debug => { + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { + span: tcx.def_span(item_def_id), + fn_name, + // FIXME: using the `Debug` impl here isn't ideal. + fn_abi: format!("{:#?}", abi), + }); + } + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: attr_span }); } } } @@ -109,24 +113,29 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, && abi1.args.iter().zip(abi2.args.iter()).all(|(arg1, arg2)| arg1.eq_abi(arg2)) } -fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_type( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id); if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let ty::FnPtr(sig_tys, hdr) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(debug)]` on a type alias requires function pointer type" - ); - }; - let abi = unwrap_fn_abi( + + match attr_kind { + RustcAbiAttrKind::Debug => { + let ty::FnPtr(sig_tys, hdr) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(debug)]` on a type alias requires function pointer type" + ); + }; + let abi = + unwrap_fn_abi( tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( sig_tys.with(*hdr), /* extra_args */ ty::List::empty(), @@ -135,61 +144,57 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut item_def_id, ); - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); - } - Some(sym::assert_eq) => { - let ty::Tuple(fields) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let [field1, field2] = ***fields else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi1 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys1.with(*hdr1), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); + } + RustcAbiAttrKind::AssertEq => { + let ty::Tuple(fields) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); - let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi2 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys2.with(*hdr2), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + }; + let [field1, field2] = ***fields else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); + }; + let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" + ); + }; + let abi1 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys1.with(*hdr1), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); + let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" + ); + }; + let abi2 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys2.with(*hdr2), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); - if !test_abi_eq(abi1, abi2) { - tcx.dcx().emit_err(AbiNe { - span, - left: format!("{:#?}", abi1), - right: format!("{:#?}", abi2), - }); - } - } - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); + if !test_abi_eq(abi1, abi2) { + tcx.dcx().emit_err(AbiNe { + span, + left: format!("{:#?}", abi1), + right: format!("{:#?}", abi2), + }); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cdd141f9233e..33d45b648cb8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -15,7 +15,7 @@ use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; +use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, msg}; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, @@ -54,16 +54,23 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; -use crate::{errors, fluent_generated as fluent}; +use crate::errors; #[derive(LintDiagnostic)] -#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)] +#[diag("`#[diagnostic::on_unimplemented]` can only be applied to trait definitions")] struct DiagnosticOnUnimplementedOnlyForTraits; #[derive(LintDiagnostic)] -#[diag(passes_diagnostic_diagnostic_on_const_only_for_trait_impls)] +#[diag("`#[diagnostic::on_const]` can only be applied to trait impls")] struct DiagnosticOnConstOnlyForTraitImpls { - #[label] + #[label("not a trait impl")] + item_span: Span, +} + +#[derive(LintDiagnostic)] +#[diag("`#[diagnostic::on_const]` can only be applied to non-const trait impls")] +struct DiagnosticOnConstOnlyForNonConstTraitImpls { + #[label("this is a const trait impl")] item_span: Span, } @@ -150,7 +157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: attr_span, stability: Stability { level, feature }, } - | AttributeKind::ConstStability { + | AttributeKind::RustcConstStability { span: attr_span, stability: PartialConstStability { level, feature, .. }, }, @@ -168,7 +175,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => { self.check_macro_only_attr(*attr_span, span, target, attrs) } - Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => { + Attribute::Parsed(AttributeKind::RustcAllowConstFnUnstable(_, first_span)) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } Attribute::Parsed(AttributeKind::Deprecation {span: attr_span, .. }) => { @@ -180,7 +187,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { self.check_object_lifetime_default(hir_id); } - &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => { + &Attribute::Parsed(AttributeKind::RustcPubTransparent(attr_span)) => { self.check_rustc_pub_transparent(attr_span, span, attrs) } Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => { @@ -226,29 +233,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)}, Attribute::Parsed( // tidy-alphabetical-start - AttributeKind::AllowIncoherentImpl(..) - | AttributeKind::AsPtr(..) + AttributeKind::RustcAllowIncoherentImpl(..) | AttributeKind::AutomaticallyDerived(..) - | AttributeKind::BodyStability { .. } | AttributeKind::CfgAttrTrace | AttributeKind::CfgTrace(..) | AttributeKind::CfiEncoding { .. } - | AttributeKind::Coinductive(..) | AttributeKind::Cold(..) | AttributeKind::CollapseDebugInfo(..) | AttributeKind::CompilerBuiltins - | AttributeKind::Confusables { .. } - | AttributeKind::ConstStabilityIndirect | AttributeKind::Coroutine(..) | AttributeKind::Coverage (..) | AttributeKind::CrateName { .. } | AttributeKind::CrateType(..) | AttributeKind::DebuggerVisualizer(..) - | AttributeKind::DenyExplicitImpl(..) // `#[doc]` is actually a lot more than just doc comments, so is checked below | AttributeKind::DocComment {..} - | AttributeKind::Dummy - | AttributeKind::DynIncompatibleTrait(..) | AttributeKind::EiiDeclaration { .. } | AttributeKind::EiiForeignItem | AttributeKind::ExportName { .. } @@ -257,12 +256,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Fundamental | AttributeKind::Ignore { .. } | AttributeKind::InstructionSet(..) + | AttributeKind::Lang(..) | AttributeKind::LinkName { .. } | AttributeKind::LinkOrdinal { .. } | AttributeKind::LinkSection { .. } | AttributeKind::Linkage(..) | AttributeKind::MacroEscape( .. ) - | AttributeKind::MacroTransparency(_) | AttributeKind::MacroUse { .. } | AttributeKind::Marker(..) | AttributeKind::MoveSizeLimit { .. } @@ -277,64 +276,106 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::NoMain | AttributeKind::NoMangle(..) | AttributeKind::NoStd { .. } - | AttributeKind::ObjcClass { .. } - | AttributeKind::ObjcSelector { .. } | AttributeKind::Optimize(..) | AttributeKind::PanicRuntime - | AttributeKind::ParenSugar(..) - | AttributeKind::PassByValue (..) | AttributeKind::PatchableFunctionEntry { .. } | AttributeKind::Path(..) | AttributeKind::PatternComplexityLimit { .. } | AttributeKind::PinV2(..) | AttributeKind::Pointee(..) + | AttributeKind::PreludeImport | AttributeKind::ProfilerRuntime | AttributeKind::RecursionLimit { .. } + | AttributeKind::ReexportTestHarnessMain(..) // handled below this loop and elsewhere | AttributeKind::Repr { .. } + | AttributeKind::RustcAbi { .. } | AttributeKind::RustcAllocator | AttributeKind::RustcAllocatorZeroed | AttributeKind::RustcAllocatorZeroedVariant { .. } + | AttributeKind::RustcAsPtr(..) + | AttributeKind::RustcBodyStability { .. } | AttributeKind::RustcBuiltinMacro { .. } + | AttributeKind::RustcCaptureAnalysis + | AttributeKind::RustcCguTestAttr(..) + | AttributeKind::RustcClean(..) | AttributeKind::RustcCoherenceIsCore(..) + | AttributeKind::RustcCoinductive(..) + | AttributeKind::RustcConfusables { .. } + | AttributeKind::RustcConstStabilityIndirect + | AttributeKind::RustcConversionSuggestion | AttributeKind::RustcDeallocator + | AttributeKind::RustcDefPath(..) + | AttributeKind::RustcDelayedBugFromInsideQuery + | AttributeKind::RustcDenyExplicitImpl(..) + | AttributeKind::RustcDeprecatedSafe2024 {..} + | AttributeKind::RustcDiagnosticItem(..) + | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents | AttributeKind::RustcDumpItemBounds | AttributeKind::RustcDumpPredicates | AttributeKind::RustcDumpUserArgs | AttributeKind::RustcDumpVtable(..) + | AttributeKind::RustcDynIncompatibleTrait(..) + | AttributeKind::RustcEffectiveVisibility + | AttributeKind::RustcEvaluateWhereClauses | AttributeKind::RustcHasIncoherentInherentImpls + | AttributeKind::RustcHiddenTypeOfOpaques + | AttributeKind::RustcIfThisChanged(..) + | AttributeKind::RustcInsignificantDtor + | AttributeKind::RustcIntrinsic + | AttributeKind::RustcIntrinsicConstStableIndirect + | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) | AttributeKind::RustcLintOptDenyFieldAccess { .. } | AttributeKind::RustcLintOptTy | AttributeKind::RustcLintQueryInstability | AttributeKind::RustcLintUntrackedQueryInformation + | AttributeKind::RustcMacroTransparency(_) | AttributeKind::RustcMain + | AttributeKind::RustcMir(_) | AttributeKind::RustcNeverReturnsNullPointer + | AttributeKind::RustcNeverTypeOptions {..} | AttributeKind::RustcNoImplicitAutorefs + | AttributeKind::RustcNoImplicitBounds + | AttributeKind::RustcNoMirInline + | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNounwind + | AttributeKind::RustcObjcClass { .. } + | AttributeKind::RustcObjcSelector { .. } | AttributeKind::RustcOffloadKernel + | AttributeKind::RustcOutlives + | AttributeKind::RustcParenSugar(..) + | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) + | AttributeKind::RustcPreserveUbChecks + | AttributeKind::RustcProcMacroDecls | AttributeKind::RustcReallocator + | AttributeKind::RustcRegions + | AttributeKind::RustcReservationImpl(..) | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) + | AttributeKind::RustcSkipDuringMethodDispatch { .. } + | AttributeKind::RustcSpecializationTrait(..) + | AttributeKind::RustcStdInternalSymbol (..) + | AttributeKind::RustcStrictCoherence(..) + | AttributeKind::RustcSymbolName(..) + | AttributeKind::RustcTestMarker(..) + | AttributeKind::RustcThenThisWouldNeed(..) + | AttributeKind::RustcTrivialFieldReads + | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::RustcVariance | AttributeKind::RustcVarianceOfOpaques | AttributeKind::ShouldPanic { .. } - | AttributeKind::SkipDuringMethodDispatch { .. } - | AttributeKind::SpecializationTrait(..) - | AttributeKind::StdInternalSymbol (..) + | AttributeKind::TestRunner(..) | AttributeKind::ThreadLocal - | AttributeKind::TypeConst{..} | AttributeKind::TypeLengthLimit { .. } - | AttributeKind::UnsafeSpecializationMarker(..) | AttributeKind::UnstableFeatureBound(..) | AttributeKind::Used { .. } | AttributeKind::WindowsSubsystem(..) // tidy-alphabetical-end - ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -345,10 +386,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_const, ..] => { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } - [sym::rustc_clean, ..] - | [sym::rustc_dirty, ..] - | [sym::rustc_if_this_changed, ..] - | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } @@ -359,55 +396,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::warn | sym::deny | sym::forbid - // need to be fixed - | sym::deprecated_safe // FIXME(deprecated_safe) // internal - | sym::prelude_import - | sym::panic_handler - | sym::lang | sym::default_lib_allocator - | sym::rustc_diagnostic_item - | sym::rustc_no_mir_inline - | sym::rustc_insignificant_dtor | sym::rustc_nonnull_optimization_guaranteed - | sym::rustc_intrinsic | sym::rustc_inherit_overflow_checks - | sym::rustc_intrinsic_const_stable_indirect - | sym::rustc_trivial_field_reads | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check - | sym::rustc_reservation_impl | sym::rustc_doc_primitive - | sym::rustc_conversion_suggestion - | sym::rustc_deprecated_safe_2024 - | sym::rustc_test_marker - | sym::rustc_abi | sym::rustc_layout - | sym::rustc_proc_macro_decls - | sym::rustc_never_type_options | sym::rustc_autodiff | sym::rustc_capture_analysis - | sym::rustc_regions - | sym::rustc_strict_coherence - | sym::rustc_hidden_type_of_opaques | sym::rustc_mir - | sym::rustc_effective_visibility - | sym::rustc_outlives - | sym::rustc_symbol_name - | sym::rustc_evaluate_where_clauses - | sym::rustc_delayed_bug_from_inside_query - | sym::rustc_def_path - | sym::rustc_partition_reused - | sym::rustc_partition_codegened - | sym::rustc_expected_cgu_reuse // crate-level attrs, are checked below | sym::feature - | sym::register_tool - | sym::rustc_no_implicit_bounds - | sym::test_runner - | sym::reexport_test_harness_main - | sym::rustc_preserve_ub_checks, - .. + | sym::register_tool, .. ] => {} [name, rest@..] => { match BUILTIN_ATTRIBUTE_MAP.get(name) { @@ -628,7 +630,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if target == (Target::Impl { of_trait: true }) { match item.unwrap() { ItemLike::Item(it) => match it.expect_impl().constness { - Constness::Const => {} + Constness::Const => { + let item_span = self.tcx.hir_span(hir_id); + self.tcx.emit_node_span_lint( + MISPLACED_DIAGNOSTIC_ATTRIBUTES, + hir_id, + attr_span, + DiagnosticOnConstOnlyForNonConstTraitImpls { item_span }, + ); + return; + } Constness::NotConst => return, }, ItemLike::ForeignItem => {} @@ -772,15 +783,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Fn => { // `#[track_caller]` is not valid on weak lang items because they are called via // `extern` declarations and `#[track_caller]` would alter their ABI. - if let Some((lang_item, _)) = hir::lang_items::extract(attrs) - && let Some(item) = hir::LangItem::from_name(lang_item) + if let Some(item) = find_attr!(attrs, AttributeKind::Lang(item, _) => item) && item.is_weak() { let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); self.dcx().emit_err(errors::LangItemWithTrackCaller { attr_span, - name: lang_item, + name: item.name(), sig_span: sig.span, }); } @@ -844,7 +854,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) | Target::Fn => { // `#[target_feature]` is not allowed in lang items. - if let Some((lang_item, _)) = hir::lang_items::extract(attrs) + if let Some(lang_item) = find_attr!(attrs, AttributeKind::Lang(lang, _) => lang) // Calling functions with `#[target_feature]` is // not unsafe on WASM, see #84988 && !self.tcx.sess.target.is_like_wasm @@ -854,7 +864,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::LangItemWithTargetFeature { attr_span, - name: lang_item, + name: lang_item.name(), sig_span: sig.span, }); } @@ -993,8 +1003,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for (inline2, span2) in rest { if inline2 != inline { let mut spans = MultiSpan::from_spans(vec![*span, *span2]); - spans.push_span_label(*span, fluent::passes_doc_inline_conflict_first); - spans.push_span_label(*span2, fluent::passes_doc_inline_conflict_second); + spans.push_span_label(*span, msg!("this attribute...")); + spans.push_span_label( + *span2, + msg!("{\".\"}..conflicts with this attribute"), + ); self.dcx().emit_err(errors::DocInlineConflict { spans }); return; } @@ -1138,7 +1151,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self.tcx.sess, sym::rustdoc_internals, *span, - fluent::passes_doc_rust_logo, + msg!("the `#[doc(rust_logo)]` attribute is used for Rust branding"), ) .emit(); } @@ -1242,14 +1255,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph - /// option is passed to the compiler. - fn check_rustc_dirty_clean(&self, attr: &Attribute) { - if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.dcx().emit_err(errors::RustcDirtyClean { span: attr.span() }); - } - } - /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3294b6802a71..e56d27721bdd 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -10,10 +10,11 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Node, PatKind, QPath}; +use rustc_hir::{self as hir, Node, PatKind, QPath, find_attr}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -21,7 +22,7 @@ use rustc_middle::ty::{self, AssocTag, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::DEAD_CODE; use rustc_session::lint::{self, LintExpectationId}; -use rustc_span::{Symbol, kw, sym}; +use rustc_span::{Symbol, kw}; use crate::errors::{ ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment, @@ -380,7 +381,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id()) && self.tcx.is_automatically_derived(impl_of) && let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity() - && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads) + && find_attr!( + self.tcx.get_all_attrs(trait_ref.def_id), + AttributeKind::RustcTrivialFieldReads + ) { if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() && let Some(adt_def_id) = adt_def.did().as_local() @@ -702,12 +706,6 @@ fn has_allow_dead_code_or_lang_attr( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> Option { - fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.has_attr(def_id, sym::lang) - // Stable attribute for #[lang = "panic_impl"] - || tcx.has_attr(def_id, sym::panic_handler) - } - fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { let hir_id = tcx.local_def_id_to_hir_id(def_id); let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level; @@ -728,7 +726,9 @@ fn has_allow_dead_code_or_lang_attr( if has_allow_expect_dead_code(tcx, def_id) { Some(ComesFromAllowExpect::Yes) - } else if has_used_like_attr(tcx, def_id) || has_lang_attr(tcx, def_id) { + } else if has_used_like_attr(tcx, def_id) + || find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Lang(..)) + { Some(ComesFromAllowExpect::No) } else { None diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 8f572af02c24..c7b1dcb95e33 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -9,20 +9,21 @@ //! //! * Compiler internal types like `Ty` and `TyCtxt` +use rustc_hir::attrs::AttributeKind; use rustc_hir::diagnostic_items::DiagnosticItems; -use rustc_hir::{Attribute, CRATE_OWNER_ID, OwnerId}; +use rustc_hir::{CRATE_OWNER_ID, OwnerId, find_attr}; use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::TyCtxt; +use rustc_span::Symbol; use rustc_span::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::{Symbol, sym}; use crate::errors::DuplicateDiagnosticItemInCrate; fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) { let attrs = tcx.hir_attrs(owner.into()); - if let Some(name) = extract(attrs) { + if let Some(name) = find_attr!(attrs, AttributeKind::RustcDiagnosticItem(name) => name) { // insert into our table - collect_item(tcx, diagnostic_items, name, owner.to_def_id()); + collect_item(tcx, diagnostic_items, *name, owner.to_def_id()); } } @@ -53,13 +54,6 @@ fn report_duplicate_item( }); } -/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. -fn extract(attrs: &[Attribute]) -> Option { - attrs.iter().find_map(|attr| { - if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None } - }) -} - /// Traverse and collect the diagnostic items in the current fn diagnostic_items(tcx: TyCtxt<'_>, _: LocalCrate) -> DiagnosticItems { // Initialize the collector. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index bf9b615546d8..281279abd1e1 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, + MultiSpan, msg, }; use rustc_hir::Target; use rustc_hir::attrs::{MirDialect, MirPhase}; @@ -13,80 +13,84 @@ use rustc_middle::ty::{MainDefinition, Ty}; use rustc_span::{DUMMY_SP, Span, Symbol}; use crate::check_attr::ProcMacroKind; -use crate::fluent_generated as fluent; use crate::lang_items::Duplicate; #[derive(LintDiagnostic)] -#[diag(passes_incorrect_do_not_recommend_location)] +#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")] pub(crate) struct IncorrectDoNotRecommendLocation; #[derive(Diagnostic)] -#[diag(passes_autodiff_attr)] +#[diag("`#[autodiff]` should be applied to a function")] pub(crate) struct AutoDiffAttr { #[primary_span] - #[label] + #[label("not a function")] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_loop_match_attr)] +#[diag("`#[loop_match]` should be applied to a loop")] pub(crate) struct LoopMatchAttr { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a loop")] pub node_span: Span, } #[derive(Diagnostic)] -#[diag(passes_const_continue_attr)] +#[diag("`#[const_continue]` should be applied to a break expression")] pub(crate) struct ConstContinueAttr { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a break expression")] pub node_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_mixed_export_name_and_no_mangle)] +#[diag("`{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}`")] pub(crate) struct MixedExportNameAndNoMangle { - #[label] - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[label("`{$no_mangle_attr}` is ignored")] + #[suggestion( + "remove the `{$no_mangle_attr}` attribute", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub no_mangle_span: Span, - #[note] + #[note("`{$export_name_attr}` takes precedence")] pub export_name_span: Span, pub no_mangle_attr: &'static str, pub export_name_attr: &'static str, } #[derive(LintDiagnostic)] -#[diag(passes_outer_crate_level_attr)] +#[diag("crate-level attribute should be an inner attribute")] pub(crate) struct OuterCrateLevelAttr { #[subdiagnostic] pub suggestion: OuterCrateLevelAttrSuggestion, } #[derive(Subdiagnostic)] -#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")] +#[multipart_suggestion("add a `!`", style = "verbose")] pub(crate) struct OuterCrateLevelAttrSuggestion { #[suggestion_part(code = "!")] pub bang_position: Span, } #[derive(LintDiagnostic)] -#[diag(passes_inner_crate_level_attr)] +#[diag("crate-level attribute should be in the root module")] pub(crate) struct InnerCrateLevelAttr; #[derive(Diagnostic)] -#[diag(passes_non_exhaustive_with_default_field_values)] +#[diag("`#[non_exhaustive]` can't be used to annotate items with default field values")] pub(crate) struct NonExhaustiveWithDefaultFieldValues { #[primary_span] pub attr_span: Span, - #[label] + #[label("this struct has default field values")] pub defn_span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_alias_bad_location)] +#[diag("`#[doc(alias = \"...\")]` isn't allowed on {$location}")] pub(crate) struct DocAliasBadLocation<'a> { #[primary_span] pub span: Span, @@ -94,7 +98,7 @@ pub(crate) struct DocAliasBadLocation<'a> { } #[derive(Diagnostic)] -#[diag(passes_doc_alias_not_an_alias)] +#[diag("`#[doc(alias = \"{$attr_str}\"]` is the same as the item's name")] pub(crate) struct DocAliasNotAnAlias { #[primary_span] pub span: Span, @@ -102,7 +106,7 @@ pub(crate) struct DocAliasNotAnAlias { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_attribute_empty_mod)] +#[diag("`#[doc({$attr_name} = \"...\")]` should be used on empty modules")] pub(crate) struct DocKeywordAttributeEmptyMod { #[primary_span] pub span: Span, @@ -110,7 +114,7 @@ pub(crate) struct DocKeywordAttributeEmptyMod { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_attribute_not_mod)] +#[diag("`#[doc({$attr_name} = \"...\")]` should be used on modules")] pub(crate) struct DocKeywordAttributeNotMod { #[primary_span] pub span: Span, @@ -118,122 +122,131 @@ pub(crate) struct DocKeywordAttributeNotMod { } #[derive(Diagnostic)] -#[diag(passes_doc_fake_variadic_not_valid)] +#[diag( + "`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity" +)] pub(crate) struct DocFakeVariadicNotValid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_only_impl)] +#[diag("`#[doc(keyword = \"...\")]` should be used on impl blocks")] pub(crate) struct DocKeywordOnlyImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_search_unbox_invalid)] +#[diag("`#[doc(search_unbox)]` should be used on generic structs and enums")] pub(crate) struct DocSearchUnboxInvalid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_inline_conflict)] -#[help] +#[diag("conflicting doc inlining attributes")] +#[help("remove one of the conflicting attributes")] pub(crate) struct DocInlineConflict { #[primary_span] pub spans: MultiSpan, } #[derive(LintDiagnostic)] -#[diag(passes_doc_inline_only_use)] -#[note] +#[diag("this attribute can only be applied to a `use` item")] +#[note( + "read for more information" +)] pub(crate) struct DocInlineOnlyUse { - #[label] + #[label("only applicable on `use` items")] pub attr_span: Span, - #[label(passes_not_a_use_item_label)] + #[label("not a `use` item")] pub item_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_doc_masked_only_extern_crate)] -#[note] +#[diag("this attribute can only be applied to an `extern crate` item")] +#[note( + "read for more information" +)] pub(crate) struct DocMaskedOnlyExternCrate { - #[label] + #[label("only applicable on `extern crate` items")] pub attr_span: Span, - #[label(passes_not_an_extern_crate_label)] + #[label("not an `extern crate` item")] pub item_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_doc_masked_not_extern_crate_self)] +#[diag("this attribute cannot be applied to an `extern crate self` item")] pub(crate) struct DocMaskedNotExternCrateSelf { - #[label] + #[label("not applicable on `extern crate self` items")] pub attr_span: Span, - #[label(passes_extern_crate_self_label)] + #[label("`extern crate self` defined here")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(passes_both_ffi_const_and_pure, code = E0757)] +#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)] pub(crate) struct BothFfiConstAndPure { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_link)] -#[warning] +#[diag("attribute should be applied to an `extern` block with non-Rust ABI")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] pub(crate) struct Link { - #[label] + #[label("not an `extern` block")] pub span: Option, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_only)] +#[diag("#[rustc_legacy_const_generics] functions must only have const generics")] pub(crate) struct RustcLegacyConstGenericsOnly { #[primary_span] pub attr_span: Span, - #[label] + #[label("non-const generic parameter")] pub param_span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_index)] +#[diag("#[rustc_legacy_const_generics] must have one index for each generic parameter")] pub(crate) struct RustcLegacyConstGenericsIndex { #[primary_span] pub attr_span: Span, - #[label] + #[label("generic parameters")] pub generics_span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_index_exceed)] +#[diag("index exceeds number of arguments")] pub(crate) struct RustcLegacyConstGenericsIndexExceed { #[primary_span] - #[label] + #[label( + "there {$arg_count -> + [one] is + *[other] are + } only {$arg_count} {$arg_count -> + [one] argument + *[other] arguments + }" + )] pub span: Span, pub arg_count: usize, } #[derive(Diagnostic)] -#[diag(passes_rustc_dirty_clean)] -pub(crate) struct RustcDirtyClean { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_repr_conflicting, code = E0566)] +#[diag("conflicting representation hints", code = E0566)] pub(crate) struct ReprConflicting { #[primary_span] pub hint_spans: Vec, } #[derive(Diagnostic)] -#[diag(passes_repr_align_greater_than_target_max, code = E0589)] -#[note] +#[diag("alignment must not be greater than `isize::MAX` bytes", code = E0589)] +#[note("`isize::MAX` is {$size} for the current target")] pub(crate) struct InvalidReprAlignForTarget { #[primary_span] pub span: Span, @@ -241,20 +254,20 @@ pub(crate) struct InvalidReprAlignForTarget { } #[derive(LintDiagnostic)] -#[diag(passes_repr_conflicting, code = E0566)] +#[diag("conflicting representation hints", code = E0566)] pub(crate) struct ReprConflictingLint; #[derive(Diagnostic)] -#[diag(passes_macro_only_attribute)] +#[diag("attribute should be applied to a macro")] pub(crate) struct MacroOnlyAttribute { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a macro")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_debug_visualizer_unreadable)] +#[diag("couldn't read {$file}: {$error}")] pub(crate) struct DebugVisualizerUnreadable<'a> { #[primary_span] pub span: Span, @@ -263,106 +276,114 @@ pub(crate) struct DebugVisualizerUnreadable<'a> { } #[derive(Diagnostic)] -#[diag(passes_rustc_allow_const_fn_unstable)] +#[diag("attribute should be applied to `const fn`")] pub(crate) struct RustcAllowConstFnUnstable { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a `const fn`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_pub_transparent)] +#[diag("attribute should be applied to `#[repr(transparent)]` types")] pub(crate) struct RustcPubTransparent { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a `#[repr(transparent)]` type")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_force_inline_coro)] +#[diag("attribute cannot be applied to a `async`, `gen` or `async gen` function")] pub(crate) struct RustcForceInlineCoro { #[primary_span] pub attr_span: Span, - #[label] + #[label("`async`, `gen` or `async gen` function")] pub span: Span, } #[derive(LintDiagnostic)] pub(crate) enum MacroExport { - #[diag(passes_macro_export_on_decl_macro)] - #[note] + #[diag("`#[macro_export]` has no effect on declarative macro definitions")] + #[note("declarative macros follow the same exporting rules as regular items")] OnDeclMacro, } #[derive(Subdiagnostic)] pub(crate) enum UnusedNote { - #[note(passes_unused_empty_lints_note)] + #[note("attribute `{$name}` with an empty list has no effect")] EmptyList { name: Symbol }, - #[note(passes_unused_no_lints_note)] + #[note("attribute `{$name}` without any lints has no effect")] NoLints { name: Symbol }, - #[note(passes_unused_default_method_body_const_note)] + #[note("`default_method_body_is_const` has been replaced with `const` on traits")] DefaultMethodBodyConst, - #[note(passes_unused_linker_messages_note)] + #[note( + "the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked" + )] LinkerMessagesBinaryCrateOnly, } #[derive(LintDiagnostic)] -#[diag(passes_unused)] +#[diag("unused attribute")] pub(crate) struct Unused { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub attr_span: Span, #[subdiagnostic] pub note: UnusedNote, } #[derive(Diagnostic)] -#[diag(passes_non_exported_macro_invalid_attrs, code = E0518)] +#[diag("attribute should be applied to function or closure", code = E0518)] pub(crate) struct NonExportedMacroInvalidAttrs { #[primary_span] - #[label] + #[label("not a function or closure")] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_may_dangle)] +#[diag("`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl")] pub(crate) struct InvalidMayDangle { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_unused_duplicate)] +#[diag("unused attribute")] pub(crate) struct UnusedDuplicate { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, - #[warning] + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] pub warning: bool, } #[derive(Diagnostic)] -#[diag(passes_unused_multiple)] +#[diag("multiple `{$name}` attributes")] pub(crate) struct UnusedMultiple { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(passes_deprecated_annotation_has_no_effect)] +#[diag("this `#[deprecated]` annotation has no effect")] pub(crate) struct DeprecatedAnnotationHasNoEffect { - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion( + "remove the unnecessary deprecation attribute", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unknown_external_lang_item, code = E0264)] +#[diag("unknown external lang item: `{$lang_item}`", code = E0264)] pub(crate) struct UnknownExternLangItem { #[primary_span] pub span: Span, @@ -370,63 +391,80 @@ pub(crate) struct UnknownExternLangItem { } #[derive(Diagnostic)] -#[diag(passes_missing_panic_handler)] +#[diag("`#[panic_handler]` function required, but not found")] pub(crate) struct MissingPanicHandler; #[derive(Diagnostic)] -#[diag(passes_panic_unwind_without_std)] -#[help] -#[note] +#[diag("unwinding panics are not supported without std")] +#[help("using nightly cargo, use -Zbuild-std with panic=\"abort\" to avoid unwinding")] +#[note( + "since the core library is usually precompiled with panic=\"unwind\", rebuilding your crate with panic=\"abort\" may not be enough to fix the problem" +)] pub(crate) struct PanicUnwindWithoutStd; #[derive(Diagnostic)] -#[diag(passes_missing_lang_item)] -#[note] -#[help] +#[diag("lang item required, but not found: `{$name}`")] +#[note( + "this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library" +)] +#[help( + "you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`" +)] pub(crate) struct MissingLangItem { pub name: Symbol, } #[derive(Diagnostic)] -#[diag(passes_lang_item_fn_with_track_caller)] +#[diag( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item +} function is not allowed to have `#[track_caller]`" +)] pub(crate) struct LangItemWithTrackCaller { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[track_caller]`" + )] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_lang_item_fn_with_target_feature)] +#[diag( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[target_feature]`" +)] pub(crate) struct LangItemWithTargetFeature { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[target_feature]`" + )] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_lang_item_on_incorrect_target, code = E0718)] +#[diag("`{$name}` lang item must be applied to a {$expected_target}", code = E0718)] pub(crate) struct LangItemOnIncorrectTarget { #[primary_span] - #[label] + #[label("attribute should be applied to a {$expected_target}, not a {$actual_target}")] pub span: Span, pub name: Symbol, pub expected_target: Target, pub actual_target: Target, } -#[derive(Diagnostic)] -#[diag(passes_unknown_lang_item, code = E0522)] -pub(crate) struct UnknownLangItem { - #[primary_span] - #[label] - pub span: Span, - pub name: Symbol, -} - pub(crate) struct InvalidAttrAtCrateLevel { pub span: Span, pub sugg_span: Option, @@ -443,7 +481,8 @@ pub(crate) struct ItemFollowingInnerAttr { impl Diagnostic<'_, G> for InvalidAttrAtCrateLevel { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); + let mut diag = + Diag::new(dcx, level, msg!("`{$name}` attribute cannot be used at crate level")); diag.span(self.span); diag.arg("name", self.name); // Only emit an error with a suggestion if we can create a string out @@ -451,27 +490,27 @@ impl Diagnostic<'_, G> for InvalidAttrAtCrateLevel { if let Some(span) = self.sugg_span { diag.span_suggestion_verbose( span, - fluent::passes_suggestion, + msg!("perhaps you meant to use an outer attribute"), String::new(), Applicability::MachineApplicable, ); } if let Some(item) = self.item { diag.arg("kind", item.kind); - diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item); + diag.span_label(item.span, msg!("the inner attribute doesn't annotate this {$kind}")); } diag } } #[derive(Diagnostic)] -#[diag(passes_duplicate_diagnostic_item_in_crate)] +#[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")] pub(crate) struct DuplicateDiagnosticItemInCrate { #[primary_span] pub duplicate_span: Option, - #[note(passes_diagnostic_item_first_defined)] + #[note("the diagnostic item is first defined here")] pub orig_span: Option, - #[note] + #[note("the diagnostic item is first defined in crate `{$orig_crate_name}`")] pub different_crates: bool, pub crate_name: Symbol, pub orig_crate_name: Symbol, @@ -479,7 +518,7 @@ pub(crate) struct DuplicateDiagnosticItemInCrate { } #[derive(Diagnostic)] -#[diag(passes_layout_abi)] +#[diag("abi: {$abi}")] pub(crate) struct LayoutAbi { #[primary_span] pub span: Span, @@ -487,7 +526,7 @@ pub(crate) struct LayoutAbi { } #[derive(Diagnostic)] -#[diag(passes_layout_align)] +#[diag("align: {$align}")] pub(crate) struct LayoutAlign { #[primary_span] pub span: Span, @@ -495,7 +534,7 @@ pub(crate) struct LayoutAlign { } #[derive(Diagnostic)] -#[diag(passes_layout_size)] +#[diag("size: {$size}")] pub(crate) struct LayoutSize { #[primary_span] pub span: Span, @@ -503,7 +542,7 @@ pub(crate) struct LayoutSize { } #[derive(Diagnostic)] -#[diag(passes_layout_homogeneous_aggregate)] +#[diag("homogeneous_aggregate: {$homogeneous_aggregate}")] pub(crate) struct LayoutHomogeneousAggregate { #[primary_span] pub span: Span, @@ -511,7 +550,7 @@ pub(crate) struct LayoutHomogeneousAggregate { } #[derive(Diagnostic)] -#[diag(passes_layout_of)] +#[diag("layout_of({$normalized_ty}) = {$ty_layout}")] pub(crate) struct LayoutOf<'tcx> { #[primary_span] pub span: Span, @@ -520,14 +559,7 @@ pub(crate) struct LayoutOf<'tcx> { } #[derive(Diagnostic)] -#[diag(passes_layout_invalid_attribute)] -pub(crate) struct LayoutInvalidAttribute { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_abi_of)] +#[diag("fn_abi_of({$fn_name}) = {$fn_abi}")] pub(crate) struct AbiOf { #[primary_span] pub span: Span, @@ -536,7 +568,11 @@ pub(crate) struct AbiOf { } #[derive(Diagnostic)] -#[diag(passes_abi_ne)] +#[diag( + "ABIs are not compatible + left ABI = {$left} + right ABI = {$right}" +)] pub(crate) struct AbiNe { #[primary_span] pub span: Span, @@ -545,21 +581,23 @@ pub(crate) struct AbiNe { } #[derive(Diagnostic)] -#[diag(passes_abi_invalid_attribute)] +#[diag( + "`#[rustc_abi]` can only be applied to function items, type aliases, and associated functions" +)] pub(crate) struct AbiInvalidAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unrecognized_argument)] +#[diag("unrecognized argument")] pub(crate) struct UnrecognizedArgument { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_feature_stable_twice, code = E0711)] +#[diag("feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}", code = E0711)] pub(crate) struct FeatureStableTwice { #[primary_span] pub span: Span, @@ -569,7 +607,7 @@ pub(crate) struct FeatureStableTwice { } #[derive(Diagnostic)] -#[diag(passes_feature_previously_declared, code = E0711)] +#[diag("feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}", code = E0711)] pub(crate) struct FeaturePreviouslyDeclared<'a> { #[primary_span] pub span: Span, @@ -579,18 +617,18 @@ pub(crate) struct FeaturePreviouslyDeclared<'a> { } #[derive(Diagnostic)] -#[diag(passes_multiple_rustc_main, code = E0137)] +#[diag("multiple functions with a `#[rustc_main]` attribute", code = E0137)] pub(crate) struct MultipleRustcMain { #[primary_span] pub span: Span, - #[label(passes_first)] + #[label("first `#[rustc_main]` function")] pub first: Span, - #[label(passes_additional)] + #[label("additional `#[rustc_main]` function")] pub additional: Span, } #[derive(Diagnostic)] -#[diag(passes_extern_main)] +#[diag("the `main` function cannot be declared in an `extern` block")] pub(crate) struct ExternMain { #[primary_span] pub span: Span, @@ -610,7 +648,8 @@ pub(crate) struct NoMainErr { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, fluent::passes_no_main_function); + let mut diag = + Diag::new(dcx, level, msg!("`main` function not found in crate `{$crate_name}`")); diag.span(DUMMY_SP); diag.code(E0601); diag.arg("crate_name", self.crate_name); @@ -618,16 +657,23 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { diag.arg("has_filename", self.has_filename); let note = if !self.non_main_fns.is_empty() { for &span in &self.non_main_fns { - diag.span_note(span, fluent::passes_here_is_main); + diag.span_note(span, msg!("here is a function named `main`")); } - diag.note(fluent::passes_one_or_more_possible_main); - diag.help(fluent::passes_consider_moving_main); + diag.note(msg!( + "you have one or more functions named `main` not defined at the crate level" + )); + diag.help(msg!("consider moving the `main` function definitions")); // There were some functions named `main` though. Try to give the user a hint. - fluent::passes_main_must_be_defined_at_crate + msg!( + "the main function must be defined at the crate level{$has_filename -> + [true] {\" \"}(in `{$filename}`) + *[false] {\"\"} + }" + ) } else if self.has_filename { - fluent::passes_consider_adding_main_to_file + msg!("consider adding a `main` function to `{$filename}`") } else { - fluent::passes_consider_adding_main_at_crate + msg!("consider adding a `main` function at the crate level") }; if self.file_empty { diag.note(note); @@ -640,11 +686,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { && main_def.opt_fn_def_id().is_none() { // There is something at `crate::main`, but it is not a function definition. - diag.span_label(main_def.span, fluent::passes_non_function_main); + diag.span_label(main_def.span, msg!("non-function item at `crate::main` is found")); } if self.add_teach_note { - diag.note(fluent::passes_teach_note); + diag.note(msg!("if you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/")); } diag } @@ -672,9 +718,13 @@ impl Diagnostic<'_, G> for DuplicateLangItem { dcx, level, match self.duplicate { - Duplicate::Plain => fluent::passes_duplicate_lang_item, - Duplicate::Crate => fluent::passes_duplicate_lang_item_crate, - Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, + Duplicate::Plain => msg!("found duplicate lang item `{$lang_item_name}`"), + Duplicate::Crate => { + msg!("duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`") + } + Duplicate::CrateDepends => msg!( + "duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`" + ), }, ); diag.code(E0152); @@ -695,24 +745,26 @@ impl Diagnostic<'_, G> for DuplicateLangItem { diag.span(span); } if let Some(span) = self.first_defined_span { - diag.span_note(span, fluent::passes_first_defined_span); + diag.span_note(span, msg!("the lang item is first defined here")); } else { if self.orig_dependency_of.is_none() { - diag.note(fluent::passes_first_defined_crate); + diag.note(msg!("the lang item is first defined in crate `{$orig_crate_name}`")); } else { - diag.note(fluent::passes_first_defined_crate_depends); + diag.note(msg!("the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)")); } if self.orig_is_local { - diag.note(fluent::passes_first_definition_local); + diag.note(msg!("first definition in the local crate (`{$orig_crate_name}`)")); } else { - diag.note(fluent::passes_first_definition_path); + diag.note(msg!( + "first definition in `{$orig_crate_name}` loaded from {$orig_path}" + )); } if self.is_local { - diag.note(fluent::passes_second_definition_local); + diag.note(msg!("second definition in the local crate (`{$crate_name}`)")); } else { - diag.note(fluent::passes_second_definition_path); + diag.note(msg!("second definition in `{$crate_name}` loaded from {$path}")); } } diag @@ -720,11 +772,22 @@ impl Diagnostic<'_, G> for DuplicateLangItem { } #[derive(Diagnostic)] -#[diag(passes_incorrect_target, code = E0718)] +#[diag("`{$name}` lang item must be applied to a {$kind} with {$at_least -> + [true] at least {$num} + *[false] {$num} + } generic {$num -> + [one] argument + *[other] arguments + }", code = E0718)] pub(crate) struct IncorrectTarget<'a> { #[primary_span] pub span: Span, - #[label] + #[label( + "this {$kind} has {$actual_num} generic {$actual_num -> + [one] argument + *[other] arguments + }" + )] pub generics_span: Span, pub name: &'a str, // cannot be symbol because it renders e.g. `r#fn` instead of `fn` pub kind: &'static str, @@ -734,26 +797,33 @@ pub(crate) struct IncorrectTarget<'a> { } #[derive(Diagnostic)] -#[diag(passes_incorrect_crate_type)] +#[diag("lang items are not allowed in stable dylibs")] pub(crate) struct IncorrectCrateType { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_useless_assignment)] +#[diag( + "useless assignment of {$is_field_assign -> + [true] field + *[false] variable + } of type `{$ty}` to itself" +)] pub(crate) struct UselessAssignment<'a> { pub is_field_assign: bool, pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(passes_inline_ignored_for_exported)] -#[help] +#[diag("`#[inline]` is ignored on externally exported functions")] +#[help( + "externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`" +)] pub(crate) struct InlineIgnoredForExported {} #[derive(Diagnostic)] -#[diag(passes_object_lifetime_err)] +#[diag("{$repr}")] pub(crate) struct ObjectLifetimeErr { #[primary_span] pub span: Span, @@ -762,38 +832,38 @@ pub(crate) struct ObjectLifetimeErr { #[derive(Diagnostic)] pub(crate) enum AttrApplication { - #[diag(passes_attr_application_enum, code = E0517)] + #[diag("attribute should be applied to an enum", code = E0517)] Enum { #[primary_span] hint_span: Span, - #[label] + #[label("not an enum")] span: Span, }, - #[diag(passes_attr_application_struct, code = E0517)] + #[diag("attribute should be applied to a struct", code = E0517)] Struct { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct")] span: Span, }, - #[diag(passes_attr_application_struct_union, code = E0517)] + #[diag("attribute should be applied to a struct or union", code = E0517)] StructUnion { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct or union")] span: Span, }, - #[diag(passes_attr_application_struct_enum_union, code = E0517)] + #[diag("attribute should be applied to a struct, enum, or union", code = E0517)] StructEnumUnion { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct, enum, or union")] span: Span, }, } #[derive(Diagnostic)] -#[diag(passes_transparent_incompatible, code = E0692)] +#[diag("transparent {$target} cannot have other repr hints", code = E0692)] pub(crate) struct TransparentIncompatible { #[primary_span] pub hint_spans: Vec, @@ -801,45 +871,45 @@ pub(crate) struct TransparentIncompatible { } #[derive(Diagnostic)] -#[diag(passes_deprecated_attribute, code = E0549)] +#[diag("deprecated attribute must be paired with either stable or unstable attribute", code = E0549)] pub(crate) struct DeprecatedAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_useless_stability)] +#[diag("this stability annotation is useless")] pub(crate) struct UselessStability { #[primary_span] - #[label] + #[label("useless stability annotation")] pub span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_sp: Span, } #[derive(Diagnostic)] -#[diag(passes_cannot_stabilize_deprecated)] +#[diag("an API can't be stabilized after it is deprecated")] pub(crate) struct CannotStabilizeDeprecated { #[primary_span] - #[label] + #[label("invalid version")] pub span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_sp: Span, } #[derive(Diagnostic)] -#[diag(passes_unstable_attr_for_already_stable_feature)] +#[diag("can't mark as unstable using an already stable feature")] pub(crate) struct UnstableAttrForAlreadyStableFeature { #[primary_span] - #[label] - #[help] + #[label("this feature is already stable")] + #[help("consider removing the attribute")] pub attr_span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(passes_missing_stability_attr)] +#[diag("{$descr} has missing stability attribute")] pub(crate) struct MissingStabilityAttr<'a> { #[primary_span] pub span: Span, @@ -847,7 +917,7 @@ pub(crate) struct MissingStabilityAttr<'a> { } #[derive(Diagnostic)] -#[diag(passes_missing_const_stab_attr)] +#[diag("{$descr} has missing const stability attribute")] pub(crate) struct MissingConstStabAttr<'a> { #[primary_span] pub span: Span, @@ -855,15 +925,15 @@ pub(crate) struct MissingConstStabAttr<'a> { } #[derive(Diagnostic)] -#[diag(passes_trait_impl_const_stable)] -#[note] +#[diag("trait implementations cannot be const stable yet")] +#[note("see issue #143874 for more information")] pub(crate) struct TraitImplConstStable { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_trait_impl_const_stability_mismatch)] +#[diag("const stability on the impl does not match the const stability on the trait")] pub(crate) struct TraitImplConstStabilityMismatch { #[primary_span] pub span: Span, @@ -875,12 +945,12 @@ pub(crate) struct TraitImplConstStabilityMismatch { #[derive(Subdiagnostic)] pub(crate) enum TraitConstStability { - #[note(passes_trait_impl_const_stability_mismatch_trait_stable)] + #[note("...but the trait is stable")] Stable { #[primary_span] span: Span, }, - #[note(passes_trait_impl_const_stability_mismatch_trait_unstable)] + #[note("...but the trait is unstable")] Unstable { #[primary_span] span: Span, @@ -889,12 +959,12 @@ pub(crate) enum TraitConstStability { #[derive(Subdiagnostic)] pub(crate) enum ImplConstStability { - #[note(passes_trait_impl_const_stability_mismatch_impl_stable)] + #[note("this impl is (implicitly) stable...")] Stable { #[primary_span] span: Span, }, - #[note(passes_trait_impl_const_stability_mismatch_impl_unstable)] + #[note("this impl is unstable...")] Unstable { #[primary_span] span: Span, @@ -902,7 +972,7 @@ pub(crate) enum ImplConstStability { } #[derive(Diagnostic)] -#[diag(passes_unknown_feature, code = E0635)] +#[diag("unknown feature `{$feature}`", code = E0635)] pub(crate) struct UnknownFeature { #[primary_span] pub span: Span, @@ -913,7 +983,7 @@ pub(crate) struct UnknownFeature { #[derive(Subdiagnostic)] #[suggestion( - passes_misspelled_feature, + "there is a feature with a similar name: `{$actual_name}`", style = "verbose", code = "{actual_name}", applicability = "maybe-incorrect" @@ -925,7 +995,7 @@ pub(crate) struct MisspelledFeature { } #[derive(Diagnostic)] -#[diag(passes_unknown_feature_alias, code = E0635)] +#[diag("feature `{$alias}` has been renamed to `{$feature}`", code = E0635)] pub(crate) struct RenamedFeature { #[primary_span] pub span: Span, @@ -934,7 +1004,7 @@ pub(crate) struct RenamedFeature { } #[derive(Diagnostic)] -#[diag(passes_implied_feature_not_exist)] +#[diag("feature `{$implied_by}` implying `{$feature}` does not exist")] pub(crate) struct ImpliedFeatureNotExist { #[primary_span] pub span: Span, @@ -943,7 +1013,7 @@ pub(crate) struct ImpliedFeatureNotExist { } #[derive(Diagnostic)] -#[diag(passes_duplicate_feature_err, code = E0636)] +#[diag("the feature `{$feature}` has already been enabled", code = E0636)] pub(crate) struct DuplicateFeatureErr { #[primary_span] pub span: Span, @@ -951,25 +1021,37 @@ pub(crate) struct DuplicateFeatureErr { } #[derive(Diagnostic)] -#[diag(passes_missing_const_err)] +#[diag( + "attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`" +)] pub(crate) struct MissingConstErr { #[primary_span] - #[help] + #[help("make the function or method const")] pub fn_sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_const_stable_not_stable)] +#[diag( + "attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`" +)] pub(crate) struct ConstStableNotStable { #[primary_span] pub fn_sig_span: Span, - #[label] + #[label("attribute specified here")] pub const_span: Span, } #[derive(LintDiagnostic)] pub(crate) enum MultipleDeadCodes<'tcx> { - #[diag(passes_dead_codes)] + #[diag( + "{ $multiple -> + *[true] multiple {$descr}s are + [false] { $num -> + [one] {$descr} {$name_list} is + *[other] {$descr}s {$name_list} are + } + } never {$participle}" + )] DeadCodes { multiple: bool, num: usize, @@ -984,7 +1066,15 @@ pub(crate) enum MultipleDeadCodes<'tcx> { #[subdiagnostic] ignored_derived_impls: Option, }, - #[diag(passes_dead_codes)] + #[diag( + "{ $multiple -> + *[true] multiple {$descr}s are + [false] { $num -> + [one] {$descr} {$name_list} is + *[other] {$descr}s {$name_list} are + } + } never {$participle}" + )] UnusedTupleStructFields { multiple: bool, num: usize, @@ -1001,7 +1091,9 @@ pub(crate) enum MultipleDeadCodes<'tcx> { } #[derive(Subdiagnostic)] -#[note(passes_enum_variant_same_name)] +#[note( + "it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name" +)] pub(crate) struct EnumVariantSameName<'tcx> { #[primary_span] pub variant_span: Span, @@ -1010,7 +1102,12 @@ pub(crate) struct EnumVariantSameName<'tcx> { } #[derive(Subdiagnostic)] -#[label(passes_parent_info)] +#[label( + "{$num -> + [one] {$descr} + *[other] {$descr}s + } in this {$parent_descr}" +)] pub(crate) struct ParentInfo<'tcx> { pub num: usize, pub descr: &'tcx str, @@ -1020,7 +1117,15 @@ pub(crate) struct ParentInfo<'tcx> { } #[derive(Subdiagnostic)] -#[note(passes_ignored_derived_impls)] +#[note( + "`{$name}` has {$trait_list_len -> + [one] a derived impl + *[other] derived impls + } for the {$trait_list_len -> + [one] trait {$trait_list}, but this is + *[other] traits {$trait_list}, but these are + } intentionally ignored during dead code analysis" +)] pub(crate) struct IgnoredDerivedImpls { pub name: Symbol, pub trait_list: DiagSymbolList, @@ -1030,7 +1135,13 @@ pub(crate) struct IgnoredDerivedImpls { #[derive(Subdiagnostic)] pub(crate) enum ChangeFields { #[multipart_suggestion( - passes_change_fields_to_be_of_unit_type, + "consider changing the { $num -> + [one] field + *[other] fields + } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num -> + [one] field + *[other] fields + }", applicability = "has-placeholders" )] ChangeToUnitTypeOrRemove { @@ -1038,12 +1149,20 @@ pub(crate) enum ChangeFields { #[suggestion_part(code = "()")] spans: Vec, }, - #[help(passes_remove_fields)] + #[help( + "consider removing { $num -> + [one] this + *[other] these + } { $num -> + [one] field + *[other] fields + }" + )] Remove { num: usize }, } #[derive(Diagnostic)] -#[diag(passes_proc_macro_bad_sig)] +#[diag("{$kind} has incorrect signature")] pub(crate) struct ProcMacroBadSig { #[primary_span] pub span: Span, @@ -1051,18 +1170,30 @@ pub(crate) struct ProcMacroBadSig { } #[derive(LintDiagnostic)] -#[diag(passes_unnecessary_stable_feature)] +#[diag( + "the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable" +)] pub(crate) struct UnnecessaryStableFeature { pub feature: Symbol, pub since: Symbol, } #[derive(LintDiagnostic)] -#[diag(passes_unnecessary_partial_stable_feature)] +#[diag( + "the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`" +)] pub(crate) struct UnnecessaryPartialStableFeature { - #[suggestion(code = "{implies}", applicability = "maybe-incorrect")] + #[suggestion( + "if you are using features which are still unstable, change to using `{$implies}`", + code = "{implies}", + applicability = "maybe-incorrect" + )] pub span: Span, - #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")] + #[suggestion( + "if you are using features which are now stable, remove this line", + code = "", + applicability = "maybe-incorrect" + )] pub line: Span, pub feature: Symbol, pub since: Symbol, @@ -1070,38 +1201,36 @@ pub(crate) struct UnnecessaryPartialStableFeature { } #[derive(LintDiagnostic)] -#[diag(passes_ineffective_unstable_impl)] -#[note] +#[diag("an `#[unstable]` annotation here has no effect")] +#[note("see issue #55436 for more information")] pub(crate) struct IneffectiveUnstableImpl; -/// "sanitize attribute not allowed here" #[derive(Diagnostic)] -#[diag(passes_sanitize_attribute_not_allowed)] +#[diag("sanitize attribute not allowed here")] pub(crate) struct SanitizeAttributeNotAllowed { #[primary_span] pub attr_span: Span, - /// "not a function, impl block, or module" - #[label(passes_not_fn_impl_mod)] + #[label("not a function, impl block, or module")] pub not_fn_impl_mod: Option, - /// "function has no body" - #[label(passes_no_body)] + #[label("function has no body")] pub no_body: Option, - /// "sanitize attribute can be applied to a function (with body), impl block, or module" - #[help] + #[help("sanitize attribute can be applied to a function (with body), impl block, or module")] pub help: (), } // FIXME(jdonszelmann): move back to rustc_attr #[derive(Diagnostic)] -#[diag(passes_rustc_const_stable_indirect_pairing)] +#[diag( + "`const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied" +)] pub(crate) struct RustcConstStableIndirectPairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unsupported_attributes_in_where)] -#[help] +#[diag("most attributes are not supported in `where` clauses")] +#[help("only `#[cfg]` and `#[cfg_attr]` are supported")] pub(crate) struct UnsupportedAttributesInWhere { #[primary_span] pub span: MultiSpan, @@ -1109,100 +1238,100 @@ pub(crate) struct UnsupportedAttributesInWhere { #[derive(Diagnostic)] pub(crate) enum UnexportableItem<'a> { - #[diag(passes_unexportable_item)] + #[diag("{$descr}'s are not exportable")] Item { #[primary_span] span: Span, descr: &'a str, }, - #[diag(passes_unexportable_generic_fn)] + #[diag("generic functions are not exportable")] GenericFn(#[primary_span] Span), - #[diag(passes_unexportable_fn_abi)] + #[diag("only functions with \"C\" ABI are exportable")] FnAbi(#[primary_span] Span), - #[diag(passes_unexportable_type_repr)] + #[diag("types with unstable layout are not exportable")] TypeRepr(#[primary_span] Span), - #[diag(passes_unexportable_type_in_interface)] + #[diag("{$desc} with `#[export_stable]` attribute uses type `{$ty}`, which is not exportable")] TypeInInterface { #[primary_span] span: Span, desc: &'a str, ty: &'a str, - #[label] + #[label("not exportable")] ty_span: Span, }, - #[diag(passes_unexportable_priv_item)] + #[diag("private items are not exportable")] PrivItem { #[primary_span] span: Span, - #[note] + #[note("is only usable at visibility `{$vis_descr}`")] vis_note: Span, vis_descr: &'a str, }, - #[diag(passes_unexportable_adt_with_private_fields)] + #[diag("ADT types with private fields are not exportable")] AdtWithPrivFields { #[primary_span] span: Span, - #[note] + #[note("`{$field_name}` is private")] vis_note: Span, field_name: &'a str, }, } #[derive(Diagnostic)] -#[diag(passes_repr_align_should_be_align)] +#[diag("`#[repr(align(...))]` is not supported on {$item}")] pub(crate) struct ReprAlignShouldBeAlign { #[primary_span] - #[help] + #[help("use `#[rustc_align(...)]` instead")] pub span: Span, pub item: &'static str, } #[derive(Diagnostic)] -#[diag(passes_repr_align_should_be_align_static)] +#[diag("`#[repr(align(...))]` is not supported on {$item}")] pub(crate) struct ReprAlignShouldBeAlignStatic { #[primary_span] - #[help] + #[help("use `#[rustc_align_static(...)]` instead")] pub span: Span, pub item: &'static str, } #[derive(Diagnostic)] -#[diag(passes_custom_mir_phase_requires_dialect)] +#[diag("`dialect` key required")] pub(crate) struct CustomMirPhaseRequiresDialect { #[primary_span] pub attr_span: Span, - #[label] + #[label("`phase` argument requires a `dialect` argument")] pub phase_span: Span, } #[derive(Diagnostic)] -#[diag(passes_custom_mir_incompatible_dialect_and_phase)] +#[diag("the {$dialect} dialect is not compatible with the {$phase} phase")] pub(crate) struct CustomMirIncompatibleDialectAndPhase { pub dialect: MirDialect, pub phase: MirPhase, #[primary_span] pub attr_span: Span, - #[label] + #[label("this dialect...")] pub dialect_span: Span, - #[label] + #[label("... is not compatible with this phase")] pub phase_span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_impl_not_function)] +#[diag("`eii_macro_for` is only valid on functions")] pub(crate) struct EiiImplNotFunction { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_impl_requires_unsafe)] +#[diag("`#[{$name}]` is unsafe to implement")] pub(crate) struct EiiImplRequiresUnsafe { #[primary_span] pub span: Span, @@ -1212,10 +1341,7 @@ pub(crate) struct EiiImplRequiresUnsafe { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - passes_eii_impl_requires_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct EiiImplRequiresUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -1224,64 +1350,71 @@ pub(crate) struct EiiImplRequiresUnsafeSuggestion { } #[derive(Diagnostic)] -#[diag(passes_eii_fn_with_track_caller)] +#[diag("`#[{$name}]` is not allowed to have `#[track_caller]`")] pub(crate) struct EiiWithTrackCaller { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label("`#[{$name}]` is not allowed to have `#[track_caller]`")] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_without_impl)] +#[diag("`#[{$name}]` required, but not found")] pub(crate) struct EiiWithoutImpl { #[primary_span] - #[label] + #[label("expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}`")] pub span: Span, pub name: Symbol, pub current_crate_name: Symbol, pub decl_crate_name: Symbol, - #[help] + #[help( + "expected at least one implementation in crate `{$current_crate_name}` or any of its dependencies" + )] pub help: (), } #[derive(Diagnostic)] -#[diag(passes_duplicate_eii_impls)] +#[diag("multiple implementations of `#[{$name}]`")] pub(crate) struct DuplicateEiiImpls { pub name: Symbol, #[primary_span] - #[label(passes_first)] + #[label("first implemented here in crate `{$first_crate}`")] pub first_span: Span, pub first_crate: Symbol, - #[label(passes_second)] + #[label("also implemented here in crate `{$second_crate}`")] pub second_span: Span, pub second_crate: Symbol, - #[note] + #[note("in addition to these two, { $num_additional_crates -> + [one] another implementation was found in crate {$additional_crate_names} + *[other] more implementations were also found in the following crates: {$additional_crate_names} + }")] pub additional_crates: Option<()>, pub num_additional_crates: usize, pub additional_crate_names: String, - #[help] + #[help( + "an \"externally implementable item\" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict" + )] pub help: (), } #[derive(Diagnostic)] -#[diag(passes_function_not_have_default_implementation)] +#[diag("function doesn't have a default implementation")] pub(crate) struct FunctionNotHaveDefaultImplementation { #[primary_span] pub span: Span, - #[note] + #[note("required by this annotation")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(passes_must_implement_not_function)] +#[diag("not a function")] pub(crate) struct MustImplementNotFunction { #[primary_span] pub span: Span, @@ -1292,26 +1425,26 @@ pub(crate) struct MustImplementNotFunction { } #[derive(Subdiagnostic)] -#[note(passes_must_implement_not_function_span_note)] +#[note("required by this annotation")] pub(crate) struct MustImplementNotFunctionSpanNote { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[note(passes_must_implement_not_function_note)] +#[note("all `#[rustc_must_implement_one_of]` arguments must be associated function names")] pub(crate) struct MustImplementNotFunctionNote {} #[derive(Diagnostic)] -#[diag(passes_function_not_found_in_trait)] +#[diag("function not found in this trait")] pub(crate) struct FunctionNotFoundInTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_functions_names_duplicated)] -#[note] +#[diag("functions names are duplicated")] +#[note("all `#[rustc_must_implement_one_of]` arguments must be unique")] pub(crate) struct FunctionNamesDuplicated { #[primary_span] pub spans: Vec, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index b9417af13b11..25aea8e9f82a 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -11,16 +11,15 @@ use rustc_ast as ast; use rustc_ast::visit; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::{GenericRequirement, extract}; +use rustc_hir::lang_items::GenericRequirement; use rustc_hir::{LangItem, LanguageItems, MethodKind, Target}; use rustc_middle::query::Providers; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::cstore::ExternCrate; -use rustc_span::Span; +use rustc_span::{Span, Symbol, sym}; use crate::errors::{ DuplicateLangItem, IncorrectCrateType, IncorrectTarget, LangItemOnIncorrectTarget, - UnknownLangItem, }; use crate::weak_lang_items; @@ -62,7 +61,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { item_span: Span, generics: Option<&'ast ast::Generics>, ) { - if let Some((name, attr_span)) = extract(attrs) { + if let Some((name, attr_span)) = extract_ast(attrs) { match LangItem::from_name(name) { // Known lang item with attribute on correct target. Some(lang_item) if actual_target == lang_item.target() => { @@ -86,7 +85,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { } // Unknown lang item. _ => { - self.tcx.dcx().emit_err(UnknownLangItem { span: attr_span, name }); + self.tcx.dcx().delayed_bug("unknown lang item"); } } } @@ -359,6 +358,20 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { } } +/// Extracts the first `lang = "$name"` out of a list of attributes. +/// The `#[panic_handler]` attribute is also extracted out when found. +/// +/// This function is used for `ast::Attribute`, for `hir::Attribute` use the `find_attr!` macro with `AttributeKind::Lang` +pub(crate) fn extract_ast(attrs: &[rustc_ast::ast::Attribute]) -> Option<(Symbol, Span)> { + attrs.iter().find_map(|attr| { + Some(match attr { + _ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span()), + _ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span()), + _ => return None, + }) + }) +} + pub(crate) fn provide(providers: &mut Providers) { providers.get_lang_items = get_lang_items; } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 4054cfa56330..354a98d6d0dc 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -1,20 +1,18 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; -use rustc_hir::Attribute; +use rustc_hir::attrs::{AttributeKind, RustcLayoutType}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits; -use crate::errors::{ - LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf, - LayoutSize, UnrecognizedArgument, -}; +use crate::errors::{LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutOf, LayoutSize}; pub fn test_layout(tcx: TyCtxt<'_>) { if !tcx.features().rustc_attrs() { @@ -22,14 +20,14 @@ pub fn test_layout(tcx: TyCtxt<'_>) { return; } 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 => { - dump_layout_of(tcx, id, attr); - } - _ => { - tcx.dcx().emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) }); - } + let attrs = tcx.get_all_attrs(id); + if let Some(attrs) = find_attr!(attrs, AttributeKind::RustcLayout(attrs) => attrs) { + // Attribute parsing handles error reporting + if matches!( + tcx.def_kind(id), + DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union + ) { + dump_layout_of(tcx, id, attrs); } } } @@ -66,7 +64,7 @@ pub fn ensure_wf<'tcx>( } } -fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayoutType]) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id.to_def_id()); @@ -75,32 +73,29 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { } match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(ty_layout) => { - // Check out the `#[rustc_layout(..)]` attribute to tell what to dump. - // The `..` are the names of fields to dump. - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { + for attr in attrs { + match attr { // FIXME: this never was about ABI and now this dump arg is confusing - Some(sym::abi) => { + RustcLayoutType::Abi => { tcx.dcx().emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.backend_repr), }); } - Some(sym::align) => { + RustcLayoutType::Align => { tcx.dcx().emit_err(LayoutAlign { span, align: format!("{:?}", ty_layout.align), }); } - Some(sym::size) => { + RustcLayoutType::Size => { tcx.dcx() .emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) }); } - Some(sym::homogeneous_aggregate) => { + RustcLayoutType::HomogenousAggregate => { tcx.dcx().emit_err(LayoutHomogeneousAggregate { span, homogeneous_aggregate: format!( @@ -111,16 +106,12 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { }); } - Some(sym::debug) => { + RustcLayoutType::Debug => { let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); } - - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); - } } } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index d371589cba6c..dea57cf4eba5 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -4,11 +4,6 @@ //! //! This API is completely unstable and subject to change. -// tidy-alphabetical-start -#![feature(if_let_guard)] -#![feature(map_try_insert)] -// tidy-alphabetical-end - use rustc_middle::query::Providers; pub mod abi_test; @@ -30,8 +25,6 @@ pub mod stability; mod upvars; mod weak_lang_items; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { check_attr::provide(providers); dead::provide(providers); diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 8d0ef88610af..1f92643815fd 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -30,10 +30,10 @@ impl<'tcx> LibFeatureCollector<'tcx> { Attribute::Parsed(AttributeKind::Stability { stability, span }) => { (stability.feature, stability.level, *span) } - Attribute::Parsed(AttributeKind::ConstStability { stability, span }) => { + Attribute::Parsed(AttributeKind::RustcConstStability { stability, span }) => { (stability.feature, stability.level, *span) } - Attribute::Parsed(AttributeKind::BodyStability { stability, span }) => { + Attribute::Parsed(AttributeKind::RustcBodyStability { stability, span }) => { (stability.feature, stability.level, *span) } _ => return None, diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index d9565e2dae0e..225487cc989f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -145,7 +145,7 @@ impl<'tcx> ReachableContext<'tcx> { _ => false, }, Node::TraitItem(trait_method) => match trait_method.kind { - hir::TraitItemKind::Const(_, ref default) => default.is_some(), + hir::TraitItemKind::Const(_, ref default, _) => default.is_some(), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, @@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body); } } - // For #[type_const] we want to evaluate the RHS. + // For `type const` we want to evaluate the RHS. hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => { self.visit_const_item_rhs(init); } @@ -258,11 +258,11 @@ impl<'tcx> ReachableContext<'tcx> { } Node::TraitItem(trait_method) => { match trait_method.kind { - hir::TraitItemKind::Const(_, None) + hir::TraitItemKind::Const(_, None, _) | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } - hir::TraitItemKind::Const(_, Some(rhs)) => self.visit_const_item_rhs(rhs), + hir::TraitItemKind::Const(_, Some(rhs), _) => self.visit_const_item_rhs(rhs), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9d94c4cc6225..657b362d5ca1 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -197,7 +197,7 @@ fn lookup_default_body_stability( let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); // FIXME: check that this item can have body stability - find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability) + find_attr!(attrs, AttributeKind::RustcBodyStability { stability, .. } => *stability) } #[instrument(level = "debug", skip(tcx))] @@ -214,7 +214,7 @@ fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option, def_id: LocalDefId) -> Option *stability); + find_attr!(attrs, AttributeKind::RustcConstStability { stability, span: _ } => *stability); // After checking the immediate attributes, get rid of the span and compute implied // const stability: inherit feature gate from regular stability. @@ -393,7 +393,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { if let Some(fn_sig) = fn_sig && !fn_sig.header.is_const() && const_stab.is_some() - && find_attr_span!(ConstStability).is_some() + && find_attr_span!(RustcConstStability).is_some() { self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span }); } @@ -403,7 +403,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { && let Some(fn_sig) = fn_sig && const_stab.is_const_stable() && !stab.is_some_and(|s| s.is_stable()) - && let Some(const_span) = find_attr_span!(ConstStability) + && let Some(const_span) = find_attr_span!(RustcConstStability) { self.tcx .dcx() @@ -413,7 +413,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { if let Some(stab) = &const_stab && stab.is_const_stable() && stab.const_stable_indirect - && let Some(span) = find_attr_span!(ConstStability) + && let Some(span) = find_attr_span!(RustcConstStability) { self.tcx.dcx().emit_err(errors::RustcConstStableIndirectPairing { span }); } @@ -602,7 +602,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { let stab = find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span)); // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - let const_stab = find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability); + let const_stab = find_attr!(attrs, AttributeKind::RustcConstStability{stability, ..} => *stability); let unstable_feature_stab = find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i) diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 811b5e930014..4200003ea1d1 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -13,6 +13,7 @@ use rustc_target::spec::Os; use crate::errors::{ MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem, }; +use crate::lang_items::extract_ast; /// Checks the crate for usage of weak lang items, returning a vector of all the /// lang items required by this crate, but not defined yet. @@ -46,7 +47,7 @@ struct WeakLangItemVisitor<'a, 'tcx> { impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_, '_> { fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) { - if let Some((lang_item, _)) = lang_items::extract(&i.attrs) { + if let Some((lang_item, _)) = extract_ast(&i.attrs) { if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() { diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index a59f7bbeb9e5..a644c6a7c01a 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -11,7 +11,6 @@ rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_errors = { path = "../rustc_errors", optional = true } -rustc_fluent_macro = { path = "../rustc_fluent_macro", optional = true } rustc_hir = { path = "../rustc_hir", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } @@ -36,7 +35,6 @@ rustc = [ "dep:rustc_arena", "dep:rustc_data_structures", "dep:rustc_errors", - "dep:rustc_fluent_macro", "dep:rustc_hir", "dep:rustc_macros", "dep:rustc_middle", diff --git a/compiler/rustc_pattern_analysis/messages.ftl b/compiler/rustc_pattern_analysis/messages.ftl deleted file mode 100644 index d3a3107f8e89..000000000000 --- a/compiler/rustc_pattern_analysis/messages.ftl +++ /dev/null @@ -1,31 +0,0 @@ -pattern_analysis_excluside_range_missing_gap = multiple ranges are one apart - .label = this range doesn't match `{$gap}` because `..` is an exclusive range - .suggestion = use an inclusive range instead - -pattern_analysis_excluside_range_missing_max = exclusive range missing `{$max}` - .label = this range doesn't match `{$max}` because `..` is an exclusive range - .suggestion = use an inclusive range instead - -pattern_analysis_mixed_deref_pattern_constructors = mix of deref patterns and normal constructors - .deref_pattern_label = matches on the result of dereferencing `{$smart_pointer_ty}` - .normal_constructor_label = matches directly on `{$smart_pointer_ty}` - -pattern_analysis_non_exhaustive_omitted_pattern = some variants are not matched explicitly - .help = ensure that all variants are matched explicitly by adding the suggested match arms - .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found - -pattern_analysis_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match - .help = it no longer has any effect to set the lint level on an individual match arm - .label = remove this attribute - .suggestion = set the lint level on the whole match - -pattern_analysis_overlapping_range_endpoints = multiple patterns overlap on their endpoints - .label = ... with this range - .note = you likely meant to write mutually exclusive ranges - -pattern_analysis_uncovered = {$count -> - [1] pattern `{$witness_1}` - [2] patterns `{$witness_1}` and `{$witness_2}` - [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}` - *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more - } not covered diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 156ba9737673..e7448613cc14 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -6,7 +6,14 @@ use rustc_span::Span; use crate::rustc::{RustcPatCtxt, WitnessPat}; #[derive(Subdiagnostic)] -#[label(pattern_analysis_uncovered)] +#[label( + "{$count -> + [1] pattern `{$witness_1}` + [2] patterns `{$witness_1}` and `{$witness_2}` + [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}` + *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more + } not covered" +)] pub struct Uncovered { #[primary_span] span: Span, @@ -40,36 +47,32 @@ impl Uncovered { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_overlapping_range_endpoints)] -#[note] +#[diag("multiple patterns overlap on their endpoints")] +#[note("you likely meant to write mutually exclusive ranges")] pub struct OverlappingRangeEndpoints { - #[label] + #[label("... with this range")] pub range: Span, #[subdiagnostic] pub overlap: Vec, } +#[derive(Subdiagnostic)] +#[label("this range overlaps on `{$range}`...")] pub struct Overlap { + #[primary_span] pub span: Span, pub range: String, // a printed pattern } -impl Subdiagnostic for Overlap { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let Overlap { span, range } = self; - - // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` - // does not support `#[subdiagnostic(eager)]`... - let message = format!("this range overlaps on `{range}`..."); - diag.span_label(span, message); - } -} - #[derive(LintDiagnostic)] -#[diag(pattern_analysis_excluside_range_missing_max)] +#[diag("exclusive range missing `{$max}`")] pub struct ExclusiveRangeMissingMax { - #[label] - #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + #[label("this range doesn't match `{$max}` because `..` is an exclusive range")] + #[suggestion( + "use an inclusive range instead", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`). pub first_range: Span, /// Suggest `lo..=max` instead. @@ -78,10 +81,14 @@ pub struct ExclusiveRangeMissingMax { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_excluside_range_missing_gap)] +#[diag("multiple ranges are one apart")] pub struct ExclusiveRangeMissingGap { - #[label] - #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + #[label("this range doesn't match `{$gap}` because `..` is an exclusive range")] + #[suggestion( + "use an inclusive range instead", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`). pub first_range: Span, pub gap: String, // a printed pattern @@ -113,9 +120,11 @@ impl Subdiagnostic for GappedRange { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_non_exhaustive_omitted_pattern)] -#[help] -#[note] +#[diag("some variants are not matched explicitly")] +#[help("ensure that all variants are matched explicitly by adding the suggested match arms")] +#[note( + "the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found" +)] pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub scrut_ty: Ty<'tcx>, #[subdiagnostic] @@ -123,25 +132,29 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_non_exhaustive_omitted_pattern_lint_on_arm)] -#[help] +#[diag("the lint level must be set on the whole match")] +#[help("it no longer has any effect to set the lint level on an individual match arm")] pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { - #[label] + #[label("remove this attribute")] pub lint_span: Span, - #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")] + #[suggestion( + "set the lint level on the whole match", + code = "#[{lint_level}({lint_name})]\n", + applicability = "maybe-incorrect" + )] pub suggest_lint_on_match: Option, pub lint_level: &'static str, pub lint_name: &'static str, } #[derive(Diagnostic)] -#[diag(pattern_analysis_mixed_deref_pattern_constructors)] +#[diag("mix of deref patterns and normal constructors")] pub(crate) struct MixedDerefPatternConstructors<'tcx> { #[primary_span] pub spans: Vec, pub smart_pointer_ty: Ty<'tcx>, - #[label(pattern_analysis_deref_pattern_label)] + #[label("matches on the result of dereferencing `{$smart_pointer_ty}`")] pub deref_pattern_label: Span, - #[label(pattern_analysis_normal_constructor_label)] + #[label("matches directly on `{$smart_pointer_ty}`")] pub normal_constructor_label: Span, } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 265284086377..059bf47c579c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -4,7 +4,6 @@ // tidy-alphabetical-start #![allow(unused_crate_dependencies)] -#![cfg_attr(feature = "rustc", feature(if_let_guard))] // tidy-alphabetical-end pub(crate) mod checks; @@ -19,9 +18,6 @@ pub mod pat_column; pub mod rustc; pub mod usefulness; -#[cfg(feature = "rustc")] -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - use std::fmt; pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index version issues diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 3e97842b7f39..dc38f2d8bc70 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -4,8 +4,8 @@ use std::iter::once; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; +use rustc_hir::HirId; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId}; use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; @@ -471,9 +471,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::Deref { pin, subpattern } => { fields = vec![self.lower_pat(subpattern).at_index(0)]; arity = 1; - ctor = match pin { - hir::Pinnedness::Not if ty.is_ref() => Ref, - hir::Pinnedness::Pinned if let Some((inner_ty, _)) = ty.pinned_ref() => { + ctor = match (pin, ty.maybe_pinned_ref()) { + (ty::Pinnedness::Not, Some((_, ty::Pinnedness::Not, _, _))) => Ref, + (ty::Pinnedness::Pinned, Some((inner_ty, ty::Pinnedness::Pinned, _, _))) => { self.internal_state.has_lowered_deref_pat.set(true); DerefPattern(RevealedTy(inner_ty)) } diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index c8bfdb913041..ff59c19b6bb6 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl deleted file mode 100644 index 43c34a109d72..000000000000 --- a/compiler/rustc_privacy/messages.ftl +++ /dev/null @@ -1,39 +0,0 @@ -privacy_field_is_private = - {$len -> - [1] field - *[other] fields - } {$field_names} of {$variant_descr} `{$def_path_str}` {$len -> - [1] is - *[other] are - } private - .label = in this type -privacy_field_is_private_is_update_syntax_label = {$rest_len -> - [1] field - *[other] fields - } {$rest_field_names} {$rest_len -> - [1] is - *[other] are - } private -privacy_field_is_private_label = private field - -privacy_from_private_dep_in_public_interface = - {$kind} `{$descr}` from private dependency '{$krate}' in public interface - -privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface - .label = can't leak {$vis_descr} {$kind} - .visibility_label = `{$descr}` declared as {$vis_descr} - -privacy_item_is_private = {$kind} `{$descr}` is private - .label = private {$kind} - -privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}` - .item_label = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}` - .ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}` - -privacy_report_effective_visibility = {$descr} - -privacy_unnameable_types_lint = {$kind} `{$descr}` is reachable but cannot be named - .label = reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}` - -privacy_unnamed_item_is_private = {$kind} is private - .label = private {$kind} diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 4d1d58c08528..af4f0d61aa11 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -4,11 +4,17 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(privacy_field_is_private, code = E0451)] +#[diag("{$len -> + [1] field + *[other] fields +} {$field_names} of {$variant_descr} `{$def_path_str}` {$len -> + [1] is + *[other] are +} private", code = E0451)] pub(crate) struct FieldIsPrivate { #[primary_span] pub span: MultiSpan, - #[label] + #[label("in this type")] pub struct_span: Option, pub field_names: String, pub variant_descr: &'static str, @@ -20,14 +26,22 @@ pub(crate) struct FieldIsPrivate { #[derive(Subdiagnostic)] pub(crate) enum FieldIsPrivateLabel { - #[label(privacy_field_is_private_is_update_syntax_label)] + #[label( + "{$rest_len -> + [1] field + *[other] fields + } {$rest_field_names} {$rest_len -> + [1] is + *[other] are + } private" + )] IsUpdateSyntax { #[primary_span] span: Span, rest_field_names: String, rest_len: usize, }, - #[label(privacy_field_is_private_label)] + #[label("private field")] Other { #[primary_span] span: Span, @@ -35,17 +49,17 @@ pub(crate) enum FieldIsPrivateLabel { } #[derive(Diagnostic)] -#[diag(privacy_item_is_private)] +#[diag("{$kind} `{$descr}` is private")] pub(crate) struct ItemIsPrivate<'a> { #[primary_span] - #[label] + #[label("private {$kind}")] pub span: Span, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, } #[derive(Diagnostic)] -#[diag(privacy_unnamed_item_is_private)] +#[diag("{$kind} is private")] pub(crate) struct UnnamedItemIsPrivate { #[primary_span] pub span: Span, @@ -53,20 +67,20 @@ pub(crate) struct UnnamedItemIsPrivate { } #[derive(Diagnostic)] -#[diag(privacy_in_public_interface, code = E0446)] +#[diag("{$vis_descr} {$kind} `{$descr}` in public interface", code = E0446)] pub(crate) struct InPublicInterface<'a> { #[primary_span] - #[label] + #[label("can't leak {$vis_descr} {$kind}")] pub span: Span, pub vis_descr: &'static str, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, - #[label(privacy_visibility_label)] + #[label("`{$descr}` declared as {$vis_descr}")] pub vis_span: Span, } #[derive(Diagnostic)] -#[diag(privacy_report_effective_visibility)] +#[diag("{$descr}")] pub(crate) struct ReportEffectiveVisibility { #[primary_span] pub span: Span, @@ -74,7 +88,7 @@ pub(crate) struct ReportEffectiveVisibility { } #[derive(LintDiagnostic)] -#[diag(privacy_from_private_dep_in_public_interface)] +#[diag("{$kind} `{$descr}` from private dependency '{$krate}' in public interface")] pub(crate) struct FromPrivateDependencyInPublicInterface<'a> { pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, @@ -82,9 +96,11 @@ pub(crate) struct FromPrivateDependencyInPublicInterface<'a> { } #[derive(LintDiagnostic)] -#[diag(privacy_unnameable_types_lint)] +#[diag("{$kind} `{$descr}` is reachable but cannot be named")] pub(crate) struct UnnameableTypesLint<'a> { - #[label] + #[label( + "reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}`" + )] pub span: Span, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, @@ -96,14 +112,14 @@ pub(crate) struct UnnameableTypesLint<'a> { // They will replace private-in-public errors and compatibility lints in future. // See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details. #[derive(LintDiagnostic)] -#[diag(privacy_private_interface_or_bounds_lint)] +#[diag("{$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}`")] pub(crate) struct PrivateInterfacesOrBoundsLint<'a> { - #[label(privacy_item_label)] + #[label("{$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`")] pub item_span: Span, pub item_kind: &'a str, pub item_descr: DiagArgFromDisplay<'a>, pub item_vis_descr: &'a str, - #[note(privacy_ty_note)] + #[note("but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}`")] pub ty_span: Span, pub ty_kind: &'a str, pub ty_descr: DiagArgFromDisplay<'a>, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8656ec6e39ae..9a952bb72195 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,5 +1,6 @@ // tidy-alphabetical-start #![feature(associated_type_defaults)] +#![feature(default_field_values)] #![feature(try_blocks)] // tidy-alphabetical-end @@ -29,8 +30,8 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, use rustc_middle::query::Providers; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitor, + self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -38,8 +39,6 @@ use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol, sym}; use tracing::debug; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - //////////////////////////////////////////////////////////////////////////////// // Generic infrastructure used to implement specific visitors below. //////////////////////////////////////////////////////////////////////////////// @@ -311,6 +310,18 @@ where } } +fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool { + if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind + && let hir::Node::TraitItem(item) = + tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local())) + && let hir::TraitItemKind::Type(_, None) = item.kind + { + false + } else { + true + } +} + fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility { if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } } @@ -497,7 +508,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id); let attrs = self.tcx.hir_attrs(hir_id); - if find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) + if find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(md.macro_rules)) != Transparency::Opaque { @@ -639,6 +650,19 @@ impl<'tcx> EmbargoVisitor<'tcx> { } impl<'tcx> EmbargoVisitor<'tcx> { + fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) { + let def_id = item.def_id.expect_local(); + let tcx = self.tcx; + let mut reach = self.reach(def_id, item_ev); + reach.generics().predicates(); + if assoc_has_type_of(tcx, item) { + reach.ty(); + } + if item.is_type() && item.container == AssocContainer::Trait { + reach.bounds(); + } + } + fn check_def_id(&mut self, owner_id: OwnerId) { // Update levels of nested things and mark all items // in interfaces of reachable items as reachable. @@ -669,22 +693,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.reach(owner_id.def_id, item_ev).generics().predicates(); for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let def_id = assoc_item.def_id.expect_local(); self.update(def_id, item_ev, Level::Reachable); - let tcx = self.tcx; - let mut reach = self.reach(def_id, item_ev); - reach.generics().predicates(); - - if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() { - // No type to visit. - } else { - reach.ty(); - } + self.check_assoc_item(assoc_item, item_ev); } } } @@ -722,17 +734,13 @@ impl<'tcx> EmbargoVisitor<'tcx> { } for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let def_id = assoc_item.def_id.expect_local(); let max_vis = if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) }; self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct); if let Some(impl_item_ev) = self.get(def_id) { - self.reach(def_id, impl_item_ev).generics().predicates().ty(); + self.check_assoc_item(assoc_item, impl_item_ev); } } } @@ -824,7 +832,12 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { } fn predicates(&mut self) -> &mut Self { - self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id)); + self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id)); + self + } + + fn bounds(&mut self) -> &mut Self { + self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder()); self } @@ -863,7 +876,7 @@ pub struct TestReachabilityVisitor<'a, 'tcx> { impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { fn effective_visibility_diagnostic(&self, def_id: LocalDefId) { - if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::RustcEffectiveVisibility) { let mut error_msg = String::new(); let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { @@ -1144,14 +1157,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { let typeck_results = self .maybe_typeck_results .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body")); - let result: ControlFlow<()> = try { + try { self.visit(typeck_results.node_type(id))?; self.visit(typeck_results.node_args(id))?; if let Some(adjustments) = typeck_results.adjustments().get(id) { adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?; } - }; - result.is_break() + } + .is_break() } fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { @@ -1353,26 +1366,20 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, required_effective_vis: Option, - in_assoc_ty: bool, - in_primary_interface: bool, - skip_assoc_tys: bool, + hard_error: bool = false, + in_primary_interface: bool = true, + skip_assoc_tys: bool = false, } impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { self.in_primary_interface = true; for param in &self.tcx.generics_of(self.item_def_id).own_params { - match param.kind { - GenericParamDefKind::Lifetime => {} - GenericParamDefKind::Type { has_default, .. } => { - if has_default { - let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); - } - } - // FIXME(generic_const_exprs): May want to look inside const here - GenericParamDefKind::Const { .. } => { - let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); - } + if let GenericParamDefKind::Const { .. } = param.kind { + let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); + } + if let Some(default) = param.default_value(self.tcx) { + let _ = self.visit(default.instantiate_identity()); } } self @@ -1427,7 +1434,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let vis = self.tcx.local_visibility(local_def_id); - if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) { + if self.hard_error && !vis.is_at_least(self.required_visibility, self.tcx) { let vis_descr = match vis { ty::Visibility::Public => "public", ty::Visibility::Restricted(vis_def_id) => { @@ -1544,9 +1551,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { item_def_id: def_id, required_visibility, required_effective_vis, - in_assoc_ty: false, - in_primary_interface: true, - skip_assoc_tys: false, + .. } } @@ -1584,16 +1589,17 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { ) { let mut check = self.check(item.def_id.expect_local(), vis, effective_vis); - let (check_ty, is_assoc_ty) = match item.kind { - ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false), - ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true), - }; - - check.in_assoc_ty = is_assoc_ty; + let is_assoc_ty = item.is_type(); + check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait(); check.generics().predicates(); - if check_ty { + if assoc_has_type_of(self.tcx, item) { + check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value(); check.ty(); } + if is_assoc_ty && item.container == AssocContainer::Trait { + check.hard_error = false; + check.bounds(); + } } fn get(&self, def_id: LocalDefId) -> Option { @@ -1625,20 +1631,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { self.check(def_id, item_visibility, effective_vis).generics().predicates(); for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - self.check_assoc_item(assoc_item, item_visibility, effective_vis); - - if assoc_item.is_type() { - self.check( - assoc_item.def_id.expect_local(), - item_visibility, - effective_vis, - ) - .bounds(); - } } } DefKind::TraitAlias => { @@ -1712,10 +1705,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { } for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let impl_item_vis = if !of_trait { min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx) } else { diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 73a3fed111b3..8594f6510041 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -433,7 +433,7 @@ where } impl RustcInternal for BoundVariableKind { - type T<'tcx> = rustc_ty::BoundVariableKind; + type T<'tcx> = rustc_ty::BoundVariableKind<'tcx>; fn internal<'tcx>( &self, diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index cee144122c0e..70cdae43126c 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -271,7 +271,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { } } -impl<'tcx> Stable<'tcx> for ty::BoundTyKind { +impl<'tcx> Stable<'tcx> for ty::BoundTyKind<'tcx> { type T = crate::ty::BoundTyKind; fn stable<'cx>( @@ -290,7 +290,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { } } -impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { +impl<'tcx> Stable<'tcx> for ty::BoundRegionKind<'tcx> { type T = crate::ty::BoundRegionKind; fn stable<'cx>( @@ -307,12 +307,12 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { cx.tcx.item_name(*def_id).to_string(), ), ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv, - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"), } } } -impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { +impl<'tcx> Stable<'tcx> for ty::BoundVariableKind<'tcx> { type T = crate::ty::BoundVariableKind; fn stable<'cx>( @@ -546,7 +546,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy { } } -impl<'tcx> Stable<'tcx> for ty::BoundTy { +impl<'tcx> Stable<'tcx> for ty::BoundTy<'tcx> { type T = crate::ty::BoundTy; fn stable<'cx>( &self, diff --git a/compiler/rustc_public/src/unstable/internal_cx/mod.rs b/compiler/rustc_public/src/unstable/internal_cx/mod.rs index 601ca4fb5cfd..4da86b9442f1 100644 --- a/compiler/rustc_public/src/unstable/internal_cx/mod.rs +++ b/compiler/rustc_public/src/unstable/internal_cx/mod.rs @@ -78,7 +78,10 @@ impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: ty::CollectAndApply>, + T: ty::CollectAndApply< + ty::BoundVariableKind<'tcx>, + &'tcx List>, + >, { TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) } diff --git a/compiler/rustc_public/src/unstable/mod.rs b/compiler/rustc_public/src/unstable/mod.rs index 2b69fb5408cf..583493c23d66 100644 --- a/compiler/rustc_public/src/unstable/mod.rs +++ b/compiler/rustc_public/src/unstable/mod.rs @@ -47,7 +47,10 @@ pub trait InternalCx<'tcx>: Copy + Clone { fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: ty::CollectAndApply>; + T: ty::CollectAndApply< + ty::BoundVariableKind<'tcx>, + &'tcx List>, + >; fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List>; diff --git a/compiler/rustc_public_bridge/src/lib.rs b/compiler/rustc_public_bridge/src/lib.rs index 025ec0e7a8c8..dd5a3601b323 100644 --- a/compiler/rustc_public_bridge/src/lib.rs +++ b/compiler/rustc_public_bridge/src/lib.rs @@ -14,7 +14,6 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_ty_tykind)] #![doc(test(attr(allow(unused_variables), deny(warnings), allow(internal_features))))] -#![feature(sized_hierarchy)] #![feature(trait_alias)] // tidy-alphabetical-end diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 257785b10c8b..a8edc1129481 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -6,13 +6,18 @@ edition = "2024" [dependencies] # tidy-alphabetical-start measureme = "12.0.1" +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } 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_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_thread_pool = { path = "../rustc_thread_pool" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs new file mode 100644 index 000000000000..99feeb86bac9 --- /dev/null +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -0,0 +1,173 @@ +use rustc_middle::bug; +use rustc_middle::dep_graph::{DepKindVTable, DepNodeKey, FingerprintStyle}; +use rustc_middle::query::QueryCache; +use rustc_middle::ty::TyCtxt; + +use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner}; +use crate::{QueryCtxt, QueryDispatcherUnerased, QueryFlags}; + +/// [`DepKindVTable`] constructors for special dep kinds that aren't queries. +#[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")] +mod non_query { + use super::*; + + // We use this for most things when incr. comp. is turned off. + pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + 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", + } + } + + // We use this for the forever-red node. + pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + 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", + } + } + + pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|tcx, _, prev_index| { + tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index); + true + }), + try_load_from_on_disk_cache: None, + name: &"SideEffect", + } + } + + pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: true, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Opaque, + force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")), + try_load_from_on_disk_cache: None, + name: &"AnonZeroDeps", + } + } + + pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: true, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: &"TraitSelect", + } + } + + pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Opaque, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: &"CompileCodegenUnit", + } + } + + pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Opaque, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: &"CompileMonoItem", + } + } + + pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> { + DepKindVTable { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: &"Metadata", + } + } +} + +/// Shared implementation of the [`DepKindVTable`] constructor for queries. +/// Called from macro-generated code for each query. +pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q, Cache, const FLAGS: QueryFlags>( + is_eval_always: bool, +) -> DepKindVTable<'tcx> +where + Q: QueryDispatcherUnerased<'tcx, Cache, FLAGS>, + Cache: QueryCache + 'tcx, +{ + let is_anon = FLAGS.is_anon; + let fingerprint_style = if is_anon { + FingerprintStyle::Opaque + } else { + >>::fingerprint_style() + }; + + if is_anon || !fingerprint_style.reconstructible() { + return DepKindVTable { + is_anon, + is_eval_always, + fingerprint_style, + force_from_dep_node: None, + try_load_from_on_disk_cache: None, + name: Q::NAME, + }; + } + + DepKindVTable { + is_anon, + is_eval_always, + fingerprint_style, + force_from_dep_node: Some(|tcx, dep_node, _| { + force_from_dep_node_inner(Q::query_dispatcher(tcx), tcx, dep_node) + }), + try_load_from_on_disk_cache: Some(|tcx, dep_node| { + try_load_from_on_disk_cache_inner(Q::query_dispatcher(tcx), tcx, dep_node) + }), + name: Q::NAME, + } +} + +/// Helper module containing a [`DepKindVTable`] constructor for each dep kind, +/// for use with [`rustc_middle::make_dep_kind_array`]. +/// +/// That macro will check that we gave it a constructor for every known dep kind. +mod _dep_kind_vtable_ctors { + // Re-export all of the vtable constructors for non-query and query dep kinds. + + // Non-query vtable constructors are defined in normal code. + pub(crate) use super::non_query::*; + // Query vtable constructors are defined via a macro. + pub(crate) use crate::_dep_kind_vtable_ctors_for_queries::*; +} + +pub fn make_dep_kind_vtables<'tcx>( + arena: &'tcx rustc_middle::arena::Arena<'tcx>, +) -> &'tcx [DepKindVTable<'tcx>] { + // Create an array of vtables, one for each dep kind (non-query and query). + let dep_kind_vtables: [DepKindVTable<'tcx>; _] = + rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors); + arena.alloc_from_iter(dep_kind_vtables) +} diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_impl/src/error.rs similarity index 51% rename from compiler/rustc_query_system/src/error.rs rename to compiler/rustc_query_impl/src/error.rs index 4b1effe2b33d..6d3eb2950982 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_impl/src/error.rs @@ -3,8 +3,29 @@ use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; +#[derive(Diagnostic)] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] +#[diag("queries overflow the depth limit!")] +pub(crate) struct QueryOverflow { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub note: QueryOverflowNote, + pub suggested_limit: Limit, + pub crate_name: Symbol, +} + #[derive(Subdiagnostic)] -#[note(query_system_cycle_stack_middle)] +#[note("query depth increased by {$depth} when {$desc}")] +pub(crate) struct QueryOverflowNote { + pub desc: String, + pub depth: usize, +} + +#[derive(Subdiagnostic)] +#[note("...which requires {$desc}...")] pub(crate) struct CycleStack { #[primary_span] pub span: Span, @@ -13,24 +34,26 @@ pub(crate) struct CycleStack { #[derive(Subdiagnostic)] pub(crate) enum StackCount { - #[note(query_system_cycle_stack_single)] + #[note("...which immediately requires {$stack_bottom} again")] Single, - #[note(query_system_cycle_stack_multiple)] + #[note("...which again requires {$stack_bottom}, completing the cycle")] Multiple, } #[derive(Subdiagnostic)] pub(crate) enum Alias { - #[note(query_system_cycle_recursive_ty_alias)] - #[help(query_system_cycle_recursive_ty_alias_help1)] - #[help(query_system_cycle_recursive_ty_alias_help2)] + #[note("type aliases cannot be recursive")] + #[help("consider using a struct, enum, or union instead to break the cycle")] + #[help( + "see for more information" + )] Ty, - #[note(query_system_cycle_recursive_trait_alias)] + #[note("trait aliases cannot be recursive")] Trait, } #[derive(Subdiagnostic)] -#[note(query_system_cycle_usage)] +#[note("cycle used when {$usage}")] pub(crate) struct CycleUsage { #[primary_span] pub span: Span, @@ -38,7 +61,7 @@ pub(crate) struct CycleUsage { } #[derive(Diagnostic)] -#[diag(query_system_cycle, code = E0391)] +#[diag("cycle detected when {$stack_bottom}", code = E0391)] pub(crate) struct Cycle { #[primary_span] pub span: Span, @@ -51,40 +74,8 @@ pub(crate) struct Cycle { pub alias: Option, #[subdiagnostic] pub cycle_usage: Option, - #[note] + #[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" + )] pub note_span: (), } - -#[derive(Diagnostic)] -#[diag(query_system_reentrant)] -pub(crate) struct Reentrant; - -#[derive(Diagnostic)] -#[diag(query_system_increment_compilation)] -#[note(query_system_increment_compilation_note1)] -#[note(query_system_increment_compilation_note2)] -#[note(query_system_increment_compilation_note3)] -#[note(query_system_increment_compilation_note4)] -pub(crate) struct IncrementCompilation { - pub run_cmd: String, - pub dep_node: String, -} - -#[derive(Diagnostic)] -#[help] -#[diag(query_system_query_overflow)] -pub struct QueryOverflow { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub note: QueryOverflowNote, - pub suggested_limit: Limit, - pub crate_name: Symbol, -} - -#[derive(Subdiagnostic)] -#[note(query_system_overflow_note)] -pub struct QueryOverflowNote { - pub desc: String, - pub depth: usize, -} diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_impl/src/execution.rs similarity index 51% rename from compiler/rustc_query_system/src/query/plumbing.rs rename to compiler/rustc_query_impl/src/execution.rs index 9afad1546e9e..4df55e46e13e 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -1,189 +1,159 @@ -//! The implementation of the query system itself. This defines the macros that -//! generate the actual methods on tcx which find and execute the provider, -//! manage the caches, and so forth. - -use std::cell::Cell; -use std::fmt::Debug; use std::hash::Hash; use std::mem; -use hashbrown::HashTable; -use hashbrown::hash_table::Entry; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::sharded::{self, Sharded}; +use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::LockGuard; -use rustc_data_structures::{outline, sync}; +use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; -use rustc_span::{DUMMY_SP, Span}; -use tracing::instrument; - -use super::{QueryDispatcher, QueryStackFrameExtra}; -use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams}; -use crate::ich::StableHashingContext; -use crate::query::caches::QueryCache; -use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; -use crate::query::{ - CycleErrorHandling, QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex, +use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, DepsType, HasDepContext}; +use rustc_middle::query::{ + ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, + QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, }; +use rustc_middle::ty::TyCtxt; +use rustc_middle::verify_ich::incremental_verify_ich; +use rustc_span::{DUMMY_SP, Span}; + +use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; +use crate::job::{QueryJobInfo, QueryJobMap, find_cycle_in_stack, report_cycle}; +use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; #[inline] fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } -pub struct QueryState { - active: Sharded)>>, -} - -/// Indicates the state of a query for a given key in a query map. -enum QueryResult { - /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), - - /// The query panicked. Queries trying to wait on this will raise a fatal error which will - /// silently panic. - Poisoned, -} - -impl QueryResult { - /// Unwraps the query job expecting that it has started. - fn expect_job(self) -> QueryJob { - match self { - Self::Started(job) => job, - Self::Poisoned => { - panic!("job for query failed to start and was poisoned") - } +/// Obtains the enclosed [`QueryJob`], or panics if this query evaluation +/// was poisoned by a panic. +fn expect_job<'tcx>(status: ActiveKeyStatus<'tcx>) -> QueryJob<'tcx> { + match status { + ActiveKeyStatus::Started(job) => job, + ActiveKeyStatus::Poisoned => { + panic!("job for query failed to start and was poisoned") } } } -impl QueryState -where - K: Eq + Hash + Copy + Debug, -{ - pub fn all_inactive(&self) -> bool { - self.active.lock_shards().all(|shard| shard.is_empty()) - } - - pub fn collect_active_jobs( - &self, - qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, - require_complete: bool, - ) -> Option<()> { - let mut active = Vec::new(); - - let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult)>>| { - for (k, v) in iter.iter() { - if let QueryResult::Started(ref job) = *v { - active.push((*k, job.clone())); - } - } - }; - - if require_complete { - for shard in self.active.lock_shards() { - collect(shard); - } - } else { - // We use try_lock_shards here since we are called from the - // deadlock handler, and this shouldn't be locked. - for shard in self.active.try_lock_shards() { - collect(shard?); - } - } - - // Call `make_query` while we're not holding a `self.active` lock as `make_query` may call - // queries leading to a deadlock. - for (key, job) in active { - let query = make_query(qcx, key); - jobs.insert(job.id, QueryJobInfo { query, job }); - } - - Some(()) - } +pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { + state.active.lock_shards().all(|shard| shard.is_empty()) } -impl Default for QueryState { - fn default() -> QueryState { - QueryState { active: Default::default() } +/// Internal plumbing for collecting the set of active jobs for this query. +/// +/// Should only be called from `gather_active_jobs`. +pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>( + state: &QueryState<'tcx, K>, + tcx: TyCtxt<'tcx>, + make_frame: fn(TyCtxt<'tcx>, K) -> QueryStackFrame>, + require_complete: bool, + job_map_out: &mut QueryJobMap<'tcx>, // Out-param; job info is gathered into this map +) -> Option<()> { + let mut active = Vec::new(); + + // Helper to gather active jobs from a single shard. + let mut gather_shard_jobs = |shard: &HashTable<(K, ActiveKeyStatus<'tcx>)>| { + for (k, v) in shard.iter() { + if let ActiveKeyStatus::Started(ref job) = *v { + active.push((*k, job.clone())); + } + } + }; + + // Lock shards and gather jobs from each shard. + if require_complete { + for shard in state.active.lock_shards() { + gather_shard_jobs(&shard); + } + } else { + // We use try_lock_shards here since we are called from the + // deadlock handler, and this shouldn't be locked. + for shard in state.active.try_lock_shards() { + let shard = shard?; + gather_shard_jobs(&shard); + } } + + // Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call + // queries leading to a deadlock. + for (key, job) in active { + let frame = make_frame(tcx, key); + job_map_out.insert(job.id, QueryJobInfo { frame, job }); + } + + Some(()) } -/// 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, I> +/// Guard object representing the responsibility to execute a query job and +/// mark it as completed. +/// +/// This will poison the relevant query key if it is dropped without calling +/// [`Self::complete`]. +struct ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'tcx QueryState<'tcx, K>, key: K, + key_hash: u64, } #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ - let error = report_cycle(qcx.dep_context().sess(), &cycle_error); +fn mk_cycle<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + cycle_error: CycleError, +) -> C::Value { + let error = report_cycle(qcx.tcx.sess, &cycle_error); handle_cycle_error(query, qcx, &cycle_error, error) } -fn handle_cycle_error( - query: Q, - qcx: Qcx, +fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, cycle_error: &CycleError, error: Diag<'_>, -) -> Q::Value -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> C::Value { match query.cycle_error_handling() { CycleErrorHandling::Error => { let guar = error.emit(); - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } CycleErrorHandling::Fatal => { error.emit(); - qcx.dep_context().sess().dcx().abort_if_errors(); + qcx.tcx.dcx().abort_if_errors(); unreachable!() } CycleErrorHandling::DelayBug => { let guar = error.delay_as_bug(); - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() - && let Some(span) = root.query.info.span + && let Some(span) = root.frame.info.span { error.stash(span, StashKey::Cycle).unwrap() } else { error.emit() }; - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } } } -impl<'tcx, K, I> JobOwner<'tcx, K, I> +impl<'tcx, K> ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { /// Completes the query by updating the query cache with the `result`, - /// signals the waiter and forgets the JobOwner, so it won't poison the query - fn complete(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex) + /// signals the waiter, and forgets the guard so it won't poison the query. + fn complete(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) where C: QueryCache, { - let key = self.key; - let state = self.state; - - // Forget ourself so our destructor won't poison the query + // Forget ourself so our destructor won't poison the query. + // (Extract fields by value first to make sure we don't leak anything.) + let Self { state, key, key_hash }: Self = self; mem::forget(self); // Mark as complete before we remove the job from the active state @@ -201,13 +171,13 @@ where Ok(occupied) => Some(occupied.remove().0.1), } }; - let job = job.expect("active query job entry").expect_job(); + let job = expect_job(job.expect("active query job entry")); job.signal_complete(); } } -impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I> +impl<'tcx, K> Drop for ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { @@ -215,16 +185,15 @@ where #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let state = self.state; + let Self { state, key, key_hash } = *self; let job = { - let key_hash = sharded::make_hash(&self.key); let mut shard = state.active.lock_shard_by_hash(key_hash); - match shard.find_entry(key_hash, equivalent_key(&self.key)) { + match shard.find_entry(key_hash, equivalent_key(&key)) { Err(_) => panic!(), Ok(occupied) => { let ((key, value), vacant) = occupied.remove(); - vacant.insert((key, QueryResult::Poisoned)); - value.expect_job() + vacant.insert((key, ActiveKeyStatus::Poisoned)); + expect_job(value) } } }; @@ -234,83 +203,42 @@ where } } -#[derive(Clone, Debug)] -pub struct CycleError { - /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec>, -} - -impl CycleError { - fn lift>(&self, qcx: Qcx) -> CycleError { - CycleError { - usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), - cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), - } - } -} - -/// Checks whether there is already a value for this key in the in-memory -/// query cache, returning that value if present. -/// -/// (Also performs some associated bookkeeping, if a value was found.) -#[inline(always)] -pub fn try_get_cached(tcx: Tcx, cache: &C, key: &C::Key) -> Option -where - C: QueryCache, - Tcx: DepContext, -{ - match cache.lookup(key) { - Some((value, index)) => { - tcx.profiler().query_cache_hit(index.into()); - tcx.dep_graph().read_index(index); - Some(value) - } - None => None, - } -} - #[cold] #[inline(never)] -fn cycle_error( - query: Q, - qcx: Qcx, +fn cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, try_execute: QueryJobId, span: Span, -) -> (Q::Value, Option) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> (C::Value, Option) { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. - let query_map = qcx.collect_active_jobs(false).ok().expect("failed to collect active queries"); + let job_map = qcx + .collect_active_jobs_from_all_queries(false) + .ok() + .expect("failed to collect active queries"); - let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); - (mk_cycle(query, qcx, error.lift(qcx)), None) + let error = find_cycle_in_stack(try_execute, job_map, &qcx.current_query_job(), span); + (mk_cycle(query, qcx, error.lift()), None) } #[inline(always)] -fn wait_for_query( - query: Q, - qcx: Qcx, +fn wait_for_query<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, - latch: QueryLatch, + key: C::Key, + latch: QueryLatch<'tcx>, current: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> (C::Value, Option) { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. - let query_blocked_prof_timer = qcx.dep_context().profiler().query_blocked(); + let query_blocked_prof_timer = qcx.tcx.prof.query_blocked(); // With parallel queries we might just have to wait on some other // thread. - let result = latch.wait_on(qcx, current, span); + let result = latch.wait_on(qcx.tcx, current, span); match result { Ok(()) => { @@ -322,7 +250,7 @@ where let shard = query.query_state(qcx).active.lock_shard_by_hash(key_hash); match shard.find(key_hash, equivalent_key(&key)) { // The query we waited on panicked. Continue unwinding here. - Some((_, QueryResult::Poisoned)) => FatalError.raise(), + Some((_, ActiveKeyStatus::Poisoned)) => FatalError.raise(), _ => panic!( "query '{}' result must be in the cache or the query must be poisoned after a wait", query.name() @@ -331,27 +259,23 @@ where }) }; - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); (v, Some(index)) } - Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None), + Err(cycle) => (mk_cycle(query, qcx, cycle.lift()), None), } } #[inline(never)] -fn try_execute_query( - query: Q, - qcx: Qcx, +fn try_execute_query<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, + key: C::Key, dep_node: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> (C::Value, Option) { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); let mut state_lock = state.active.lock_shard_by_hash(key_hash); @@ -362,9 +286,9 @@ where // re-executing the query since `try_start` only checks that the query is not currently // executing, but another thread may have already completed the query and stores it result // in the query cache. - if qcx.dep_context().sess().threads() > 1 { + if qcx.tcx.sess.threads() > 1 { if let Some((value, index)) = query.query_cache(qcx).lookup(&key) { - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); return (value, Some(index)); } } @@ -377,16 +301,16 @@ where // state map. let id = qcx.next_job_id(); let job = QueryJob::new(id, span, current_job_id); - entry.insert((key, QueryResult::Started(job))); + entry.insert((key, ActiveKeyStatus::Started(job))); // Drop the lock before we start executing the query drop(state_lock); - execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node) + execute_job::(query, qcx, state, key, key_hash, id, dep_node) } Entry::Occupied(mut entry) => { match &mut entry.get_mut().1 { - QueryResult::Started(job) => { + ActiveKeyStatus::Started(job) => { if sync::is_dyn_thread_safe() { // Get the latch out let latch = job.latch(); @@ -404,40 +328,31 @@ where // so we just return the error. cycle_error(query, qcx, id, span) } - QueryResult::Poisoned => FatalError.raise(), + ActiveKeyStatus::Poisoned => FatalError.raise(), } } } } #[inline(always)] -fn execute_job( - query: Q, - qcx: Qcx, - state: &QueryState, - key: Q::Key, +fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + state: &'tcx QueryState<'tcx, C::Key>, + key: C::Key, key_hash: u64, id: QueryJobId, dep_node: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ - // Use `JobOwner` so the query will be poisoned if executing it panics. - let job_owner = JobOwner { state, key }; +) -> (C::Value, Option) { + // Set up a guard object that will automatically poison the query if a + // panic occurs while executing the query (or any intermediate plumbing). + let job_guard = ActiveJobGuard { state, key, key_hash }; - debug_assert_eq!(qcx.dep_context().dep_graph().is_fully_enabled(), INCR); + debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR); + // Delegate to another function to actually execute the query job. let (result, dep_node_index) = if INCR { - execute_job_incr( - query, - qcx, - qcx.dep_context().dep_graph().data().unwrap(), - key, - dep_node, - id, - ) + execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id) } else { execute_job_non_incr(query, qcx, key, id) }; @@ -466,7 +381,7 @@ where // We have an inconsistency. This can happen if one of the two // results is tainted by errors. assert!( - qcx.dep_context().sess().dcx().has_errors().is_some(), + qcx.tcx.dcx().has_errors().is_some(), "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\ computed={:#?}\nfed={:#?}", query.dep_kind(), @@ -477,34 +392,33 @@ where } } } - job_owner.complete(cache, key_hash, result, dep_node_index); + + // Tell the guard to perform completion bookkeeping, and also to not poison the query. + job_guard.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } // Fast path for when incr. comp. is off. #[inline(always)] -fn execute_job_non_incr( - query: Q, - qcx: Qcx, - key: Q::Key, +fn execute_job_non_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + key: C::Key, job_id: QueryJobId, -) -> (Q::Value, DepNodeIndex) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ - debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); +) -> (C::Value, DepNodeIndex) { + debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); // Fingerprint the key, just to assert that it doesn't // have anything we don't consider hashable if cfg!(debug_assertions) { - let _ = key.to_fingerprint(*qcx.dep_context()); + let _ = key.to_fingerprint(qcx.tcx); } - let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, query.depth_limit(), || query.compute(qcx, key)); - let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index(); + let prof_timer = qcx.tcx.prof.query_provider(); + // Call the query provider. + let result = qcx.start_query(job_id, query.depth_limit(), || query.invoke_provider(qcx, key)); + let dep_node_index = qcx.tcx.dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); // Similarly, fingerprint the result to assert that @@ -521,22 +435,17 @@ where } #[inline(always)] -fn execute_job_incr( - query: Q, - qcx: Qcx, - dep_graph_data: &DepGraphData, - key: Q::Key, +fn execute_job_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + dep_graph_data: &DepGraphData, + key: C::Key, mut dep_node_opt: Option, job_id: QueryJobId, -) -> (Q::Value, DepNodeIndex) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> (C::Value, DepNodeIndex) { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.get_or_insert_with(|| query.construct_dep_node(*qcx.dep_context(), &key)); + let dep_node = dep_node_opt.get_or_insert_with(|| query.construct_dep_node(qcx.tcx, &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. @@ -547,26 +456,25 @@ where } } - let prof_timer = qcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.tcx.prof.query_provider(); let (result, dep_node_index) = qcx.start_query(job_id, query.depth_limit(), || { if query.anon() { - return dep_graph_data.with_anon_task_inner( - *qcx.dep_context(), - query.dep_kind(), - || query.compute(qcx, key), - ); + // Call the query provider inside an anon task. + return dep_graph_data.with_anon_task_inner(qcx.tcx, query.dep_kind(), || { + query.invoke_provider(qcx, key) + }); } // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); + let dep_node = dep_node_opt.unwrap_or_else(|| query.construct_dep_node(qcx.tcx, &key)); + // Call the query provider. dep_graph_data.with_task( dep_node, (qcx, query), key, - |(qcx, query), key| query.compute(qcx, key), + |(qcx, query), key| query.invoke_provider(qcx, key), query.hash_result(), ) }); @@ -577,17 +485,13 @@ where } #[inline(always)] -fn try_load_from_disk_and_cache_in_memory( - query: Q, - dep_graph_data: &DepGraphData, - qcx: Qcx, - key: &Q::Key, +fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + dep_graph_data: &DepGraphData, + qcx: QueryCtxt<'tcx>, + key: &C::Key, dep_node: &DepNode, -) -> Option<(Q::Value, DepNodeIndex)> -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> Option<(C::Value, DepNodeIndex)> { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -598,7 +502,7 @@ where // First we try to load the result from the on-disk cache. // Some things are never cached on disk. if let Some(result) = query.try_load_from_disk(qcx, key, prev_dep_node_index, dep_node_index) { - if std::intrinsics::unlikely(qcx.dep_context().sess().opts.unstable_opts.query_dep_graph) { + if std::intrinsics::unlikely(qcx.tcx.sess.opts.unstable_opts.query_dep_graph) { dep_graph_data.mark_debug_loaded_from_disk(*dep_node) } @@ -612,10 +516,10 @@ where // give us some coverage of potential bugs though. let try_verify = prev_fingerprint.split().1.as_u64().is_multiple_of(32); if std::intrinsics::unlikely( - try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, + try_verify || qcx.tcx.sess.opts.unstable_opts.incremental_verify_ich, ) { incremental_verify_ich( - *qcx.dep_context(), + qcx.tcx, dep_graph_data, &result, prev_dep_node_index, @@ -630,7 +534,7 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !query.cache_on_disk(*qcx.dep_context(), key) + !query.will_cache_on_disk_for_key(qcx.tcx, key) || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {dep_node:?}" ); @@ -638,16 +542,17 @@ where // Sanity check for the logic in `ensure`: if the node is green and the result loadable, // we should actually be able to load it. debug_assert!( - !query.loadable_from_disk(qcx, key, prev_dep_node_index), + !query.is_loadable_from_disk(qcx, key, prev_dep_node_index), "missing on-disk cache entry for loadable {dep_node:?}" ); // We could not load a result from the on-disk cache, so // recompute. - let prof_timer = qcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.tcx.prof.query_provider(); // The dep-graph for this computation is already in-place. - let result = qcx.dep_context().dep_graph().with_ignore(|| query.compute(qcx, *key)); + // Call the query provider. + let result = qcx.tcx.dep_graph.with_ignore(|| query.invoke_provider(qcx, *key)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -661,7 +566,7 @@ where // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check incremental_verify_ich( - *qcx.dep_context(), + qcx.tcx, dep_graph_data, &result, prev_dep_node_index, @@ -672,89 +577,6 @@ where Some((result, dep_node_index)) } -#[inline] -#[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, - result: &V, - prev_index: SerializedDepNodeIndex, - hash_result: Option, &V) -> Fingerprint>, - format_value: fn(&V) -> String, -) where - Tcx: DepContext, -{ - if !dep_graph_data.is_index_green(prev_index) { - incremental_verify_ich_not_green(tcx, prev_index) - } - - let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| { - tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) - }); - - let old_hash = dep_graph_data.prev_fingerprint_of(prev_index); - - if new_hash != old_hash { - incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); - } -} - -#[cold] -#[inline(never)] -fn incremental_verify_ich_not_green(tcx: Tcx, prev_index: SerializedDepNodeIndex) -where - Tcx: DepContext, -{ - panic!( - "fingerprint for green query instance not loaded from cache: {:?}", - tcx.dep_graph().data().unwrap().prev_node_of(prev_index) - ) -} - -// Note that this is marked #[cold] and intentionally takes `dyn Debug` for `result`, -// as we want to avoid generating a bunch of different implementations for LLVM to -// chew on (and filling up the final binary, too). -#[cold] -#[inline(never)] -fn incremental_verify_ich_failed( - tcx: Tcx, - prev_index: SerializedDepNodeIndex, - result: &dyn Fn() -> String, -) where - Tcx: DepContext, -{ - // When we emit an error message and panic, we try to debug-print the `DepNode` - // and query result. Unfortunately, this can cause us to run additional queries, - // which may result in another fingerprint mismatch while we're in the middle - // of processing this one. To avoid a double-panic (which kills the process - // before we can print out the query static), we print out a terse - // but 'safe' message if we detect a reentrant call to this method. - thread_local! { - static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; - }; - - let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); - - if old_in_panic { - tcx.sess().dcx().emit_err(crate::error::Reentrant); - } else { - let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { - format!("`cargo clean -p {crate_name}` or `cargo clean`") - } else { - "`cargo clean`".to_string() - }; - - let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index); - tcx.sess().dcx().emit_err(crate::error::IncrementCompilation { - run_cmd, - dep_node: format!("{dep_node:?}"), - }); - panic!("Found unstable fingerprints for {dep_node:?}: {}", result()); - } - - INSIDE_VERIFY_PANIC.set(old_in_panic); -} - /// Ensure that either this query has all green inputs or been executed. /// Executing `query::ensure(D)` is considered a read of the dep-node `D`. /// Returns true if the query should still run. @@ -764,16 +586,12 @@ fn incremental_verify_ich_failed( /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run( - query: Q, - qcx: Qcx, - key: &Q::Key, +fn ensure_must_run<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + key: &C::Key, check_cache: bool, -) -> (bool, Option) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +) -> (bool, Option) { if query.eval_always() { return (true, None); } @@ -781,9 +599,9 @@ where // Ensuring an anonymous query makes no sense assert!(!query.anon()); - let dep_node = query.construct_dep_node(*qcx.dep_context(), key); + let dep_node = query.construct_dep_node(qcx.tcx, key); - let dep_graph = qcx.dep_context().dep_graph(); + let dep_graph = &qcx.tcx.dep_graph; let serialized_dep_node_index = match dep_graph.try_mark_green(qcx, &dep_node) { None => { // A None return from `try_mark_green` means that this is either @@ -796,7 +614,7 @@ where } Some((serialized_dep_node_index, dep_node_index)) => { dep_graph.read_index(dep_node_index); - qcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); + qcx.tcx.prof.query_cache_hit(dep_node_index.into()); serialized_dep_node_index } }; @@ -806,40 +624,31 @@ where return (false, None); } - let loadable = query.loadable_from_disk(qcx, key, serialized_dep_node_index); + let loadable = query.is_loadable_from_disk(qcx, key, serialized_dep_node_index); (!loadable, Some(dep_node)) } -#[derive(Debug)] -pub enum QueryMode { - Get, - Ensure { check_cache: bool }, -} - #[inline(always)] -pub fn get_query_non_incr(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ - debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); - - ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) -} - -#[inline(always)] -pub fn get_query_incr( - query: Q, - qcx: Qcx, +pub(super) fn get_query_non_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, + key: C::Key, +) -> C::Value { + debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); + + ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) +} + +#[inline(always)] +pub(super) fn get_query_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + span: Span, + key: C::Key, mode: QueryMode, -) -> Option -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ - debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled()); +) -> Option { + debug_assert!(qcx.tcx.dep_graph.is_fully_enabled()); let dep_node = if let QueryMode::Ensure { check_cache } = mode { let (must_run, dep_node) = ensure_must_run(query, qcx, &key, check_cache); @@ -852,29 +661,30 @@ where }; let (result, dep_node_index) = ensure_sufficient_stack(|| { - try_execute_query::<_, _, true>(query, qcx, span, key, dep_node) + try_execute_query::(query, qcx, span, key, dep_node) }); if let Some(dep_node_index) = dep_node_index { - qcx.dep_context().dep_graph().read_index(dep_node_index) + qcx.tcx.dep_graph.read_index(dep_node_index) } Some(result) } -pub fn force_query(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) -where - Q: QueryDispatcher, - Qcx: QueryContext, -{ +pub(crate) fn force_query<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + key: C::Key, + dep_node: DepNode, +) { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. if let Some((_, index)) = query.query_cache(qcx).lookup(&key) { - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); return; } debug_assert!(!query.anon()); ensure_sufficient_stack(|| { - try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node)) + try_execute_query::(query, qcx, DUMMY_SP, key, Some(dep_node)) }); } diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs new file mode 100644 index 000000000000..6db4998ffafb --- /dev/null +++ b/compiler/rustc_query_impl/src/job.rs @@ -0,0 +1,494 @@ +use std::io::Write; +use std::iter; +use std::ops::ControlFlow; +use std::sync::Arc; + +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::{Diag, DiagCtxtHandle}; +use rustc_hir::def::DefKind; +use rustc_middle::query::{ + CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, + QueryWaiter, +}; +use rustc_session::Session; +use rustc_span::{DUMMY_SP, Span}; + +use crate::QueryCtxt; +use crate::dep_graph::DepContext; + +/// Map from query job IDs to job information collected by +/// `collect_active_jobs_from_all_queries`. +#[derive(Debug, Default)] +pub struct QueryJobMap<'tcx> { + map: FxHashMap>, +} + +impl<'tcx> QueryJobMap<'tcx> { + /// Adds information about a job ID to the job map. + /// + /// Should only be called by `gather_active_jobs_inner`. + pub(crate) fn insert(&mut self, id: QueryJobId, info: QueryJobInfo<'tcx>) { + self.map.insert(id, info); + } + + fn frame_of(&self, id: QueryJobId) -> &QueryStackFrame> { + &self.map[&id].frame + } + + fn span_of(&self, id: QueryJobId) -> Span { + self.map[&id].job.span + } + + fn parent_of(&self, id: QueryJobId) -> Option { + self.map[&id].job.parent + } + + fn latch_of(&self, id: QueryJobId) -> Option<&QueryLatch<'tcx>> { + self.map[&id].job.latch.as_ref() + } +} + +#[derive(Clone, Debug)] +pub(crate) struct QueryJobInfo<'tcx> { + pub(crate) frame: QueryStackFrame>, + pub(crate) job: QueryJob<'tcx>, +} + +pub(crate) fn find_cycle_in_stack<'tcx>( + id: QueryJobId, + job_map: QueryJobMap<'tcx>, + current_job: &Option, + span: Span, +) -> CycleError> { + // Find the waitee amongst `current_job` parents + let mut cycle = Vec::new(); + let mut current_job = Option::clone(current_job); + + while let Some(job) = current_job { + let info = &job_map.map[&job]; + cycle.push(QueryInfo { span: info.job.span, frame: info.frame.clone() }); + + if job == id { + cycle.reverse(); + + // This is the end of the cycle + // The span entry we included was for the usage + // of the cycle itself, and not part of the cycle + // Replace it with the span which caused the cycle to form + cycle[0].span = span; + // Find out why the cycle itself was used + let usage = try { + let parent = info.job.parent?; + (info.job.span, job_map.frame_of(parent).clone()) + }; + return CycleError { usage, cycle }; + } + + current_job = info.job.parent; + } + + panic!("did not find a cycle") +} + +#[cold] +#[inline(never)] +pub(crate) fn find_dep_kind_root<'tcx>( + id: QueryJobId, + job_map: QueryJobMap<'tcx>, +) -> (QueryJobInfo<'tcx>, usize) { + let mut depth = 1; + let info = &job_map.map[&id]; + let dep_kind = info.frame.dep_kind; + let mut current_id = info.job.parent; + let mut last_layout = (info.clone(), depth); + + while let Some(id) = current_id { + let info = &job_map.map[&id]; + if info.frame.dep_kind == dep_kind { + depth += 1; + last_layout = (info.clone(), depth); + } + current_id = info.job.parent; + } + last_layout +} + +/// A resumable waiter of a query. The usize is the index into waiters in the query's latch +type Waiter = (QueryJobId, usize); + +/// Visits all the non-resumable and resumable waiters of a query. +/// Only waiters in a query are visited. +/// `visit` is called for every waiter and is passed a query waiting on `query` +/// and a span indicating the reason the query waited on `query`. +/// If `visit` returns `Break`, this function also returns `Break`, +/// and if all `visit` calls returns `Continue` it also returns `Continue`. +/// For visits of non-resumable waiters it returns the return value of `visit`. +/// For visits of resumable waiters it returns information required to resume that waiter. +fn visit_waiters<'tcx>( + job_map: &QueryJobMap<'tcx>, + query: QueryJobId, + mut visit: impl FnMut(Span, QueryJobId) -> ControlFlow>, +) -> ControlFlow> { + // Visit the parent query which is a non-resumable waiter since it's on the same stack + if let Some(parent) = job_map.parent_of(query) { + visit(job_map.span_of(query), parent)?; + } + + // Visit the explicit waiters which use condvars and are resumable + if let Some(latch) = job_map.latch_of(query) { + for (i, waiter) in latch.info.lock().waiters.iter().enumerate() { + if let Some(waiter_query) = waiter.query { + // Return a value which indicates that this waiter can be resumed + visit(waiter.span, waiter_query).map_break(|_| Some((query, i)))?; + } + } + } + + ControlFlow::Continue(()) +} + +/// Look for query cycles by doing a depth first search starting at `query`. +/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. +/// If a cycle is detected, this initial value is replaced with the span causing +/// the cycle. +fn cycle_check<'tcx>( + job_map: &QueryJobMap<'tcx>, + query: QueryJobId, + span: Span, + stack: &mut Vec<(Span, QueryJobId)>, + visited: &mut FxHashSet, +) -> ControlFlow> { + if !visited.insert(query) { + return if let Some(p) = stack.iter().position(|q| q.1 == query) { + // We detected a query cycle, fix up the initial span and return Some + + // Remove previous stack entries + stack.drain(0..p); + // Replace the span for the first query with the cycle cause + stack[0].0 = span; + ControlFlow::Break(None) + } else { + ControlFlow::Continue(()) + }; + } + + // Query marked as visited is added it to the stack + stack.push((span, query)); + + // Visit all the waiters + let r = visit_waiters(job_map, query, |span, successor| { + cycle_check(job_map, successor, span, stack, visited) + }); + + // Remove the entry in our stack if we didn't find a cycle + if r.is_continue() { + stack.pop(); + } + + r +} + +/// Finds out if there's a path to the compiler root (aka. code which isn't in a query) +/// from `query` without going through any of the queries in `visited`. +/// This is achieved with a depth first search. +fn connected_to_root<'tcx>( + job_map: &QueryJobMap<'tcx>, + query: QueryJobId, + visited: &mut FxHashSet, +) -> ControlFlow> { + // We already visited this or we're deliberately ignoring it + if !visited.insert(query) { + return ControlFlow::Continue(()); + } + + // This query is connected to the root (it has no query parent), return true + if job_map.parent_of(query).is_none() { + return ControlFlow::Break(None); + } + + visit_waiters(job_map, query, |_, successor| connected_to_root(job_map, successor, visited)) +} + +// Deterministically pick an query from a list +fn pick_query<'a, 'tcx, T, F>(job_map: &QueryJobMap<'tcx>, queries: &'a [T], f: F) -> &'a T +where + F: Fn(&T) -> (Span, QueryJobId), +{ + // Deterministically pick an entry point + // FIXME: Sort this instead + queries + .iter() + .min_by_key(|v| { + let (span, query) = f(v); + let hash = job_map.frame_of(query).hash; + // Prefer entry points which have valid spans for nicer error messages + // We add an integer to the tuple ensuring that entry points + // with valid spans are picked first + let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; + (span_cmp, hash) + }) + .unwrap() +} + +/// Looks for query cycles starting from the last query in `jobs`. +/// If a cycle is found, all queries in the cycle is removed from `jobs` and +/// the function return true. +/// If a cycle was not found, the starting query is removed from `jobs` and +/// the function returns false. +fn remove_cycle<'tcx>( + job_map: &QueryJobMap<'tcx>, + jobs: &mut Vec, + wakelist: &mut Vec>>, +) -> bool { + let mut visited = FxHashSet::default(); + let mut stack = Vec::new(); + // Look for a cycle starting with the last query in `jobs` + if let ControlFlow::Break(waiter) = + cycle_check(job_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) + { + // The stack is a vector of pairs of spans and queries; reverse it so that + // the earlier entries require later entries + let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); + + // Shift the spans so that queries are matched with the span for their waitee + spans.rotate_right(1); + + // Zip them back together + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); + + // Remove the queries in our cycle from the list of jobs to look at + for r in &stack { + if let Some(pos) = jobs.iter().position(|j| j == &r.1) { + jobs.remove(pos); + } + } + + // Find the queries in the cycle which are + // connected to queries outside the cycle + let entry_points = stack + .iter() + .filter_map(|&(span, query)| { + if job_map.parent_of(query).is_none() { + // This query is connected to the root (it has no query parent) + Some((span, query, None)) + } else { + let mut waiters = Vec::new(); + // Find all the direct waiters who lead to the root + let _ = visit_waiters(job_map, query, |span, waiter| { + // Mark all the other queries in the cycle as already visited + let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); + + if connected_to_root(job_map, waiter, &mut visited).is_break() { + waiters.push((span, waiter)); + } + + ControlFlow::Continue(()) + }); + if waiters.is_empty() { + None + } else { + // Deterministically pick one of the waiters to show to the user + let waiter = *pick_query(job_map, &waiters, |s| *s); + Some((span, query, Some(waiter))) + } + } + }) + .collect::)>>(); + + // Deterministically pick an entry point + let (_, entry_point, usage) = pick_query(job_map, &entry_points, |e| (e.0, e.1)); + + // Shift the stack so that our entry point is first + let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); + if let Some(pos) = entry_point_pos { + stack.rotate_left(pos); + } + + let usage = usage.map(|(span, job)| (span, job_map.frame_of(job).clone())); + + // Create the cycle error + let error = CycleError { + usage, + cycle: stack + .iter() + .map(|&(span, job)| QueryInfo { span, frame: job_map.frame_of(job).clone() }) + .collect(), + }; + + // We unwrap `waiter` here since there must always be one + // edge which is resumable / waited using a query latch + let (waitee_query, waiter_idx) = waiter.unwrap(); + + // Extract the waiter we want to resume + let waiter = job_map.latch_of(waitee_query).unwrap().extract_waiter(waiter_idx); + + // Set the cycle error so it will be picked up when resumed + *waiter.cycle.lock() = Some(error); + + // Put the waiter on the list of things to resume + wakelist.push(waiter); + + true + } else { + false + } +} + +/// Detects query cycles by using depth first search over all active query jobs. +/// If a query cycle is found it will break the cycle by finding an edge which +/// uses a query latch and then resuming that waiter. +/// 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. +pub fn break_query_cycles<'tcx>( + job_map: QueryJobMap<'tcx>, + registry: &rustc_thread_pool::Registry, +) { + let mut wakelist = Vec::new(); + // It is OK per the comments: + // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 + // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392 + #[allow(rustc::potential_query_instability)] + let mut jobs: Vec = job_map.map.keys().copied().collect(); + + let mut found_cycle = false; + + while jobs.len() > 0 { + if remove_cycle(&job_map, &mut jobs, &mut wakelist) { + found_cycle = true; + } + } + + // Check that a cycle was found. It is possible for a deadlock to occur without + // a query cycle if a query which can be waited on uses Rayon to do multithreading + // internally. Such a query (X) may be executing on 2 threads (A and B) and A may + // wait using Rayon on B. Rayon may then switch to executing another query (Y) + // which in turn will wait on X causing a deadlock. We have a false dependency from + // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here + // only considers the true dependency and won't detect a cycle. + if !found_cycle { + panic!( + "deadlock detected as we're unable to find a query cycle to break\n\ + current query map:\n{job_map:#?}", + ); + } + + // Mark all the thread we're about to wake up as unblocked. This needs to be done before + // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we + // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked. + for _ in 0..wakelist.len() { + rustc_thread_pool::mark_unblocked(registry); + } + + for waiter in wakelist.into_iter() { + waiter.condvar.notify_one(); + } +} + +pub fn print_query_stack<'tcx>( + qcx: QueryCtxt<'tcx>, + mut current_query: Option, + dcx: DiagCtxtHandle<'_>, + limit_frames: Option, + mut file: Option, +) -> usize { + // Be careful relying on global state here: this code is called from + // a panic hook, which means that the global `DiagCtxt` may be in a weird + // state if it was responsible for triggering the panic. + let mut count_printed = 0; + let mut count_total = 0; + + // Make use of a partial query job map if we fail to take locks collecting active queries. + let job_map: QueryJobMap<'_> = qcx + .collect_active_jobs_from_all_queries(false) + .unwrap_or_else(|partial_job_map| partial_job_map); + + if let Some(ref mut file) = file { + let _ = writeln!(file, "\n\nquery stack during panic:"); + } + while let Some(query) = current_query { + let Some(query_info) = job_map.map.get(&query) else { + break; + }; + let query_extra = query_info.frame.info.extract(); + if Some(count_printed) < limit_frames || limit_frames.is_none() { + // Only print to stderr as many stack frames as `num_frames` when present. + dcx.struct_failure_note(format!( + "#{} [{:?}] {}", + count_printed, query_info.frame.dep_kind, query_extra.description + )) + .with_span(query_info.job.span) + .emit(); + count_printed += 1; + } + + if let Some(ref mut file) = file { + let _ = writeln!( + file, + "#{} [{}] {}", + count_total, + qcx.tcx.dep_kind_vtable(query_info.frame.dep_kind).name, + query_extra.description + ); + } + + current_query = query_info.job.parent; + count_total += 1; + } + + if let Some(ref mut file) = file { + let _ = writeln!(file, "end of query stack"); + } + count_total +} + +#[inline(never)] +#[cold] +pub(crate) fn report_cycle<'a>( + sess: &'a Session, + CycleError { usage, cycle: stack }: &CycleError, +) -> Diag<'a> { + assert!(!stack.is_empty()); + + let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); + + let mut cycle_stack = Vec::new(); + + use crate::error::StackCount; + let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; + + for i in 1..stack.len() { + let frame = &stack[i].frame; + let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); + cycle_stack + .push(crate::error::CycleStack { span, desc: frame.info.description.to_owned() }); + } + + let mut cycle_usage = None; + if let Some((span, ref query)) = *usage { + cycle_usage = Some(crate::error::CycleUsage { + span: query.info.default_span(span), + usage: query.info.description.to_string(), + }); + } + + let alias = + if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { + Some(crate::error::Alias::Ty) + } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { + Some(crate::error::Alias::Trait) + } else { + None + }; + + let cycle_diag = crate::error::Cycle { + span, + cycle_stack, + stack_bottom: stack[0].frame.info.description.to_owned(), + alias, + cycle_usage, + stack_count, + note_span: (), + }; + + sess.dcx().create_err(cycle_diag) +} diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index b628224db536..6a4171afe4bc 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -2,173 +2,169 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![feature(adt_const_params)] +#![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(rustc_attrs)] +#![feature(try_blocks)] // tidy-alphabetical-end -use rustc_data_structures::stable_hasher::HashStable; +use std::marker::ConstParamTy; + use rustc_data_structures::sync::AtomicU64; -use rustc_middle::arena::Arena; -use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; -use rustc_middle::query::erase::{Erase, erase, restore}; +use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use rustc_middle::queries::{ + self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, +}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::{ - AsLocalKey, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, queries, +use rustc_middle::query::plumbing::{ + HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, }; +use rustc_middle::query::{AsLocalKey, CycleError, CycleErrorHandling, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; -use rustc_query_system::Value; -use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{ - CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, - QueryStackDeferred, QueryState, get_query_incr, get_query_non_incr, -}; use rustc_span::{ErrorGuaranteed, Span}; -use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green}; +pub use crate::dep_kind_vtables::make_dep_kind_vtables; +pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack}; +pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; +use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; +pub use crate::profiling_support::alloc_self_profile_query_strings; +use crate::values::Value; #[macro_use] mod plumbing; -pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; +mod dep_kind_vtables; +mod error; +mod execution; +mod job; mod profiling_support; -pub use self::profiling_support::alloc_self_profile_query_strings; +mod values; -/// Combines a [`QueryVTable`] with some additional compile-time booleans -/// to implement [`QueryDispatcher`], for use by code in [`rustc_query_system`]. +#[derive(ConstParamTy)] // Allow this struct to be used for const-generic values. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct QueryFlags { + /// True if this query has the `anon` modifier. + is_anon: bool, + /// True if this query has the `depth_limit` modifier. + is_depth_limit: bool, + /// True if this query has the `feedable` modifier. + is_feedable: bool, +} + +/// Combines a [`QueryVTable`] with some additional compile-time booleans. +/// "Dispatcher" should be understood as a near-synonym of "vtable". /// /// Baking these boolean flags into the type gives a modest but measurable /// improvement to compiler perf and compiler code size; see /// . -struct SemiDynamicQueryDispatcher< - 'tcx, - C: QueryCache, - const ANON: bool, - const DEPTH_LIMIT: bool, - const FEEDABLE: bool, -> { +struct SemiDynamicQueryDispatcher<'tcx, C: QueryCache, const FLAGS: QueryFlags> { vtable: &'tcx QueryVTable<'tcx, C>, } // Manually implement Copy/Clone, because deriving would put trait bounds on the cache type. -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Copy + for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { } -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Clone + for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { fn clone(&self) -> Self { *self } } -// This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> - QueryDispatcher> - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> -where - for<'a> C::Key: HashStable>, -{ - type Key = C::Key; - type Value = C::Value; - type Cache = C; - +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { #[inline(always)] fn name(self) -> &'static str { self.vtable.name } #[inline(always)] - fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { - (self.vtable.cache_on_disk)(tcx, key) + fn will_cache_on_disk_for_key(self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool { + self.vtable.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key)) } + // Don't use this method to access query results, instead use the methods on TyCtxt. #[inline(always)] - fn query_state<'a>( - self, - qcx: QueryCtxt<'tcx>, - ) -> &'a QueryState> - where - QueryCtxt<'tcx>: 'a, - { + fn query_state(self, qcx: QueryCtxt<'tcx>) -> &'tcx QueryState<'tcx, C::Key> { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) .byte_add(self.vtable.query_state) - .cast::>>() + .cast::>() } } + // Don't use this method to access query results, instead use the methods on TyCtxt. #[inline(always)] - fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache - where - 'tcx: 'a, - { + fn query_cache(self, qcx: QueryCtxt<'tcx>) -> &'tcx C { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { &*(&qcx.tcx.query_system.caches as *const QueryCaches<'tcx>) .byte_add(self.vtable.query_cache) - .cast::() + .cast::() } } + /// Calls `tcx.$query(key)` for this query, and discards the returned value. + /// See [`QueryVTable::call_query_method_fn`] for details of this strange operation. #[inline(always)] - fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { - (self.vtable.execute_query)(tcx, key) + fn call_query_method(self, tcx: TyCtxt<'tcx>, key: C::Key) { + (self.vtable.call_query_method_fn)(tcx, key) } + /// Calls the actual provider function for this query. + /// See [`QueryVTable::invoke_provider_fn`] for more details. #[inline(always)] - fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - (self.vtable.compute)(qcx.tcx, key) + fn invoke_provider(self, qcx: QueryCtxt<'tcx>, key: C::Key) -> C::Value { + (self.vtable.invoke_provider_fn)(qcx.tcx, key) } #[inline(always)] fn try_load_from_disk( self, qcx: QueryCtxt<'tcx>, - key: &Self::Key, + key: &C::Key, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, - ) -> Option { - if self.vtable.can_load_from_disk { - (self.vtable.try_load_from_disk)(qcx.tcx, key, prev_index, index) - } else { - None - } + ) -> Option { + // `?` will return None immediately for queries that never cache to disk. + self.vtable.try_load_from_disk_fn?(qcx.tcx, key, prev_index, index) } #[inline] - fn loadable_from_disk( + fn is_loadable_from_disk( self, qcx: QueryCtxt<'tcx>, - key: &Self::Key, + key: &C::Key, index: SerializedDepNodeIndex, ) -> bool { - (self.vtable.loadable_from_disk)(qcx.tcx, key, index) + self.vtable.is_loadable_from_disk_fn.map_or(false, |f| f(qcx.tcx, key, index)) } + /// Synthesize an error value to let compilation continue after a cycle. fn value_from_cycle_error( self, tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed, - ) -> Self::Value { + ) -> C::Value { (self.vtable.value_from_cycle_error)(tcx, cycle_error, guar) } #[inline(always)] - fn format_value(self) -> fn(&Self::Value) -> String { + fn format_value(self) -> fn(&C::Value) -> String { self.vtable.format_value } #[inline(always)] fn anon(self) -> bool { - ANON + FLAGS.is_anon } #[inline(always)] @@ -178,12 +174,12 @@ where #[inline(always)] fn depth_limit(self) -> bool { - DEPTH_LIMIT + FLAGS.is_depth_limit } #[inline(always)] fn feedable(self) -> bool { - FEEDABLE + FLAGS.is_feedable } #[inline(always)] @@ -197,13 +193,17 @@ where } #[inline(always)] - fn hash_result(self) -> HashResult { + fn hash_result(self) -> HashResult { self.vtable.hash_result } + + fn construct_dep_node(self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode { + DepNode::construct(tcx, self.dep_kind(), key) + } } /// Provides access to vtable-like operations for a query -/// (by creating a [`QueryDispatcher`]), +/// (by creating a [`SemiDynamicQueryDispatcher`]), /// but also keeps track of the "unerased" value type of the query /// (i.e. the actual result type in the query declaration). /// @@ -213,25 +213,22 @@ where /// /// There is one macro-generated implementation of this trait for each query, /// on the type `rustc_query_impl::query_impl::$name::QueryType`. -trait QueryDispatcherUnerased<'tcx> { +trait QueryDispatcherUnerased<'tcx, C: QueryCache, const FLAGS: QueryFlags> { type UnerasedValue; - type Dispatcher: QueryDispatcher>; const NAME: &'static &'static str; - fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher; + fn query_dispatcher(tcx: TyCtxt<'tcx>) -> SemiDynamicQueryDispatcher<'tcx, C, FLAGS>; - fn restore_val( - value: >>::Value, - ) -> Self::UnerasedValue; + fn restore_val(value: C::Value) -> Self::UnerasedValue; } -pub fn query_system<'a>( +pub fn query_system<'tcx>( local_providers: Providers, extern_providers: ExternProviders, on_disk_cache: Option, incremental: bool, -) -> QuerySystem<'a> { +) -> QuerySystem<'tcx> { QuerySystem { states: Default::default(), arenas: Default::default(), diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6ead03a527a7..ad782b3150b0 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -9,32 +9,36 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; +use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_index::Idx; use rustc_middle::bug; +#[expect(unused_imports, reason = "used by doc comments")] +use rustc_middle::dep_graph::DepKindVTable; use rustc_middle::dep_graph::{ - self, DepContext, DepKind, DepKindVTable, DepNode, DepNodeIndex, SerializedDepNodeIndex, - dep_kinds, + self, DepContext, DepNode, DepNodeIndex, DepNodeKey, DepsType, HasDepContext, + SerializedDepNodeIndex, dep_kinds, }; -use rustc_middle::query::Key; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, }; +use rustc_middle::query::plumbing::QueryVTable; +use rustc_middle::query::{ + Key, QueryCache, QueryContext, QueryJobId, QueryStackDeferred, QueryStackFrame, + QueryStackFrameExtra, +}; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; -use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{ - QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, - QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query, -}; -use rustc_query_system::{QueryOverflow, QueryOverflowNote}; +use rustc_query_system::query::QuerySideEffect; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; -use crate::QueryDispatcherUnerased; +use crate::error::{QueryOverflow, QueryOverflowNote}; +use crate::execution::{all_inactive, force_query}; +use crate::job::{QueryJobMap, find_dep_kind_root}; +use crate::{QueryDispatcherUnerased, QueryFlags, SemiDynamicQueryDispatcher}; /// Implements [`QueryContext`] for use by [`rustc_query_system`], since that /// crate does not have direct access to [`TyCtxt`]. @@ -48,28 +52,28 @@ impl<'tcx> QueryCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { QueryCtxt { tcx } } -} -impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type Deps = rustc_middle::dep_graph::DepsType; - type DepContext = TyCtxt<'tcx>; + fn depth_limit_error(self, job: QueryJobId) { + let job_map = self + .collect_active_jobs_from_all_queries(true) + .expect("failed to collect active queries"); + let (info, depth) = find_dep_kind_root(job, job_map); - #[inline] - fn dep_context(&self) -> &Self::DepContext { - &self.tcx - } -} + let suggested_limit = match self.tcx.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; -impl<'tcx> QueryContext for QueryCtxt<'tcx> { - type QueryInfo = QueryStackDeferred<'tcx>; - - #[inline] - fn jobserver_proxy(&self) -> &Proxy { - &self.tcx.jobserver_proxy + self.tcx.sess.dcx().emit_fatal(QueryOverflow { + span: info.job.span, + note: QueryOverflowNote { desc: info.frame.info.extract().description, depth }, + suggested_limit, + crate_name: self.tcx.crate_name(LOCAL_CRATE), + }); } #[inline] - fn next_job_id(self) -> QueryJobId { + pub(crate) fn next_job_id(self) -> QueryJobId { QueryJobId( NonZero::new( self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed), @@ -79,67 +83,14 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> { } #[inline] - fn current_query_job(self) -> Option { + pub(crate) fn current_query_job(self) -> Option { tls::with_related_context(self.tcx, |icx| icx.query) } - /// Returns a map of currently active query jobs. - /// - /// If `require_complete` is `true`, this function locks all shards of the - /// query results to produce a complete map, which always returns `Ok`. - /// Otherwise, it may return an incomplete map as an error if any shard - /// lock cannot be acquired. - /// - /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, - /// especially when called from within a deadlock handler, unless a - /// complete map is needed and no deadlock is possible at this call site. - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result>, QueryMap>> { - let mut jobs = QueryMap::default(); - let mut complete = true; - - for collect in super::COLLECT_ACTIVE_JOBS.iter() { - if collect(self.tcx, &mut jobs, require_complete).is_none() { - complete = false; - } - } - - if complete { Ok(jobs) } else { Err(jobs) } - } - - fn lift_query_info( - self, - info: &QueryStackDeferred<'tcx>, - ) -> rustc_query_system::query::QueryStackFrameExtra { - info.extract() - } - - // Interactions with on_disk_cache - fn load_side_effect( - self, - prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option { - self.tcx - .query_system - .on_disk_cache - .as_ref() - .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index)) - } - - #[inline(never)] - #[cold] - fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { - if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() { - c.store_side_effect(dep_node_index, side_effect) - } - } - /// Executes a job by changing the `ImplicitCtxt` to point to the /// new query job while it executes. #[inline(always)] - fn start_query( + pub(crate) fn start_query( self, token: QueryJobId, depth_limit: bool, @@ -168,24 +119,67 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> { }) } - fn depth_limit_error(self, job: QueryJobId) { - let query_map = self.collect_active_jobs(true).expect("failed to collect active queries"); - let (info, depth) = job.find_dep_kind_root(query_map); + /// Returns a map of currently active query jobs, collected from all queries. + /// + /// If `require_complete` is `true`, this function locks all shards of the + /// query results to produce a complete map, which always returns `Ok`. + /// Otherwise, it may return an incomplete map as an error if any shard + /// lock cannot be acquired. + /// + /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, + /// especially when called from within a deadlock handler, unless a + /// complete map is needed and no deadlock is possible at this call site. + pub fn collect_active_jobs_from_all_queries( + self, + require_complete: bool, + ) -> Result, QueryJobMap<'tcx>> { + let mut job_map_out = QueryJobMap::default(); + let mut complete = true; - let suggested_limit = match self.tcx.recursion_limit() { - Limit(0) => Limit(2), - limit => limit * 2, - }; + for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() { + if gather_fn(self.tcx, require_complete, &mut job_map_out).is_none() { + complete = false; + } + } - self.tcx.sess.dcx().emit_fatal(QueryOverflow { - span: info.job.span, - note: QueryOverflowNote { - desc: self.lift_query_info(&info.query.info).description, - depth, - }, - suggested_limit, - crate_name: self.tcx.crate_name(LOCAL_CRATE), - }); + if complete { Ok(job_map_out) } else { Err(job_map_out) } + } +} + +impl<'tcx> HasDepContext for QueryCtxt<'tcx> { + type Deps = DepsType; + type DepContext = TyCtxt<'tcx>; + + #[inline] + fn dep_context(&self) -> &Self::DepContext { + &self.tcx + } +} + +impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { + #[inline] + fn jobserver_proxy(&self) -> &Proxy { + &self.tcx.jobserver_proxy + } + + // Interactions with on_disk_cache + fn load_side_effect( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option { + self.tcx + .query_system + .on_disk_cache + .as_ref() + .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index)) + } + + #[inline(never)] + #[cold] + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { + if let Some(c) = self.tcx.query_system.on_disk_cache.as_ref() { + c.store_side_effect(dep_node_index, side_effect) + } } } @@ -215,16 +209,16 @@ pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { macro_rules! cycle_error_handling { ([]) => {{ - rustc_query_system::query::CycleErrorHandling::Error + rustc_middle::query::CycleErrorHandling::Error }}; ([(cycle_fatal) $($rest:tt)*]) => {{ - rustc_query_system::query::CycleErrorHandling::Fatal + rustc_middle::query::CycleErrorHandling::Fatal }}; ([(cycle_stash) $($rest:tt)*]) => {{ - rustc_query_system::query::CycleErrorHandling::Stash + rustc_middle::query::CycleErrorHandling::Stash }}; ([(cycle_delay_bug) $($rest:tt)*]) => {{ - rustc_query_system::query::CycleErrorHandling::DelayBug + rustc_middle::query::CycleErrorHandling::DelayBug }}; ([$other:tt $($modifiers:tt)*]) => { cycle_error_handling!([$($modifiers)*]) @@ -281,7 +275,10 @@ macro_rules! feedable { macro_rules! hash_result { ([][$V:ty]) => {{ - Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result))) + Some(|hcx, result| { + let result = rustc_middle::query::erase::restore_val::<$V>(*result); + rustc_middle::dep_graph::hash_result(hcx, &result) + }) }}; ([(no_hash) $($rest:tt)*][$V:ty]) => {{ None @@ -307,27 +304,42 @@ macro_rules! call_provider { }; } -macro_rules! should_ever_cache_on_disk { - ([]$yes:tt $no:tt) => {{ +/// Expands to one of two token trees, depending on whether the current query +/// has the `cache_on_disk_if` modifier. +macro_rules! if_cache_on_disk { + ([] $yes:tt $no:tt) => { $no - }}; - ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{ + }; + // The `cache_on_disk_if` modifier generates a synthetic `(cache_on_disk)`, + // modifier, for use by this macro and similar macros. + ([(cache_on_disk) $($rest:tt)*] $yes:tt $no:tt) => { $yes - }}; - ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => { - should_ever_cache_on_disk!([$($modifiers)*]$yes $no) + }; + ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { + if_cache_on_disk!([$($modifiers)*] $yes $no) }; } -fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( - (tcx, key, kind, name, do_describe): ( - TyCtxt<'tcx>, - K, - DepKind, - &'static str, - fn(TyCtxt<'tcx>, K) -> String, - ), -) -> QueryStackFrameExtra { +/// Conditionally expands to some token trees, if the current query has the +/// `cache_on_disk_if` modifier. +macro_rules! item_if_cache_on_disk { + ([] $($item:tt)*) => {}; + ([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => { + $($item)* + }; + ([$other:tt $($modifiers:tt)*] $($item:tt)*) => { + item_if_cache_on_disk! { [$($modifiers)*] $($item)* } + }; +} + +/// The deferred part of a deferred query stack frame. +fn mk_query_stack_frame_extra<'tcx, Cache>( + (tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key), +) -> QueryStackFrameExtra +where + Cache: QueryCache, + Cache::Key: Key, +{ let def_id = key.key_as_def_id(); // If reduced queries are requested, we may be printing a query stack due @@ -335,13 +347,13 @@ fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( let reduce_queries = with_reduced_queries(); // Avoid calling queries while formatting the description - let description = ty::print::with_no_queries!(do_describe(tcx, key)); + let description = ty::print::with_no_queries!((vtable.description_fn)(tcx, key)); let description = if tcx.sess.verbose_internals() { - format!("{description} [{name:?}]") + format!("{description} [{name:?}]", name = vtable.name) } else { description }; - let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { + let span = if vtable.dep_kind == dep_graph::dep_kinds::def_span || reduce_queries { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -349,7 +361,7 @@ fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( Some(key.default_span(tcx)) }; - let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { + let def_kind = if vtable.dep_kind == dep_graph::dep_kinds::def_kind || reduce_queries { // Try to avoid infinite recursion. None } else { @@ -358,49 +370,46 @@ fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( QueryStackFrameExtra::new(description, span, def_kind) } -pub(crate) fn create_query_frame< - 'tcx, - K: Copy + DynSend + DynSync + Key + for<'a> HashStable> + 'tcx, ->( +pub(crate) fn create_deferred_query_stack_frame<'tcx, Cache>( tcx: TyCtxt<'tcx>, - do_describe: fn(TyCtxt<'tcx>, K) -> String, - key: K, - kind: DepKind, - name: &'static str, -) -> QueryStackFrame> { - let def_id = key.key_as_def_id(); + vtable: &'tcx QueryVTable<'tcx, Cache>, + key: Cache::Key, +) -> QueryStackFrame> +where + Cache: QueryCache, + Cache::Key: Key + DynSend + DynSync, +{ + let kind = vtable.dep_kind; - let hash = || { - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - kind.as_usize().hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() - }) - }; - let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); + let hash = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + kind.as_usize().hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::() + }); - let info = - QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra); + let def_id: Option = key.key_as_def_id(); + let def_id_for_ty_in_cycle: Option = key.def_id_for_ty_in_cycle(); + let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra); QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } -pub(crate) fn encode_query_results<'a, 'tcx, Q>( - query: Q::Dispatcher, +pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) where - Q: QueryDispatcherUnerased<'tcx>, + Q: QueryDispatcherUnerased<'tcx, C, FLAGS>, Q::UnerasedValue: Encodable>, { let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name()); - assert!(query.query_state(qcx).all_inactive()); + assert!(all_inactive(query.query_state(qcx))); let cache = query.query_cache(qcx); cache.iter(&mut |key, value, dep_node| { - if query.cache_on_disk(qcx.tcx, key) { + if query.will_cache_on_disk_for_key(qcx.tcx, key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. @@ -413,15 +422,14 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( }); } -pub(crate) fn query_key_hash_verify<'tcx>( - query: impl QueryDispatcher>, +pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); - let mut map = UnordMap::default(); - let cache = query.query_cache(qcx); + let mut map = UnordMap::with_capacity(cache.len()); cache.iter(&mut |key, _, _| { let node = DepNode::construct(qcx.tcx, query.dep_kind(), key); if let Some(other_key) = map.insert(node, *key) { @@ -440,17 +448,21 @@ pub(crate) fn query_key_hash_verify<'tcx>( }); } -fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -where - Q: QueryDispatcher>, -{ +/// Implementation of [`DepKindVTable::try_load_from_on_disk_cache`] for queries. +pub(crate) fn try_load_from_on_disk_cache_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + tcx: TyCtxt<'tcx>, + dep_node: DepNode, +) { debug_assert!(tcx.dep_graph.is_green(&dep_node)); - let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| { + let key = C::Key::recover(tcx, &dep_node).unwrap_or_else(|| { panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash) }); - if query.cache_on_disk(tcx, &key) { - let _ = query.execute_query(tcx, key); + if query.will_cache_on_disk_for_key(tcx, &key) { + // Call `tcx.$query(key)` for its side-effect of loading the disk-cached + // value into memory. + query.call_query_method(tcx, key); } } @@ -486,10 +498,12 @@ where value } -fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool -where - Q: QueryDispatcher>, -{ +/// Implementation of [`DepKindVTable::force_from_dep_node`] for queries. +pub(crate) fn force_from_dep_node_inner<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + tcx: TyCtxt<'tcx>, + dep_node: DepNode, +) -> bool { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we @@ -508,7 +522,7 @@ where "calling force_from_dep_node() on dep_kinds::codegen_unit" ); - if let Some(key) = Q::Key::recover(tcx, &dep_node) { + if let Some(key) = C::Key::recover(tcx, &dep_node) { force_query(query, QueryCtxt::new(tcx), key, dep_node); true } else { @@ -516,75 +530,6 @@ where } } -pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>( - is_anon: bool, - is_eval_always: bool, -) -> DepKindVTable<'tcx> -where - Q: QueryDispatcherUnerased<'tcx>, -{ - let fingerprint_style = - >>::Key::fingerprint_style(); - - if is_anon || !fingerprint_style.reconstructible() { - return DepKindVTable { - is_anon, - is_eval_always, - fingerprint_style, - force_from_dep_node: None, - try_load_from_on_disk_cache: None, - name: Q::NAME, - }; - } - - DepKindVTable { - is_anon, - is_eval_always, - fingerprint_style, - force_from_dep_node: Some(|tcx, dep_node, _| { - force_from_dep_node(Q::query_dispatcher(tcx), tcx, dep_node) - }), - try_load_from_on_disk_cache: Some(|tcx, dep_node| { - try_load_from_on_disk_cache(Q::query_dispatcher(tcx), tcx, dep_node) - }), - name: Q::NAME, - } -} - -macro_rules! item_if_cached { - ([] $tokens:tt) => {}; - ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => { - $($tokens)* - }; - ([$other:tt $($modifiers:tt)*] $tokens:tt) => { - item_if_cached! { [$($modifiers)*] $tokens } - }; -} - -macro_rules! expand_if_cached { - ([], $tokens:expr) => {{ - None - }}; - ([(cache) $($rest:tt)*], $tokens:expr) => {{ - Some($tokens) - }}; - ([$other:tt $($modifiers:tt)*], $tokens:expr) => { - expand_if_cached!([$($modifiers)*], $tokens) - }; -} - -/// Don't show the backtrace for query system by default -/// use `RUST_BACKTRACE=full` to show all the backtraces -#[inline(never)] -pub(crate) fn __rust_begin_short_backtrace(f: F) -> T -where - F: FnOnce() -> T, -{ - let result = f(); - std::hint::black_box(()); - result -} - // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_with_all_queries`. macro_rules! define_queries { @@ -598,6 +543,7 @@ macro_rules! define_queries { pub(crate) mod query_impl { $(pub(crate) mod $name { use super::super::*; use std::marker::PhantomData; + use ::rustc_middle::query::erase::{self, Erased}; pub(crate) mod get_query_incr { use super::*; @@ -610,10 +556,10 @@ macro_rules! define_queries { span: Span, key: queries::$name::Key<'tcx>, mode: QueryMode, - ) -> Option>> { + ) -> Option>> { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - get_query_incr( + execution::get_query_incr( QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), span, @@ -632,8 +578,8 @@ macro_rules! define_queries { span: Span, key: queries::$name::Key<'tcx>, __mode: QueryMode, - ) -> Option>> { - Some(get_query_non_incr( + ) -> Option>> { + Some(execution::get_query_non_incr( QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), span, @@ -642,6 +588,36 @@ macro_rules! define_queries { } } + /// Defines an `invoke_provider` function that calls the query's provider, + /// to be used as a function pointer in the query's vtable. + /// + /// To mark a short-backtrace boundary, the function's actual name + /// (after demangling) must be `__rust_begin_short_backtrace`. + mod invoke_provider_fn { + use super::*; + use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased}; + + #[inline(never)] + pub(crate) fn __rust_begin_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + key: Key<'tcx>, + ) -> Erased> { + #[cfg(debug_assertions)] + let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); + + // Call the actual provider function for this query. + let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]); + + rustc_middle::ty::print::with_reduced_queries!({ + tracing::trace!(?provided_value); + }); + + // Erase the returned value, because `QueryVTable` uses erased values. + // For queries with `arena_cache`, this also arena-allocates the value. + provided_to_erased(tcx, provided_value) + } + } + pub(crate) fn make_query_vtable<'tcx>() -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> { @@ -652,57 +628,48 @@ macro_rules! define_queries { cycle_error_handling: cycle_error_handling!([$($modifiers)*]), query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), - cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), - execute_query: |tcx, key| erase(tcx.$name(key)), - compute: |tcx, key| { - #[cfg(debug_assertions)] - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - __rust_begin_short_backtrace(|| - queries::$name::provided_to_erased( - tcx, - { - let ret = call_provider!([$($modifiers)*][tcx, $name, key]); - rustc_middle::ty::print::with_reduced_queries!({ - tracing::trace!(?ret); - }); - ret - } - ) - ) - }, - can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false), - try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] { - |tcx, key, prev_index, index| { - if ::rustc_middle::query::cached::$name(tcx, key) { - let value = $crate::plumbing::try_load_from_disk::< - queries::$name::ProvidedValue<'tcx> - >( - tcx, - prev_index, - index, - ); - value.map(|value| queries::$name::provided_to_erased(tcx, value)) - } else { - None - } - } + will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] { + Some(::rustc_middle::queries::_cache_on_disk_if_fns::$name) } { - |_tcx, _key, _prev_index, _index| None + None + }), + call_query_method_fn: |tcx, key| { + // Call the query method for its side-effect of loading a value + // from disk-cache; the caller doesn't need the value. + let _ = tcx.$name(key); + }, + invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace, + try_load_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, prev_index, index| { + // Check the `cache_on_disk_if` condition for this key. + if !::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) { + return None; + } + + let value: queries::$name::ProvidedValue<'tcx> = + $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?; + + // Arena-alloc the value if appropriate, and erase it. + Some(queries::$name::provided_to_erased(tcx, value)) + }) + } { + None + }), + is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, index| -> bool { + ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && + $crate::plumbing::loadable_from_disk(tcx, index) + }) + } { + None }), value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar); - erase(result) - }, - loadable_from_disk: |_tcx, _key, _index| { - should_ever_cache_on_disk!([$($modifiers)*] { - ::rustc_middle::query::cached::$name(_tcx, _key) && - $crate::plumbing::loadable_from_disk(_tcx, _index) - } { - false - }) + erase::erase_val(result) }, hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), - format_value: |value| format!("{:?}", restore::>(*value)), + format_value: |value| format!("{:?}", erase::restore_val::>(*value)), + description_fn: $crate::queries::_description_fns::$name, } } @@ -711,47 +678,57 @@ macro_rules! define_queries { data: PhantomData<&'tcx ()> } - impl<'tcx> QueryDispatcherUnerased<'tcx> for QueryType<'tcx> { + const FLAGS: QueryFlags = QueryFlags { + is_anon: is_anon!([$($modifiers)*]), + is_depth_limit: depth_limit!([$($modifiers)*]), + is_feedable: feedable!([$($modifiers)*]), + }; + + impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS> + for QueryType<'tcx> + { type UnerasedValue = queries::$name::Value<'tcx>; - type Dispatcher = SemiDynamicQueryDispatcher< - 'tcx, - queries::$name::Storage<'tcx>, - { is_anon!([$($modifiers)*]) }, - { depth_limit!([$($modifiers)*]) }, - { feedable!([$($modifiers)*]) }, - >; const NAME: &'static &'static str = &stringify!($name); #[inline(always)] - fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher { + fn query_dispatcher(tcx: TyCtxt<'tcx>) + -> SemiDynamicQueryDispatcher<'tcx, queries::$name::Storage<'tcx>, FLAGS> + { SemiDynamicQueryDispatcher { vtable: &tcx.query_system.query_vtables.$name, } } #[inline(always)] - fn restore_val(value: >>::Value) -> Self::UnerasedValue { - restore::>(value) + fn restore_val(value: as QueryCache>::Value) + -> Self::UnerasedValue + { + erase::restore_val::>(value) } } - pub(crate) fn collect_active_jobs<'tcx>( + /// Internal per-query plumbing for collecting the set of active jobs for this query. + /// + /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`. + pub(crate) fn gather_active_jobs<'tcx>( tcx: TyCtxt<'tcx>, - qmap: &mut QueryMap>, require_complete: bool, + job_map_out: &mut QueryJobMap<'tcx>, ) -> Option<()> { - let make_query = |tcx, key| { - 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) + let make_frame = |tcx: TyCtxt<'tcx>, key| { + let vtable = &tcx.query_system.query_vtables.$name; + $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key) }; - let res = tcx.query_system.states.$name.collect_active_jobs( + + // Call `gather_active_jobs_inner` to do the actual work. + let res = crate::execution::gather_active_jobs_inner(&tcx.query_system.states.$name, tcx, - make_query, - qmap, + make_frame, require_complete, + job_map_out, ); + // this can be called during unwinding, and the function has a `try_`-prefix, so // don't `unwrap()` here, just manually check for `None` and do best-effort error // reporting. @@ -776,20 +753,24 @@ macro_rules! define_queries { ) } - item_if_cached! { [$($modifiers)*] { + item_if_cache_on_disk! { [$($modifiers)*] pub(crate) fn encode_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex ) { - $crate::plumbing::encode_query_results::>( + $crate::plumbing::encode_query_results::< + query_impl::$name::QueryType<'tcx>, + _, + _ + > ( query_impl::$name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), encoder, query_result_index, ) } - }} + } pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { $crate::plumbing::query_key_hash_verify( @@ -811,8 +792,8 @@ macro_rules! define_queries { } } - pub fn make_query_vtables<'tcx>() -> ::rustc_middle::query::PerQueryVTables<'tcx> { - ::rustc_middle::query::PerQueryVTables { + pub fn make_query_vtables<'tcx>() -> queries::PerQueryVTables<'tcx> { + queries::PerQueryVTables { $( $name: query_impl::$name::make_query_vtable(), )* @@ -821,10 +802,21 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const COLLECT_ACTIVE_JOBS: &[ - for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap>, bool) -> Option<()> - ] = - &[$(query_impl::$name::collect_active_jobs),*]; + /// Used by `collect_active_jobs_from_all_queries` to iterate over all + /// queries, and gather the active jobs for each query. + /// + /// (We arbitrarily use the word "gather" when collecting the jobs for + /// each individual query, so that we have distinct function names to + /// grep for.) + const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[ + for<'tcx> fn( + tcx: TyCtxt<'tcx>, + require_complete: bool, + job_map_out: &mut QueryJobMap<'tcx>, + ) -> Option<()> + ] = &[ + $( $crate::query_impl::$name::gather_active_jobs ),* + ]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache) @@ -836,126 +828,34 @@ macro_rules! define_queries { &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex) > - ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; + ] = &[ + $( + if_cache_on_disk!([$($modifiers)*] { + Some(query_impl::$name::encode_query_results) + } { + None + }) + ),* + ]; const QUERY_KEY_HASH_VERIFY: &[ for<'tcx> fn(TyCtxt<'tcx>) ] = &[$(query_impl::$name::query_key_hash_verify),*]; - /// Module containing a named function for each dep kind (including queries) - /// that creates a `DepKindVTable`. - /// - /// Consumed via `make_dep_kind_array!` to create a list of vtables. - #[expect(non_snake_case)] - mod _dep_kind_vtable_ctors { - use super::*; - use rustc_middle::bug; - use rustc_query_system::dep_graph::FingerprintStyle; + /// Declares a dep-kind vtable constructor for each query. + mod _dep_kind_vtable_ctors_for_queries { + use ::rustc_middle::dep_graph::DepKindVTable; + use $crate::dep_kind_vtables::make_dep_kind_vtable_for_query; - // We use this for most things when incr. comp. is turned off. - pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - 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", + $( + /// `DepKindVTable` constructor for this query. + pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { + use $crate::query_impl::$name::QueryType; + make_dep_kind_vtable_for_query::, _, _>( + is_eval_always!([$($modifiers)*]), + ) } - } - - // We use this for the forever-red node. - pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - 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", - } - } - - pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|tcx, _, prev_index| { - tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index); - true - }), - try_load_from_on_disk_cache: None, - name: &"SideEffect", - } - } - - pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: true, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Opaque, - force_from_dep_node: Some(|_, _, _| bug!("cannot force an anon node")), - try_load_from_on_disk_cache: None, - name: &"AnonZeroDeps", - } - } - - pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: true, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: None, - try_load_from_on_disk_cache: None, - name: &"TraitSelect", - } - } - - pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Opaque, - force_from_dep_node: None, - try_load_from_on_disk_cache: None, - name: &"CompileCodegenUnit", - } - } - - pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Opaque, - force_from_dep_node: None, - try_load_from_on_disk_cache: None, - name: &"CompileMonoItem", - } - } - - pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> { - DepKindVTable { - is_anon: false, - is_eval_always: false, - fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: None, - try_load_from_on_disk_cache: None, - name: &"Metadata", - } - } - - $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { - use $crate::query_impl::$name::QueryType; - $crate::plumbing::make_dep_kind_vtable_for_query::>( - is_anon!([$($modifiers)*]), - is_eval_always!([$($modifiers)*]), - ) - })* - } - - pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] { - arena.alloc_from_iter(rustc_middle::make_dep_kind_array!(_dep_kind_vtable_ctors)) + )* } } } diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 7be75ea88aca..679fee49b6c6 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -6,8 +6,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::DefPathData; +use rustc_middle::query::QueryCache; use rustc_middle::ty::TyCtxt; -use rustc_query_system::query::QueryCache; pub(crate) struct QueryKeyStringCache { def_id_cache: FxHashMap, diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_query_impl/src/values.rs similarity index 84% rename from compiler/rustc_middle/src/values.rs rename to compiler/rustc_query_impl/src/values.rs index bc73d36216ef..67bc6893a320 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -7,16 +7,37 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_query_system::Value; -use rustc_query_system::query::{CycleError, report_cycle}; +use rustc_middle::dep_graph::dep_kinds; +use rustc_middle::query::CycleError; +use rustc_middle::query::plumbing::CyclePlaceholder; +use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; -use crate::dep_graph::dep_kinds; -use crate::query::plumbing::CyclePlaceholder; -use crate::ty::{self, Representability, Ty, TyCtxt}; +use crate::job::report_cycle; -impl<'tcx> Value> for Ty<'_> { +pub(crate) trait Value<'tcx>: Sized { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) + -> Self; +} + +impl<'tcx, T> Value<'tcx> for T { + default fn from_cycle_error( + tcx: TyCtxt<'tcx>, + cycle_error: &CycleError, + _guar: ErrorGuaranteed, + ) -> T { + tcx.sess.dcx().abort_if_errors(); + bug!( + "<{} as Value>::from_cycle_error called without errors: {:#?}", + std::any::type_name::(), + cycle_error.cycle, + ); + } +} + +impl<'tcx> Value<'tcx> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. @@ -24,13 +45,13 @@ impl<'tcx> Value> for Ty<'_> { } } -impl<'tcx> Value> for Result>, CyclePlaceholder> { +impl<'tcx> Value<'tcx> for Result>, CyclePlaceholder> { fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } } -impl<'tcx> Value> for ty::SymbolName<'_> { +impl<'tcx> Value<'tcx> for ty::SymbolName<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, _guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. @@ -42,7 +63,7 @@ impl<'tcx> Value> for ty::SymbolName<'_> { } } -impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { +impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -50,9 +71,9 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { ) -> Self { let err = Ty::new_error(tcx, guar); - let arity = if let Some(frame) = cycle_error.cycle.get(0) - && frame.query.dep_kind == dep_kinds::fn_sig - && let Some(def_id) = frame.query.def_id + let arity = if let Some(info) = cycle_error.cycle.get(0) + && info.frame.dep_kind == dep_kinds::fn_sig + && let Some(def_id) = info.frame.def_id && let Some(node) = tcx.hir_get_if_local(def_id) && let Some(sig) = node.fn_sig() { @@ -76,7 +97,7 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { } } -impl<'tcx> Value> for Representability { +impl<'tcx> Value<'tcx> for Representability { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -85,10 +106,10 @@ impl<'tcx> Value> for Representability { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in &cycle_error.cycle { - if info.query.dep_kind == dep_kinds::representability - && let Some(field_id) = info.query.def_id + if info.frame.dep_kind == dep_kinds::representability + && let Some(field_id) = info.frame.def_id && let Some(field_id) = field_id.as_local() - && let Some(DefKind::Field) = info.query.info.def_kind + && let Some(DefKind::Field) = info.frame.info.def_kind { let parent_id = tcx.parent(field_id.to_def_id()); let item_id = match tcx.def_kind(parent_id) { @@ -99,8 +120,8 @@ impl<'tcx> Value> for Representability { } } for info in &cycle_error.cycle { - if info.query.dep_kind == dep_kinds::representability_adt_ty - && let Some(def_id) = info.query.def_id_for_ty_in_cycle + if info.frame.dep_kind == dep_kinds::representability_adt_ty + && let Some(def_id) = info.frame.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) { @@ -112,7 +133,7 @@ impl<'tcx> Value> for Representability { } } -impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { +impl<'tcx> Value<'tcx> for ty::EarlyBinder<'_, Ty<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -122,7 +143,7 @@ impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { } } -impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { +impl<'tcx> Value<'tcx> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -132,7 +153,7 @@ impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig< } } -impl<'tcx> Value> for &[ty::Variance] { +impl<'tcx> Value<'tcx> for &[ty::Variance] { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -141,9 +162,9 @@ impl<'tcx> Value> for &[ty::Variance] { search_for_cycle_permutation( &cycle_error.cycle, |cycle| { - if let Some(frame) = cycle.get(0) - && frame.query.dep_kind == dep_kinds::variances_of - && let Some(def_id) = frame.query.def_id + if let Some(info) = cycle.get(0) + && info.frame.dep_kind == dep_kinds::variances_of + && let Some(def_id) = info.frame.def_id { let n = tcx.generics_of(def_id).own_params.len(); ControlFlow::Break(vec![ty::Bivariant; n].leak()) @@ -180,7 +201,7 @@ fn search_for_cycle_permutation( otherwise() } -impl<'tcx, T> Value> for Result> { +impl<'tcx, T> Value<'tcx> for Result> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -189,8 +210,8 @@ impl<'tcx, T> Value> for Result> let diag = search_for_cycle_permutation( &cycle_error.cycle, |cycle| { - if cycle[0].query.dep_kind == dep_kinds::layout_of - && let Some(def_id) = cycle[0].query.def_id_for_ty_in_cycle + if cycle[0].frame.dep_kind == dep_kinds::layout_of + && let Some(def_id) = cycle[0].frame.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && let def_kind = tcx.def_kind(def_id) && matches!(def_kind, DefKind::Closure) @@ -213,18 +234,18 @@ impl<'tcx, T> Value> for Result> tcx.def_kind_descr_article(def_kind, def_id.to_def_id()), tcx.def_kind_descr(def_kind, def_id.to_def_id()), ); - for (i, frame) in cycle.iter().enumerate() { - if frame.query.dep_kind != dep_kinds::layout_of { + for (i, info) in cycle.iter().enumerate() { + if info.frame.dep_kind != dep_kinds::layout_of { continue; } - let Some(frame_def_id) = frame.query.def_id_for_ty_in_cycle else { + let Some(frame_def_id) = info.frame.def_id_for_ty_in_cycle else { continue; }; let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else { continue; }; let frame_span = - frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span); + info.frame.info.default_span(cycle[(i + 1) % cycle.len()].span); if frame_span.is_dummy() { continue; } @@ -273,7 +294,7 @@ impl<'tcx, T> Value> for Result> // item_and_field_ids should form a cycle where each field contains the // type in the next element in the list -pub fn recursive_type_error( +fn recursive_type_error( tcx: TyCtxt<'_>, mut item_and_field_ids: Vec<(LocalDefId, LocalDefId)>, representable_ids: &FxHashSet, diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 73ab03576dec..bd12dcbfe0d1 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -5,26 +5,15 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -parking_lot = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } 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_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" # tidy-alphabetical-end - -[dependencies.hashbrown] -version = "0.16.1" -default-features = false -features = ["nightly"] # for may_dangle diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl deleted file mode 100644 index d2ab2d34c5fc..000000000000 --- a/compiler/rustc_query_system/messages.ftl +++ /dev/null @@ -1,30 +0,0 @@ -query_system_cycle = cycle detected when {$stack_bottom} - .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 - -query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive - -query_system_cycle_recursive_ty_alias = type aliases cannot be recursive -query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle -query_system_cycle_recursive_ty_alias_help2 = see for more information - -query_system_cycle_stack_middle = ...which requires {$desc}... - -query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle - -query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again - -query_system_cycle_usage = cycle used when {$usage} - -query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node} - -query_system_increment_compilation_note1 = please follow the instructions below to create a bug report with the provided information -query_system_increment_compilation_note2 = for incremental compilation bugs, having a reproduction is vital -query_system_increment_compilation_note3 = an ideal reproduction consists of the code before and some patch that then triggers the bug when applied and compiled again -query_system_increment_compilation_note4 = as a workaround, you can run {$run_cmd} to allow your project to compile - -query_system_overflow_note = query depth increased by {$depth} when {$desc} - -query_system_query_overflow = queries overflow the depth limit! - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) - -query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs deleted file mode 100644 index 72bdcd2d534d..000000000000 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ /dev/null @@ -1,341 +0,0 @@ -//! This module defines the [`DepNode`] type which the compiler uses to represent -//! nodes in the [dependency graph]. A `DepNode` consists of a [`DepKind`] (which -//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.) -//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which -//! depends on the node's `DepKind`. Together, the kind and the fingerprint -//! fully identify a dependency node, even across multiple compilation sessions. -//! In other words, the value of the fingerprint does not depend on anything -//! that is specific to a given compilation session, like an unpredictable -//! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a -//! pointer. The concept behind this could be compared to how git commit hashes -//! uniquely identify a given commit. The fingerprinting approach has -//! a few advantages: -//! -//! * A `DepNode` can simply be serialized to disk and loaded in another session -//! without the need to do any "rebasing" (like we have to do for Spans and -//! NodeIds) or "retracing" (like we had to do for `DefId` in earlier -//! implementations of the dependency graph). -//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to -//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. -//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into -//! memory without any post-processing (e.g., "abomination-style" pointer -//! reconstruction). -//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that -//! refer to things that do not exist anymore. In previous implementations -//! `DepNode` contained a `DefId`. A `DepNode` referring to something that -//! had been removed between the previous and the current compilation session -//! could not be instantiated because the current compilation session -//! contained no `DefId` for thing that had been removed. -//! -//! `DepNode` definition happens in `rustc_middle` with the -//! `define_dep_nodes!()` macro. This macro defines the `DepKind` enum. Each -//! `DepKind` has its own parameters that are needed at runtime in order to -//! construct a valid `DepNode` fingerprint. However, only `CompileCodegenUnit` -//! and `CompileMonoItem` are constructed explicitly (with -//! `make_compile_codegen_unit` and `make_compile_mono_item`). -//! -//! Because the macro sees what parameters a given `DepKind` requires, it can -//! "infer" some properties for each kind of `DepNode`: -//! -//! * Whether a `DepNode` of a given kind has any parameters at all. Some -//! `DepNode`s could represent global concepts with only one value. -//! * Whether it is possible, in principle, to reconstruct a query key from a -//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, -//! in which case it is possible to map the node's fingerprint back to the -//! `DefId` it was computed from. In other cases, too much information gets -//! lost during fingerprint computation. -//! -//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with -//! `DepNode::new()`, ensure that only valid `DepNode` instances can be -//! constructed. For example, the API does not allow for constructing -//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. -//! More generally speaking, it relieves the user of the `DepNode` API of -//! having to know how to compute the expected fingerprint for a given set of -//! node parameters. -//! -//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html - -use std::fmt; -use std::hash::Hash; - -use rustc_data_structures::AtomicRef; -use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; -use rustc_hir::definitions::DefPathHash; -use rustc_macros::{Decodable, Encodable}; - -use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex}; -use crate::ich::StableHashingContext; - -/// 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 - } -} - -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 { - /// 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: DepKind) -> DepNode - where - Tcx: super::DepContext, - { - debug_assert_eq!(tcx.fingerprint_style(kind), FingerprintStyle::Unit); - DepNode { kind, hash: Fingerprint::ZERO.into() } - } - - pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode - where - Tcx: super::DepContext, - Key: DepNodeParams, - { - let hash = arg.to_fingerprint(tcx); - let dep_node = DepNode { kind, hash: hash.into() }; - - #[cfg(debug_assertions)] - { - if !tcx.fingerprint_style(kind).reconstructible() - && (tcx.sess().opts.unstable_opts.incremental_info - || tcx.sess().opts.unstable_opts.query_dep_graph) - { - tcx.dep_graph().register_dep_node_debug_str(dep_node, || arg.to_debug_str(tcx)); - } - } - - dep_node - } - - /// 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: DepKind) -> Self - where - Tcx: super::DepContext, - { - debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); - DepNode { kind, hash: def_path_hash.0.into() } - } -} - -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 { - (*DEP_NODE_DEBUG)(*self, f) - } -} - -pub trait DepNodeParams: fmt::Debug + Sized { - fn fingerprint_style() -> FingerprintStyle; - - /// This method turns the parameters of a DepNodeConstructor into an opaque - /// Fingerprint to be used in DepNode. - /// Not all DepNodeParams support being turned into a Fingerprint (they - /// don't need to if the corresponding DepNode is anonymous). - fn to_fingerprint(&self, _: Tcx) -> Fingerprint { - panic!("Not implemented. Accidentally called on anonymous node?") - } - - fn to_debug_str(&self, tcx: Tcx) -> String; - - /// This method tries to recover the query key from the given `DepNode`, - /// something which is needed when forcing `DepNode`s during red-green - /// evaluation. The query system will only call this method if - /// `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; -} - -impl DepNodeParams for T -where - T: for<'a> HashStable> + fmt::Debug, -{ - #[inline(always)] - default fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::Opaque - } - - #[inline(always)] - default fn to_fingerprint(&self, tcx: Tcx) -> Fingerprint { - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - self.hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }) - } - - #[inline(always)] - default fn to_debug_str(&self, tcx: Tcx) -> String { - // Make sure to print dep node params with reduced queries since printing - // may themselves call queries, which may lead to (possibly untracked!) - // query cycles. - tcx.with_reduced_queries(|| format!("{self:?}")) - } - - #[inline(always)] - default fn recover(_: Tcx, _: &DepNode) -> Option { - None - } -} - -/// This struct stores function pointers and other metadata for a particular DepKind. -/// -/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value -/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual -/// jump table instead of large matches. -pub struct DepKindVTable { - /// Anonymous queries cannot be replayed from one compiler invocation to the next. - /// When their result is needed, it is recomputed. They are useful for fine-grained - /// dependency tracking, and caching within one compiler invocation. - pub is_anon: bool, - - /// Eval-always queries do not track their dependencies, and are always recomputed, even if - /// their inputs have not changed since the last compiler invocation. The result is still - /// cached within one compiler invocation. - pub is_eval_always: bool, - - /// Whether the query key can be recovered from the hashed fingerprint. - /// See [DepNodeParams] trait for the behaviour of each key type. - pub fingerprint_style: FingerprintStyle, - - /// The red/green evaluation system will try to mark a specific DepNode in the - /// dependency graph as green by recursively trying to mark the dependencies of - /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` - /// where we don't know if it is red or green and we therefore actually have - /// to recompute its value in order to find out. Since the only piece of - /// information that we have at that point is the `DepNode` we are trying to - /// re-evaluate, we need some way to re-run a query from just that. This is what - /// `force_from_dep_node()` implements. - /// - /// In the general case, a `DepNode` consists of a `DepKind` and an opaque - /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint - /// is usually constructed by computing a stable hash of the query-key that the - /// `DepNode` corresponds to. Consequently, it is not in general possible to go - /// back from hash to query-key (since hash functions are not reversible). For - /// this reason `force_from_dep_node()` is expected to fail from time to time - /// because we just cannot find out, from the `DepNode` alone, what the - /// corresponding query-key is and therefore cannot re-run the query. - /// - /// The system deals with this case letting `try_mark_green` fail which forces - /// the root query to be re-evaluated. - /// - /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. - /// Fortunately, we can use some contextual information that will allow us to - /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we - /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a - /// valid `DefPathHash`. Since we also always build a huge table that maps every - /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have - /// everything we need to re-run the query. - /// - /// Take the `mir_promoted` query as an example. Like many other queries, it - /// just has a single parameter: the `DefId` of the item it will compute the - /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` - /// 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>, - - /// Invoke a query to put the on-disk cached value in memory. - 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 -/// save in between runs. These IDs do not have a `DefId` but rather -/// some independent path or string that persists between runs without -/// the need to be mapped or unmapped. (This ensures we can serialize -/// them even in the absence of a tcx.) -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -pub struct WorkProductId { - hash: Fingerprint, -} - -impl WorkProductId { - pub fn from_cgu_name(cgu_name: &str) -> WorkProductId { - let mut hasher = StableHasher::new(); - cgu_name.hash(&mut hasher); - WorkProductId { hash: hasher.finish() } - } -} - -impl HashStable for WorkProductId { - #[inline] - fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - self.hash.hash_stable(hcx, hasher) - } -} -impl ToStableHashKey for WorkProductId { - type KeyType = Fingerprint; - #[inline] - fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { - self.hash - } -} -impl StableOrd for WorkProductId { - // Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well - const CAN_USE_UNSTABLE_SORT: bool = true; - - // `WorkProductId` sort order is not affected by (de)serialization. - const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); -} - -// Some types are used a lot. Make sure they don't unintentionally get bigger. -#[cfg(target_pointer_width = "64")] -mod size_asserts { - use rustc_data_structures::static_assert_size; - - use super::*; - // tidy-alphabetical-start - static_assert_size!(DepKind, 2); - #[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); - // tidy-alphabetical-end -} diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs deleted file mode 100644 index 874b41cbf3b1..000000000000 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ /dev/null @@ -1,173 +0,0 @@ -pub mod debug; -pub mod dep_node; -mod edges; -mod graph; -mod query; -mod serialized; - -use std::panic; - -pub use dep_node::{DepKind, DepKindVTable, DepNode, DepNodeParams, WorkProductId}; -pub(crate) use graph::DepGraphData; -pub use graph::{DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result}; -pub use query::DepGraphQuery; -use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_data_structures::sync::DynSync; -use rustc_session::Session; -pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; -use tracing::instrument; - -use self::graph::{MarkFrame, print_markframe_trace}; -use crate::ich::StableHashingContext; - -pub trait DepContext: Copy { - 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; - - /// Access the profiler. - fn profiler(&self) -> &SelfProfilerRef; - - /// Access the compiler session. - fn sess(&self) -> &Session; - - fn dep_kind_vtable(&self, dep_node: DepKind) -> &DepKindVTable; - - #[inline(always)] - fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { - let vtable = self.dep_kind_vtable(kind); - if vtable.is_anon { - return FingerprintStyle::Opaque; - } - vtable.fingerprint_style - } - - #[inline(always)] - /// Return whether this kind always require evaluation. - fn is_eval_always(self, kind: DepKind) -> bool { - self.dep_kind_vtable(kind).is_eval_always - } - - /// Try to force a dep node to execute and see if it's green. - /// - /// Returns true if the query has actually been forced. It is valid that a query - /// fails to be forced, e.g. when the query key cannot be reconstructed from the - /// dep-node or when the query kind outright does not support it. - #[inline] - #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node( - self, - dep_node: DepNode, - prev_index: SerializedDepNodeIndex, - frame: &MarkFrame<'_>, - ) -> bool { - if let Some(force_fn) = self.dep_kind_vtable(dep_node.kind).force_from_dep_node { - match panic::catch_unwind(panic::AssertUnwindSafe(|| { - force_fn(self, dep_node, prev_index) - })) { - Err(value) => { - if !value.is::() { - print_markframe_trace(self.dep_graph(), frame); - } - panic::resume_unwind(value) - } - Ok(query_has_been_forced) => query_has_been_forced, - } - } else { - false - } - } - - /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(self, dep_node: DepNode) { - if let Some(try_load_fn) = self.dep_kind_vtable(dep_node.kind).try_load_from_on_disk_cache { - try_load_fn(self, dep_node) - } - } - - fn with_reduced_queries(self, _: impl FnOnce() -> T) -> T; -} - -pub trait Deps: DynSync { - /// 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>); - - fn name(dep_kind: DepKind) -> &'static str; - - /// 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; - - /// We use this to create a side effect node. - const DEP_KIND_SIDE_EFFECT: DepKind; - - /// We use this to create the anon node with zero dependencies. - const DEP_KIND_ANON_ZERO_DEPS: 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 Deps: self::Deps; - type DepContext: self::DepContext; - - fn dep_context(&self) -> &Self::DepContext; -} - -impl HasDepContext for T { - type Deps = T::Deps; - type DepContext = Self; - - fn dep_context(&self) -> &Self::DepContext { - self - } -} - -impl HasDepContext for (T, Q) { - type Deps = T::Deps; - type DepContext = T::DepContext; - - fn dep_context(&self) -> &Self::DepContext { - self.0.dep_context() - } -} - -/// Describes the contents of the fingerprint generated by a given query. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum FingerprintStyle { - /// The fingerprint is actually a DefPathHash. - DefPathHash, - /// The fingerprint is actually a HirId. - HirId, - /// Query key was `()` or equivalent, so fingerprint is just zero. - Unit, - /// Some opaque hash. - Opaque, -} - -impl FingerprintStyle { - #[inline] - pub const fn reconstructible(self) -> bool { - match self { - FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => { - true - } - FingerprintStyle::Opaque => false, - } - } -} diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 840f0b35266d..2e118dc3359f 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,13 +1,20 @@ -use rustc_ast as ast; +use std::hash::Hash; + use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_session::Session; use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData, Symbol}; +use rustc_span::{CachingSourceMapView, DUMMY_SP, Pos, Span}; -use crate::ich; +// Very often, we are hashing something that does not need the `CachingSourceMapView`, so we +// initialize it lazily. +#[derive(Clone)] +enum CachingSourceMap<'a> { + Unused(&'a SourceMap), + InUse(CachingSourceMapView<'a>), +} /// This is the context state available during incr. comp. hashing. It contains /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., @@ -19,10 +26,7 @@ pub struct StableHashingContext<'a> { // The value of `-Z incremental-ignore-spans`. // This field should only be used by `unstable_opts_incremental_ignore_span` incremental_ignore_spans: bool, - // Very often, we are hashing something that does not need the - // `CachingSourceMapView`, so we initialize it lazily. - raw_source_map: &'a SourceMap, - caching_source_map: Option>, + caching_source_map: CachingSourceMap<'a>, hashing_controls: HashingControls, } @@ -34,8 +38,7 @@ impl<'a> StableHashingContext<'a> { StableHashingContext { untracked, incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, - caching_source_map: None, - raw_source_map: sess.source_map(), + caching_source_map: CachingSourceMap::Unused(sess.source_map()), hashing_controls: HashingControls { hash_spans: hash_spans_initial }, } } @@ -49,81 +52,145 @@ impl<'a> StableHashingContext<'a> { } #[inline] - pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - if let Some(def_id) = def_id.as_local() { - self.local_def_path_hash(def_id) - } else { - self.untracked.cstore.read().def_path_hash(def_id) - } - } - - #[inline] - pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { - self.untracked.definitions.read().def_path_hash(def_id) - } - - #[inline] - pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { + fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { match self.caching_source_map { - Some(ref mut sm) => sm, - ref mut none => { - *none = Some(CachingSourceMapView::new(self.raw_source_map)); - none.as_mut().unwrap() + CachingSourceMap::InUse(ref mut sm) => sm, + CachingSourceMap::Unused(sm) => { + self.caching_source_map = CachingSourceMap::InUse(CachingSourceMapView::new(sm)); + self.source_map() // this recursive call will hit the `InUse` case } } } - #[inline] - pub fn is_ignored_attr(&self, name: Symbol) -> bool { - ich::IGNORED_ATTRIBUTES.contains(&name) - } - - #[inline] - pub fn hashing_controls(&self) -> HashingControls { - self.hashing_controls.clone() - } -} - -impl<'a> HashStable> for ast::NodeId { - #[inline] - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - panic!("Node IDs should not appear in incremental state"); - } -} - -impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { - #[inline] - fn hash_spans(&self) -> bool { - self.hashing_controls.hash_spans - } - - #[inline] - fn unstable_opts_incremental_ignore_spans(&self) -> bool { - self.incremental_ignore_spans - } - - #[inline] - fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - self.def_path_hash(def_id) - } - #[inline] fn def_span(&self, def_id: LocalDefId) -> Span { self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP) } #[inline] - fn span_data_to_lines_and_cols( - &mut self, - span: &SpanData, - ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)> { - self.source_map().span_data_to_lines_and_cols(span) - } - - #[inline] - fn hashing_controls(&self) -> HashingControls { - self.hashing_controls.clone() + pub fn hashing_controls(&self) -> HashingControls { + self.hashing_controls } } +impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` fields (that + /// would be similar to hashing pointers, since those are just offsets into the `SourceMap`). + /// Instead, we hash the (file name, line, column) triple, which stays the same even if the + /// containing `SourceFile` has moved within the `SourceMap`. + /// + /// Also note that we are hashing byte offsets for the column, not unicode codepoint offsets. + /// For the purpose of the hash that's sufficient. Also, hashing filenames is expensive so we + /// avoid doing it twice when the span starts and ends in the same file, which is almost always + /// the case. + /// + /// IMPORTANT: changes to this method should be reflected in implementations of `SpanEncoder`. + #[inline] + fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher) { + const TAG_VALID_SPAN: u8 = 0; + const TAG_INVALID_SPAN: u8 = 1; + const TAG_RELATIVE_SPAN: u8 = 2; + + if !self.hashing_controls().hash_spans { + return; + } + + let span = span.data_untracked(); + span.ctxt.hash_stable(self, hasher); + span.parent.hash_stable(self, hasher); + + if span.is_dummy() { + Hash::hash(&TAG_INVALID_SPAN, hasher); + return; + } + + let parent = span.parent.map(|parent| self.def_span(parent).data_untracked()); + if let Some(parent) = parent + && parent.contains(span) + { + // This span is enclosed in a definition: only hash the relative position. This catches + // a subset of the cases from the `file.contains(parent.lo)`. But we can do this check + // cheaply without the expensive `span_data_to_lines_and_cols` query. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + (span.lo - parent.lo).to_u32().hash_stable(self, hasher); + (span.hi - parent.lo).to_u32().hash_stable(self, hasher); + return; + } + + // If this is not an empty or invalid span, we want to hash the last position that belongs + // to it, as opposed to hashing the first position past it. + let Some((file, line_lo, col_lo, line_hi, col_hi)) = + self.source_map().span_data_to_lines_and_cols(&span) + else { + Hash::hash(&TAG_INVALID_SPAN, hasher); + return; + }; + + if let Some(parent) = parent + && file.contains(parent.lo) + { + // This span is relative to another span in the same file, + // only hash the relative position. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + Hash::hash(&(span.lo.0.wrapping_sub(parent.lo.0)), hasher); + Hash::hash(&(span.hi.0.wrapping_sub(parent.lo.0)), hasher); + return; + } + + Hash::hash(&TAG_VALID_SPAN, hasher); + Hash::hash(&file.stable_id, hasher); + + // Hash both the length and the end location (line/column) of a span. If we hash only the + // length, for example, then two otherwise equal spans with different end locations will + // have the same hash. This can cause a problem during incremental compilation wherein a + // previous result for a query that depends on the end location of a span will be + // incorrectly reused when the end location of the span it depends on has changed (see + // issue #74890). A similar analysis applies if some query depends specifically on the + // length of the span, but we only hash the end location. So hash both. + + let col_lo_trunc = (col_lo.0 as u64) & 0xFF; + let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; + let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; + let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; + let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; + let len = (span.hi - span.lo).0; + Hash::hash(&col_line, hasher); + Hash::hash(&len, hasher); + } + + #[inline] + fn def_path_hash(&self, def_id: DefId) -> DefPathHash { + if let Some(def_id) = def_id.as_local() { + self.untracked.definitions.read().def_path_hash(def_id) + } else { + self.untracked.cstore.read().def_path_hash(def_id) + } + } + + /// Assert that the provided `HashStableContext` is configured with the default + /// `HashingControls`. We should always have bailed out before getting to here with a + /// non-default mode. With this check in place, we can avoid the need to maintain separate + /// versions of `ExpnData` hashes for each permutation of `HashingControls` settings. + #[inline] + fn assert_default_hashing_controls(&self, msg: &str) { + let hashing_controls = self.hashing_controls; + let HashingControls { hash_spans } = hashing_controls; + + // Note that we require that `hash_spans` be the inverse of the global `-Z + // incremental-ignore-spans` option. Normally, this option is disabled, in which case + // `hash_spans` must be true. + // + // Span hashing can also be disabled without `-Z incremental-ignore-spans`. This is the + // case for instance when building a hash for name mangling. Such configuration must not be + // used for metadata. + assert_eq!( + hash_spans, !self.incremental_ignore_spans, + "Attempted hashing of {msg} with non-default HashingControls: {hashing_controls:?}" + ); + } +} + +impl<'a> rustc_abi::HashStableContext for StableHashingContext<'a> {} +impl<'a> rustc_ast::HashStableContext for StableHashingContext<'a> {} +impl<'a> rustc_hir::HashStableContext for StableHashingContext<'a> {} impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index fe6fb3d65194..5592f6553971 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -2,14 +2,18 @@ //! from various crates in no particular order. use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::{self as hir, HashIgnoredAttrId}; -use rustc_span::SourceFile; +use rustc_span::{SourceFile, Symbol, sym}; use smallvec::SmallVec; +use {rustc_ast as ast, rustc_hir as hir}; use crate::ich::StableHashingContext; -impl<'ctx> rustc_abi::HashStableContext for StableHashingContext<'ctx> {} -impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {} +impl<'a> HashStable> for ast::NodeId { + #[inline] + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + panic!("Node IDs should not appear in incremental state"); + } +} impl<'a> HashStable> for [hir::Attribute] { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -24,7 +28,7 @@ impl<'a> HashStable> for [hir::Attribute] { .filter(|attr| { attr.is_doc_comment().is_none() // FIXME(jdonszelmann) have a better way to handle ignored attrs - && !attr.name().is_some_and(|ident| hcx.is_ignored_attr(ident)) + && !attr.name().is_some_and(|ident| is_ignored_attr(ident)) }) .collect(); @@ -35,10 +39,18 @@ impl<'a> HashStable> for [hir::Attribute] { } } -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { - fn hash_attr_id(&mut self, _id: &HashIgnoredAttrId, _hasher: &mut StableHasher) { - /* we don't hash HashIgnoredAttrId, we ignore them */ - } +#[inline] +fn is_ignored_attr(name: Symbol) -> bool { + const IGNORED_ATTRIBUTES: &[Symbol] = &[ + sym::cfg_trace, // FIXME(#138844) should this really be ignored? + sym::rustc_if_this_changed, + sym::rustc_then_this_would_need, + sym::rustc_clean, + sym::rustc_partition_reused, + sym::rustc_partition_codegened, + sym::rustc_expected_cgu_reuse, + ]; + IGNORED_ATTRIBUTES.contains(&name) } impl<'a> HashStable> for SourceFile { diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 25778add60a9..99575299c978 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -1,19 +1,6 @@ //! ICH - Incremental Compilation Hash -use rustc_span::{Symbol, sym}; - pub use self::hcx::StableHashingContext; mod hcx; mod impls_syntax; - -pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ - sym::cfg_trace, // FIXME should this really be ignored? - sym::rustc_if_this_changed, - sym::rustc_then_this_would_need, - sym::rustc_dirty, - sym::rustc_clean, - sym::rustc_partition_reused, - sym::rustc_partition_codegened, - sym::rustc_expected_cgu_reuse, -]; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index cdfe3454061c..bb077d02422b 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,18 +1,8 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![feature(assert_matches)] -#![feature(core_intrinsics)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(min_specialization)] // tidy-alphabetical-end -pub mod cache; -pub mod dep_graph; -mod error; pub mod ich; pub mod query; -mod values; - -pub use error::{QueryOverflow, QueryOverflowNote}; -pub use values::Value; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs deleted file mode 100644 index bba1703dfbb6..000000000000 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::fmt::Debug; -use std::hash::Hash; - -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_span::ErrorGuaranteed; - -use super::QueryStackFrameExtra; -use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; -use crate::ich::StableHashingContext; -use crate::query::caches::QueryCache; -use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState}; - -pub type HashResult = Option, &V) -> Fingerprint>; - -/// Trait that can be used as a vtable for a single query, providing operations -/// and metadata for that query. -/// -/// Implemented by `rustc_query_impl::SemiDynamicQueryDispatcher`, which -/// mostly delegates to `rustc_middle::query::plumbing::QueryVTable`. -/// Those types are not visible from this `rustc_query_system` crate. -/// -/// "Dispatcher" should be understood as a near-synonym of "vtable". -pub trait QueryDispatcher: Copy { - fn name(self) -> &'static str; - - // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, - // but it isn't necessary. - type Key: DepNodeParams + Eq + Hash + Copy + Debug; - type Value: Copy; - - type Cache: QueryCache; - - 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 - where - Qcx: 'a; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache - where - Qcx: 'a; - - fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value; - - fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value; - - fn try_load_from_disk( - self, - tcx: Qcx, - key: &Self::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option; - - fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool; - - /// Synthesize an error value to let compilation continue after a cycle. - fn value_from_cycle_error( - self, - tcx: Qcx::DepContext, - cycle_error: &CycleError, - guar: ErrorGuaranteed, - ) -> Self::Value; - - fn anon(self) -> bool; - fn eval_always(self) -> bool; - fn depth_limit(self) -> bool; - fn feedable(self) -> bool; - - fn dep_kind(self) -> DepKind; - fn cycle_error_handling(self) -> CycleErrorHandling; - 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 { - 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 deleted file mode 100644 index 5810ce0cbe66..000000000000 --- a/compiler/rustc_query_system/src/query/job.rs +++ /dev/null @@ -1,661 +0,0 @@ -use std::fmt::Debug; -use std::hash::Hash; -use std::io::Write; -use std::iter; -use std::num::NonZero; -use std::sync::Arc; - -use parking_lot::{Condvar, Mutex}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{Diag, DiagCtxtHandle}; -use rustc_hir::def::DefKind; -use rustc_session::Session; -use rustc_span::{DUMMY_SP, Span}; - -use super::QueryStackFrameExtra; -use crate::dep_graph::DepContext; -use crate::error::CycleStack; -use crate::query::plumbing::CycleError; -use crate::query::{QueryContext, QueryStackFrame}; - -/// Represents a span and a query key. -#[derive(Clone, Debug)] -pub struct QueryInfo { - /// The span corresponding to the reason for which this query was required. - pub span: Span, - pub query: QueryStackFrame, -} - -impl QueryInfo { - pub(crate) fn lift>( - &self, - qcx: Qcx, - ) -> QueryInfo { - QueryInfo { span: self.span, query: self.query.lift(qcx) } - } -} - -pub type QueryMap = FxHashMap>; - -/// A value uniquely identifying an active query job. -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] -pub struct QueryJobId(pub NonZero); - -impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { - map.get(&self).unwrap().query.clone() - } - - fn span(self, map: &QueryMap) -> Span { - map.get(&self).unwrap().job.span - } - - fn parent(self, map: &QueryMap) -> Option { - map.get(&self).unwrap().job.parent - } - - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { - map.get(&self).unwrap().job.latch.as_ref() - } -} - -#[derive(Clone, Debug)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, -} - -/// Represents an active query job. -#[derive(Debug)] -pub struct QueryJob { - pub id: QueryJobId, - - /// The span corresponding to the reason for which this query was required. - pub span: Span, - - /// The parent query job which created this job and is implicitly waiting on it. - pub parent: Option, - - /// The latch that is used to wait on this job. - latch: Option>, -} - -impl Clone for QueryJob { - fn clone(&self) -> Self { - Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } - } -} - -impl QueryJob { - /// Creates a new query job. - #[inline] - pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { - QueryJob { id, span, parent, latch: None } - } - - pub(super) fn latch(&mut self) -> QueryLatch { - if self.latch.is_none() { - self.latch = Some(QueryLatch::new()); - } - self.latch.as_ref().unwrap().clone() - } - - /// Signals to waiters that the query is complete. - /// - /// This does nothing for single threaded rustc, - /// as there are no concurrent jobs which could be waiting on us - #[inline] - pub fn signal_complete(self) { - if let Some(latch) = self.latch { - latch.set(); - } - } -} - -impl QueryJobId { - pub(super) fn find_cycle_in_stack( - &self, - query_map: QueryMap, - current_job: &Option, - span: Span, - ) -> CycleError { - // Find the waitee amongst `current_job` parents - let mut cycle = Vec::new(); - let mut current_job = Option::clone(current_job); - - while let Some(job) = current_job { - let info = query_map.get(&job).unwrap(); - cycle.push(QueryInfo { span: info.job.span, query: info.query.clone() }); - - if job == *self { - cycle.reverse(); - - // This is the end of the cycle - // The span entry we included was for the usage - // of the cycle itself, and not part of the cycle - // Replace it with the span which caused the cycle to form - cycle[0].span = span; - // Find out why the cycle itself was used - let usage = info - .job - .parent - .as_ref() - .map(|parent| (info.job.span, parent.query(&query_map))); - return CycleError { usage, cycle }; - } - - current_job = info.job.parent; - } - - panic!("did not find a cycle") - } - - #[cold] - #[inline(never)] - pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { - let mut depth = 1; - let info = query_map.get(&self).unwrap(); - let dep_kind = info.query.dep_kind; - let mut current_id = info.job.parent; - let mut last_layout = (info.clone(), depth); - - while let Some(id) = current_id { - let info = query_map.get(&id).unwrap(); - if info.query.dep_kind == dep_kind { - depth += 1; - last_layout = (info.clone(), depth); - } - current_id = info.job.parent; - } - last_layout - } -} - -#[derive(Debug)] -struct QueryWaiter { - query: Option, - condvar: Condvar, - span: Span, - cycle: Mutex>>, -} - -#[derive(Debug)] -struct QueryLatchInfo { - complete: bool, - waiters: Vec>>, -} - -#[derive(Debug)] -pub(super) struct QueryLatch { - info: Arc>>, -} - -impl Clone for QueryLatch { - fn clone(&self) -> Self { - Self { info: Arc::clone(&self.info) } - } -} - -impl QueryLatch { - fn new() -> Self { - QueryLatch { - info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), - } - } - - /// Awaits for the query job to complete. - pub(super) fn wait_on( - &self, - qcx: impl QueryContext, - query: Option, - span: Span, - ) -> Result<(), CycleError> { - let waiter = - Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); - self.wait_on_inner(qcx, &waiter); - // FIXME: Get rid of this lock. We have ownership of the QueryWaiter - // although another thread may still have a Arc reference so we cannot - // use Arc::get_mut - let mut cycle = waiter.cycle.lock(); - match cycle.take() { - None => Ok(()), - Some(cycle) => Err(cycle), - } - } - - /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, qcx: impl QueryContext, 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 - // the `wait` call below, by 1) the `set` method or 2) by deadlock detection. - // Both of these will remove it from the `waiters` list before resuming - // this thread. - info.waiters.push(Arc::clone(waiter)); - - // If this detects a deadlock and the deadlock handler wants to resume this thread - // we have to be in the `wait` call. This is ensured by the deadlock handler - // getting the self.info lock. - rustc_thread_pool::mark_blocked(); - let proxy = qcx.jobserver_proxy(); - proxy.release_thread(); - waiter.condvar.wait(&mut info); - // Release the lock before we potentially block in `acquire_thread` - drop(info); - proxy.acquire_thread(); - } - } - - /// Sets the latch and resumes all waiters on it - fn set(&self) { - let mut info = self.info.lock(); - debug_assert!(!info.complete); - info.complete = true; - let registry = rustc_thread_pool::Registry::current(); - for waiter in info.waiters.drain(..) { - rustc_thread_pool::mark_unblocked(®istry); - waiter.condvar.notify_one(); - } - } - - /// Removes a single waiter from the list of waiters. - /// This is used to break query cycles. - 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 - info.waiters.remove(waiter) - } -} - -/// A resumable waiter of a query. The usize is the index into waiters in the query's latch -type Waiter = (QueryJobId, usize); - -/// Visits all the non-resumable and resumable waiters of a query. -/// Only waiters in a query are visited. -/// `visit` is called for every waiter and is passed a query waiting on `query_ref` -/// and a span indicating the reason the query waited on `query_ref`. -/// If `visit` returns Some, this function returns. -/// For visits of non-resumable waiters it returns the return value of `visit`. -/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the -/// required information to resume the waiter. -/// If all `visit` calls returns None, this function also returns None. -fn visit_waiters( - query_map: &QueryMap, - query: QueryJobId, - mut visit: F, -) -> Option> -where - F: FnMut(Span, QueryJobId) -> Option>, -{ - // 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) - && let Some(cycle) = visit(query.span(query_map), parent) - { - return Some(cycle); - } - - // Visit the explicit waiters which use condvars and are resumable - if let Some(latch) = query.latch(query_map) { - for (i, waiter) in latch.info.lock().waiters.iter().enumerate() { - if let Some(waiter_query) = waiter.query { - if visit(waiter.span, waiter_query).is_some() { - // Return a value which indicates that this waiter can be resumed - return Some(Some((query, i))); - } - } - } - } - - None -} - -/// Look for query cycles by doing a depth first search starting at `query`. -/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. -/// If a cycle is detected, this initial value is replaced with the span causing -/// the cycle. -fn cycle_check( - query_map: &QueryMap, - query: QueryJobId, - span: Span, - stack: &mut Vec<(Span, QueryJobId)>, - visited: &mut FxHashSet, -) -> Option> { - if !visited.insert(query) { - return if let Some(p) = stack.iter().position(|q| q.1 == query) { - // We detected a query cycle, fix up the initial span and return Some - - // Remove previous stack entries - stack.drain(0..p); - // Replace the span for the first query with the cycle cause - stack[0].0 = span; - Some(None) - } else { - None - }; - } - - // Query marked as visited is added it to the stack - stack.push((span, query)); - - // Visit all the waiters - let r = visit_waiters(query_map, query, |span, successor| { - cycle_check(query_map, successor, span, stack, visited) - }); - - // Remove the entry in our stack if we didn't find a cycle - if r.is_none() { - stack.pop(); - } - - r -} - -/// Finds out if there's a path to the compiler root (aka. code which isn't in a query) -/// from `query` without going through any of the queries in `visited`. -/// This is achieved with a depth first search. -fn connected_to_root( - query_map: &QueryMap, - query: QueryJobId, - visited: &mut FxHashSet, -) -> bool { - // We already visited this or we're deliberately ignoring it - if !visited.insert(query) { - return false; - } - - // This query is connected to the root (it has no query parent), return true - if query.parent(query_map).is_none() { - return true; - } - - visit_waiters(query_map, query, |_, successor| { - connected_to_root(query_map, successor, visited).then_some(None) - }) - .is_some() -} - -// Deterministically pick an query from a list -fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T -where - F: Fn(&T) -> (Span, QueryJobId), -{ - // Deterministically pick an entry point - // FIXME: Sort this instead - queries - .iter() - .min_by_key(|v| { - let (span, query) = f(v); - let hash = query.query(query_map).hash; - // Prefer entry points which have valid spans for nicer error messages - // We add an integer to the tuple ensuring that entry points - // with valid spans are picked first - let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; - (span_cmp, hash) - }) - .unwrap() -} - -/// Looks for query cycles starting from the last query in `jobs`. -/// If a cycle is found, all queries in the cycle is removed from `jobs` and -/// the function return true. -/// If a cycle was not found, the starting query is removed from `jobs` and -/// the function returns false. -fn remove_cycle( - query_map: &QueryMap, - jobs: &mut Vec, - wakelist: &mut Vec>>, -) -> bool { - let mut visited = FxHashSet::default(); - let mut stack = Vec::new(); - // Look for a cycle starting with the last query in `jobs` - if let Some(waiter) = - cycle_check(query_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) - { - // The stack is a vector of pairs of spans and queries; reverse it so that - // the earlier entries require later entries - let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); - - // Shift the spans so that queries are matched with the span for their waitee - spans.rotate_right(1); - - // Zip them back together - let mut stack: Vec<_> = iter::zip(spans, queries).collect(); - - // Remove the queries in our cycle from the list of jobs to look at - for r in &stack { - if let Some(pos) = jobs.iter().position(|j| j == &r.1) { - jobs.remove(pos); - } - } - - // Find the queries in the cycle which are - // connected to queries outside the cycle - let entry_points = stack - .iter() - .filter_map(|&(span, query)| { - if query.parent(query_map).is_none() { - // This query is connected to the root (it has no query parent) - Some((span, query, None)) - } else { - let mut waiters = Vec::new(); - // Find all the direct waiters who lead to the root - visit_waiters(query_map, query, |span, waiter| { - // Mark all the other queries in the cycle as already visited - let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); - - if connected_to_root(query_map, waiter, &mut visited) { - waiters.push((span, waiter)); - } - - None - }); - if waiters.is_empty() { - None - } else { - // Deterministically pick one of the waiters to show to the user - let waiter = *pick_query(query_map, &waiters, |s| *s); - Some((span, query, Some(waiter))) - } - } - }) - .collect::)>>(); - - // Deterministically pick an entry point - let (_, entry_point, usage) = pick_query(query_map, &entry_points, |e| (e.0, e.1)); - - // Shift the stack so that our entry point is first - let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); - if let Some(pos) = entry_point_pos { - stack.rotate_left(pos); - } - - let usage = usage.as_ref().map(|(span, query)| (*span, query.query(query_map))); - - // Create the cycle error - let error = CycleError { - usage, - cycle: stack - .iter() - .map(|&(s, ref q)| QueryInfo { span: s, query: q.query(query_map) }) - .collect(), - }; - - // We unwrap `waiter` here since there must always be one - // edge which is resumable / waited using a query latch - let (waitee_query, waiter_idx) = waiter.unwrap(); - - // Extract the waiter we want to resume - let waiter = waitee_query.latch(query_map).unwrap().extract_waiter(waiter_idx); - - // Set the cycle error so it will be picked up when resumed - *waiter.cycle.lock() = Some(error); - - // Put the waiter on the list of things to resume - wakelist.push(waiter); - - true - } else { - false - } -} - -/// Detects query cycles by using depth first search over all active query jobs. -/// If a query cycle is found it will break the cycle by finding an edge which -/// uses a query latch and then resuming that waiter. -/// 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. -pub fn break_query_cycles( - query_map: QueryMap, - registry: &rustc_thread_pool::Registry, -) { - let mut wakelist = Vec::new(); - // It is OK per the comments: - // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 - // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392 - #[allow(rustc::potential_query_instability)] - let mut jobs: Vec = query_map.keys().cloned().collect(); - - let mut found_cycle = false; - - while jobs.len() > 0 { - if remove_cycle(&query_map, &mut jobs, &mut wakelist) { - found_cycle = true; - } - } - - // Check that a cycle was found. It is possible for a deadlock to occur without - // a query cycle if a query which can be waited on uses Rayon to do multithreading - // internally. Such a query (X) may be executing on 2 threads (A and B) and A may - // wait using Rayon on B. Rayon may then switch to executing another query (Y) - // which in turn will wait on X causing a deadlock. We have a false dependency from - // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here - // only considers the true dependency and won't detect a cycle. - if !found_cycle { - panic!( - "deadlock detected as we're unable to find a query cycle to break\n\ - current query map:\n{:#?}", - query_map - ); - } - - // Mark all the thread we're about to wake up as unblocked. This needs to be done before - // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we - // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked. - for _ in 0..wakelist.len() { - rustc_thread_pool::mark_unblocked(registry); - } - - for waiter in wakelist.into_iter() { - waiter.condvar.notify_one(); - } -} - -#[inline(never)] -#[cold] -pub fn report_cycle<'a>( - sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, -) -> Diag<'a> { - assert!(!stack.is_empty()); - - let span = stack[0].query.info.default_span(stack[1 % stack.len()].span); - - let mut cycle_stack = Vec::new(); - - use crate::error::StackCount; - let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; - - for i in 1..stack.len() { - let query = &stack[i].query; - let span = query.info.default_span(stack[(i + 1) % stack.len()].span); - cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() }); - } - - let mut cycle_usage = None; - if let Some((span, ref query)) = *usage { - cycle_usage = Some(crate::error::CycleUsage { - span: query.info.default_span(span), - usage: query.info.description.to_string(), - }); - } - - let alias = - if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) { - Some(crate::error::Alias::Ty) - } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) { - Some(crate::error::Alias::Trait) - } else { - None - }; - - let cycle_diag = crate::error::Cycle { - span, - cycle_stack, - stack_bottom: stack[0].query.info.description.to_owned(), - alias, - cycle_usage, - stack_count, - note_span: (), - }; - - sess.dcx().create_err(cycle_diag) -} - -pub fn print_query_stack( - qcx: Qcx, - mut current_query: Option, - dcx: DiagCtxtHandle<'_>, - limit_frames: Option, - mut file: Option, -) -> usize { - // Be careful relying on global state here: this code is called from - // a panic hook, which means that the global `DiagCtxt` may be in a weird - // state if it was responsible for triggering the panic. - let mut count_printed = 0; - let mut count_total = 0; - - // Make use of a partial query map if we fail to take locks collecting active queries. - let query_map = match qcx.collect_active_jobs(false) { - Ok(query_map) => query_map, - Err(query_map) => query_map, - }; - - if let Some(ref mut file) = file { - let _ = writeln!(file, "\n\nquery stack during panic:"); - } - while let Some(query) = current_query { - let Some(query_info) = query_map.get(&query) else { - break; - }; - let query_extra = qcx.lift_query_info(&query_info.query.info); - if Some(count_printed) < limit_frames || limit_frames.is_none() { - // Only print to stderr as many stack frames as `num_frames` when present. - dcx.struct_failure_note(format!( - "#{} [{:?}] {}", - count_printed, query_info.query.dep_kind, query_extra.description - )) - .with_span(query_info.job.span) - .emit(); - count_printed += 1; - } - - if let Some(ref mut file) = file { - let _ = writeln!( - file, - "#{} [{}] {}", - count_total, - qcx.dep_context().dep_kind_vtable(query_info.query.dep_kind).name, - query_extra.description - ); - } - - current_query = query_info.job.parent; - count_total += 1; - } - - if let Some(ref mut file) = file { - let _ = writeln!(file, "end of query stack"); - } - count_total -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 701253d50fcc..87be4358fb8b 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -1,145 +1,7 @@ use std::fmt::Debug; -use std::marker::PhantomData; -use std::mem::transmute; -use std::sync::Arc; -use rustc_data_structures::jobserver::Proxy; -use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_errors::DiagInner; -use rustc_hashes::Hash64; -use rustc_hir::def::DefKind; use rustc_macros::{Decodable, Encodable}; -use rustc_span::Span; -use rustc_span::def_id::DefId; - -pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; -pub use self::dispatcher::{HashResult, QueryDispatcher}; -pub use self::job::{ - QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack, - report_cycle, -}; -pub use self::plumbing::*; -use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; - -mod caches; -mod dispatcher; -mod job; -mod plumbing; - -/// How a particular query deals with query cycle errors. -/// -/// Inspected by the code that actually handles cycle errors, to decide what -/// approach to use. -#[derive(Copy, Clone)] -pub enum CycleErrorHandling { - Error, - Fatal, - DelayBug, - Stash, -} - -/// Description of a frame in the query stack. -/// -/// This is mostly used in case of cycles for error reporting. -#[derive(Clone, Debug)] -pub struct QueryStackFrame { - /// This field initially stores a `QueryStackDeferred` during collection, - /// but can later be changed to `QueryStackFrameExtra` containing concrete information - /// by calling `lift`. This is done so that collecting query does not need to invoke - /// queries, instead `lift` will call queries in a more appropriate location. - pub info: I, - - pub dep_kind: DepKind, - /// This hash is used to deterministically pick - /// a query to remove cycles in the parallel compiler. - hash: Hash64, - pub def_id: Option, - /// A def-id that is extracted from a `Ty` in a query key - pub def_id_for_ty_in_cycle: Option, -} - -impl QueryStackFrame { - #[inline] - pub fn new( - info: I, - dep_kind: DepKind, - hash: impl FnOnce() -> Hash64, - def_id: Option, - def_id_for_ty_in_cycle: Option, - ) -> Self { - Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle } - } - - fn lift>( - &self, - qcx: Qcx, - ) -> QueryStackFrame { - QueryStackFrame { - info: qcx.lift_query_info(&self.info), - dep_kind: self.dep_kind, - hash: self.hash, - def_id: self.def_id, - def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle, - } - } -} - -#[derive(Clone, Debug)] -pub struct QueryStackFrameExtra { - pub description: String, - span: Option, - pub def_kind: Option, -} - -impl QueryStackFrameExtra { - #[inline] - pub fn new(description: String, span: Option, def_kind: Option) -> Self { - Self { description, span, def_kind } - } - - // FIXME(eddyb) Get more valid `Span`s on queries. - #[inline] - pub fn default_span(&self, span: Span) -> Span { - if !span.is_dummy() { - return span; - } - self.span.unwrap_or(span) - } -} - -/// Track a 'side effect' for a particular query. -/// This is used to hold a closure which can create `QueryStackFrameExtra`. -#[derive(Clone)] -pub struct QueryStackDeferred<'tcx> { - _dummy: PhantomData<&'tcx ()>, - - // `extract` may contain references to 'tcx, but we can't tell drop checking that it won't - // access it in the destructor. - extract: Arc QueryStackFrameExtra + DynSync + DynSend>, -} - -impl<'tcx> QueryStackDeferred<'tcx> { - pub fn new( - context: C, - extract: fn(C) -> QueryStackFrameExtra, - ) -> Self { - let extract: Arc QueryStackFrameExtra + DynSync + DynSend + 'tcx> = - Arc::new(move || extract(context)); - // SAFETY: The `extract` closure does not access 'tcx in its destructor as the only - // captured variable is `context` which is Copy and cannot have a destructor. - Self { _dummy: PhantomData, extract: unsafe { transmute(extract) } } - } - - pub fn extract(&self) -> QueryStackFrameExtra { - (self.extract)() - } -} - -impl<'tcx> Debug for QueryStackDeferred<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("QueryStackDeferred") - } -} /// Tracks 'side effects' for a particular query. /// This struct is saved to disk along with the query result, @@ -158,39 +20,3 @@ pub enum QuerySideEffect { /// effect dep node as a dependency. Diagnostic(DiagInner), } - -pub trait QueryContext: HasDepContext { - type QueryInfo: Clone; - - /// Gets a jobserver reference which is used to release then acquire - /// a token while waiting on a query. - fn jobserver_proxy(&self) -> &Proxy; - - fn next_job_id(self) -> QueryJobId; - - /// Get the query information from the TLS context. - fn current_query_job(self) -> Option; - - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result, QueryMap>; - - fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra; - - /// Load a side effect associated to the node in the previous session. - fn load_side_effect( - self, - prev_dep_node_index: SerializedDepNodeIndex, - ) -> Option; - - /// Register a side effect for the given node, for use in next session. - fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); - - /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. - fn start_query(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R) - -> R; - - fn depth_limit_error(self, job: QueryJobId); -} diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs deleted file mode 100644 index 133904f59af1..000000000000 --- a/compiler/rustc_query_system/src/values.rs +++ /dev/null @@ -1,21 +0,0 @@ -use rustc_span::ErrorGuaranteed; - -use crate::dep_graph::DepContext; -use crate::query::CycleError; - -pub trait Value: Sized { - fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self; -} - -impl Value for T { - default fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed) -> T { - tcx.sess().dcx().abort_if_errors(); - // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's - // non-trivial to define it earlier. - panic!( - "<{} as Value>::from_cycle_error called without errors: {:#?}", - std::any::type_name::(), - cycle_error.cycle, - ); - } -} diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index dd15e879c644..feb0a93d0788 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -16,13 +16,11 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl deleted file mode 100644 index 4a980b2bd747..000000000000 --- a/compiler/rustc_resolve/messages.ftl +++ /dev/null @@ -1,531 +0,0 @@ -resolve_accessible_unsure = not sure whether the path is accessible or not - .note = the type may have associated items, but we are currently not checking them - -resolve_add_as_non_derive = - add as non-Derive macro - `#[{$macro_path}]` - -resolve_added_macro_use = - have you added the `#[macro_use]` on the module/import? - -resolve_ancestor_only = - visibilities can only be restricted to ancestor modules - -resolve_anonymous_lifetime_non_gat_report_error = missing lifetime in associated type - .label = this lifetime must come from the implemented type - .note = in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - -resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here - -resolve_associated_const_with_similar_name_exists = - there is an associated constant with a similar name - -resolve_associated_fn_with_similar_name_exists = - there is an associated function with a similar name - -resolve_associated_type_with_similar_name_exists = - there is an associated type with a similar name - -resolve_attempt_to_use_non_constant_value_in_constant = - attempt to use a non-constant value in a constant - -resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion = - non-constant value - -resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = - consider using `{$suggestion}` instead of `{$current}` - -resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = - this would need to be a `{$suggestion}` - -resolve_attributes_starting_with_rustc_are_reserved = - attributes starting with `rustc` are reserved for use by the `rustc` compiler - -resolve_binding_in_never_pattern = - never patterns cannot contain variable bindings - .suggestion = use a wildcard `_` instead - -resolve_binding_shadows_something_unacceptable = - {$shadowing_binding}s cannot shadow {$shadowed_binding}s - .label = cannot be named the same as {$article} {$shadowed_binding} - .label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here - -resolve_binding_shadows_something_unacceptable_suggestion = - try specify the pattern arguments - -resolve_cannot_be_reexported_crate_public = - `{$ident}` is only public within the crate, and cannot be re-exported outside - -resolve_cannot_be_reexported_private = - `{$ident}` is private, and cannot be re-exported - -resolve_cannot_capture_dynamic_environment_in_fn_item = - can't capture dynamic environment in a fn item - .help = use the `|| {"{"} ... {"}"}` closure form instead - -resolve_cannot_determine_import_resolution = - cannot determine resolution for the import - .note = import resolution is stuck, try simplifying other imports - -resolve_cannot_determine_macro_resolution = - cannot determine resolution for the {$kind} `{$path}` - .note = import resolution is stuck, try simplifying macro imports - -resolve_cannot_find_builtin_macro_with_name = - cannot find a built-in macro with name `{$ident}` - -resolve_cannot_find_ident_in_this_scope = - cannot find {$expected} `{$ident}` in this scope - -resolve_cannot_glob_import_possible_crates = - cannot glob-import all possible crates - -resolve_cannot_use_through_an_import = - cannot use {$article} {$descr} through an import - .note = the {$descr} imported here - -resolve_change_import_binding = - you can use `as` to change the binding name of the import - -resolve_consider_adding_a_derive = - consider adding a derive - -resolve_consider_adding_macro_export = - consider adding a `#[macro_export]` to the macro in the imported module - -resolve_consider_declaring_with_pub = - consider declaring type or module `{$ident}` with `pub` - -resolve_consider_making_the_field_public = - { $number_of_fields -> - [one] consider making the field publicly accessible - *[other] consider making the fields publicly accessible - } - -resolve_consider_marking_as_pub = - consider marking `{$ident}` as `pub` in the imported module - -resolve_consider_marking_as_pub_crate = - in case you want to use the macro within this crate only, reduce the visibility to `pub(crate)` - -resolve_consider_move_macro_position = - consider moving the definition of `{$ident}` before this call - - -resolve_const_not_member_of_trait = - const `{$const_}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_const_param_in_enum_discriminant = - const parameters may not be used in enum discriminant values - -resolve_const_param_in_non_trivial_anon_const = - const parameters may only be used as standalone arguments here, i.e. `{$name}` - -resolve_constructor_private_if_any_field_private = - a constructor is private if any of the fields is private - -resolve_elided_anonymous_lifetime_report_error = - `&` without an explicit lifetime name cannot be used here - .label = explicit lifetime name needed here - -resolve_elided_anonymous_lifetime_report_error_suggestion = - consider introducing a higher-ranked lifetime here - -resolve_expected_module_found = - expected module, found {$res} `{$path_str}` - .label = not a module - -resolve_explicit_anonymous_lifetime_report_error = - `'_` cannot be used here - .label = `'_` is a reserved lifetime name - -resolve_explicit_unsafe_traits = - unsafe traits like `{$ident}` should be implemented explicitly - -resolve_extern_crate_loading_macro_not_at_crate_root = - an `extern crate` loading macros must be at the crate root - -resolve_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition - .suggestion = convert it to a `use` - -resolve_extern_crate_self_requires_renaming = - `extern crate self;` requires renaming - .suggestion = rename the `self` crate to be able to import it - -resolve_forward_declared_generic_in_const_param_ty = - const parameter types cannot reference parameters before they are declared - .label = const parameter type cannot reference `{$param}` before it is declared - -resolve_forward_declared_generic_param = - generic parameter defaults cannot reference parameters before they are declared - .label = cannot reference `{$param}` before it is declared - -resolve_found_an_item_configured_out = - found an item that was configured out - -resolve_generic_arguments_in_macro_path = - generic arguments in macro path - -resolve_generic_params_from_outer_item = - can't use {$is_self -> - [true] `Self` - *[false] generic parameters - } from outer item - .label = use of {$is_self -> - [true] `Self` - *[false] generic parameter - } from outer item - .refer_to_type_directly = refer to the type directly here instead - .suggestion = try introducing a local generic parameter here - .note = nested items are independent from their parent item for everything except for privacy and name resolution - -resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it - -resolve_generic_params_from_outer_item_const_param = const parameter from outer item - -resolve_generic_params_from_outer_item_inner_item = {$is_self -> - [true] `Self` - *[false] generic parameter - } used in this inner {$descr} - -resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl` - -resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here - -resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it - -resolve_generic_params_from_outer_item_ty_param = type parameter from outer item - -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 - -resolve_ident_bound_more_than_once_in_same_pattern = - identifier `{$identifier}` is bound more than once in the same pattern - .label = used in a pattern more than once - -resolve_ident_imported_here_but_it_is_desc = - `{$imported_ident}` is imported here, but it is {$imported_ident_desc} - -resolve_ident_in_scope_but_it_is_desc = - `{$imported_ident}` is in scope, but it is {$imported_ident_desc} - -resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here - -resolve_imported_crate = `$crate` may not be imported - -resolve_imported_macro_not_found = imported macro not found - -resolve_imports_cannot_refer_to = - imports cannot refer to {$what} - -resolve_indeterminate = - cannot determine resolution for the visibility - -resolve_invalid_asm_sym = - invalid `sym` operand - .label = is a local variable - .help = `sym` operands must refer to either a function or a static - -resolve_is_private = - {$ident_descr} `{$ident}` is private - .label = private {$ident_descr} - -resolve_item_was_behind_feature = - the item is gated behind the `{$feature}` feature - -resolve_item_was_cfg_out = the item is gated here - -resolve_label_with_similar_name_reachable = - a label with a similar name is reachable - -resolve_legacy_derive_helpers = derive helper attribute is used before it is introduced - .label = the attribute is introduced here - -resolve_lending_iterator_report_error = - associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type - -resolve_lifetime_param_in_enum_discriminant = - lifetime parameters may not be used in enum discriminant values - -resolve_lifetime_param_in_non_trivial_anon_const = - lifetime parameters may not be used in const expressions - -resolve_lowercase_self = - attempt to use a non-constant value in a constant - .suggestion = try using `Self` - -resolve_macro_cannot_use_as_attr = - `{$ident}` exists, but has no `attr` rules - -resolve_macro_cannot_use_as_derive = - `{$ident}` exists, but has no `derive` rules - -resolve_macro_cannot_use_as_fn_like = - `{$ident}` exists, but has no rules for function-like invocation - -resolve_macro_defined_later = - a macro with the same name exists, but it appears later - -resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments = - macro-expanded `extern crate` items cannot shadow names passed with `--extern` - -resolve_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths - .note = the macro is defined here - -resolve_macro_expected_found = - expected {$expected}, found {$found} `{$macro_path}` - .label = not {$article} {$expected} - -resolve_macro_extern_deprecated = - `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - .help = try an outer attribute: `#[macro_use]` - -resolve_macro_is_private = macro `{$ident}` is private - -resolve_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used - -resolve_macro_use_deprecated = - applying the `#[macro_use]` attribute to an `extern crate` item is deprecated - .help = remove it and import macros at use sites with a `use` item instead - -resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self` - -resolve_macro_use_name_already_in_use = - `{$name}` is already in scope - .note = macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) - -resolve_method_not_member_of_trait = - method `{$method}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_missing_macro_rules_name = maybe you have forgotten to define a name for this `macro_rules!` - -resolve_module_only = - visibility must resolve to a module - -resolve_name_defined_multiple_time = - the name `{$name}` is defined multiple times - .note = `{$name}` must be defined only once in the {$descr} namespace of this {$container} - -resolve_name_defined_multiple_time_old_binding_definition = - previous definition of the {$old_kind} `{$name}` here - -resolve_name_defined_multiple_time_old_binding_import = - previous import of the {$old_kind} `{$name}` here - -resolve_name_defined_multiple_time_redefined = - `{$name}` redefined here - -resolve_name_defined_multiple_time_reimported = - `{$name}` reimported here - -resolve_name_is_already_used_as_generic_parameter = - the name `{$name}` is already used for a generic parameter in this item's generic parameters - .label = already used - .first_use_of_name = first use of `{$name}` - -resolve_name_reserved_in_attribute_namespace = - name `{$ident}` is reserved in attribute namespace - -resolve_note_and_refers_to_the_item_defined_here = - {$first -> - [true] {$dots -> - [true] the {$binding_descr} `{$binding_name}` is defined here... - *[false] the {$binding_descr} `{$binding_name}` is defined here - } - *[false] {$dots -> - [true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here... - *[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here - } - } - -resolve_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location} - .label = not found from {$location} - .help = import `macro_rules` with `use` to make it callable above its definition - -resolve_outer_ident_is_not_publicly_reexported = - {$outer_ident_descr} `{$outer_ident}` is not publicly re-exported - -resolve_param_in_enum_discriminant = - generic parameters may not be used in enum discriminant values - .label = cannot perform const operation using `{$name}` - -resolve_param_in_non_trivial_anon_const = - generic parameters may not be used in const operations - .label = cannot perform const operation using `{$name}` - -resolve_param_in_non_trivial_anon_const_help = - add `#![feature(generic_const_exprs)]` to allow generic const expressions - -resolve_param_in_ty_of_const_param = - the type of const parameters must not depend on other generic parameters - .label = the type must not depend on the parameter `{$name}` - -resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}` - -resolve_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported - .suggestion = consider making the `extern crate` item publicly accessible - -resolve_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope - .label = names from parent modules are not accessible without an explicit import - -resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it - .help = you can define integration tests in a directory named `tests` - -resolve_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough - .note = the most public imported item is `{$max_vis}` - .help = reduce the glob import's visibility or increase visibility of imported items - -resolve_reexport_of_crate_public = - re-export of crate public `{$ident}` - -resolve_reexport_of_private = - re-export of private `{$ident}` - -resolve_reexport_private_dependency = - {$kind} `{$name}` from private dependency '{$krate}' is re-exported - -resolve_relative_2018 = - relative paths are not supported in visibilities in 2018 edition or later - .suggestion = try - -resolve_remove_surrounding_derive = - remove from the surrounding `derive()` - -resolve_remove_unnecessary_import = remove unnecessary import - -resolve_self_import_can_only_appear_once_in_the_list = - `self` import can only appear once in an import list - .label = can only appear once in an import list - -resolve_self_import_only_in_import_list_with_non_empty_prefix = - `self` import can only appear in an import list with a non-empty prefix - .label = can only appear in an import list with a non-empty prefix - -resolve_self_imports_only_allowed_within = - `self` imports are only allowed within a {"{"} {"}"} list - -resolve_self_imports_only_allowed_within_multipart_suggestion = - alternatively, use the multi-path `use` syntax to import `self` - -resolve_self_imports_only_allowed_within_suggestion = - consider importing the module directly - -resolve_self_in_const_generic_ty = - cannot use `Self` in const parameter type - -resolve_self_in_generic_param_default = - generic parameters cannot use `Self` in their defaults - -resolve_similarly_named_defined_here = - similarly named {$candidate_descr} `{$candidate}` defined here - -resolve_single_item_defined_here = - {$candidate_descr} `{$candidate}` defined here - -resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}` - .label = 'static is a reserved lifetime name - -resolve_suggestion_import_ident_directly = - import `{$ident}` directly - -resolve_suggestion_import_ident_through_reexport = - import `{$ident}` through the re-export - -resolve_tool_module_imported = - cannot use a tool module through an import - .note = the tool module imported here - -resolve_tool_only_accepts_identifiers = - `{$tool}` only accepts identifiers - .label = not an identifier - -resolve_tool_was_already_registered = - tool `{$tool}` was already registered - .label = already registered here - -resolve_trait_impl_duplicate = - duplicate definitions with name `{$name}`: - .label = duplicate definition - .old_span_label = previous definition here - .trait_item_span = item in trait - -resolve_trait_impl_mismatch = - item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` - .label = does not match trait - .trait_impl_mismatch_label_item = item in trait -resolve_try_using_similarly_named_label = - try using similarly named label - -resolve_type_not_member_of_trait = - type `{$type_}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_type_param_in_enum_discriminant = - type parameters may not be used in enum discriminant values - -resolve_type_param_in_non_trivial_anon_const = - type parameters may not be used in const expressions - -resolve_undeclared_label = - use of undeclared label `{$name}` - .label = undeclared label `{$name}` - -resolve_underscore_lifetime_is_reserved = `'_` cannot be used here - .label = `'_` is a reserved lifetime name - .help = use another lifetime specifier - -resolve_unexpected_res_change_ty_to_const_param_sugg = - you might have meant to write a const parameter here - -resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = - if you meant to collect the rest of the slice in `{$ident}`, use the at operator - -resolve_unknown_diagnostic_attribute = unknown diagnostic attribute -resolve_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists - -resolve_unnamed_crate_root_import = - crate root imports need to be explicitly named: `use crate as name;` - -resolve_unreachable_label = - use of unreachable label `{$name}` - .label = unreachable label `{$name}` - .label_definition_span = unreachable label defined here - .note = labels are unreachable through functions, closures, async blocks and modules - -resolve_unreachable_label_similar_name_reachable = - a label with a similar name is reachable - -resolve_unreachable_label_similar_name_unreachable = - a label with a similar name exists but is also unreachable - -resolve_unreachable_label_suggestion_use_similarly_named = - try using similarly named label - -resolve_unreachable_label_with_similar_name_exists = - a label with a similar name exists but is unreachable - -resolve_unused_extern_crate = unused extern crate - .label = unused - .suggestion = remove the unused `extern crate` - -resolve_unused_label = unused label - -resolve_unused_macro_definition = unused macro definition: `{$name}` - -resolve_unused_macro_use = unused `#[macro_use]` import - -resolve_variable_bound_with_different_mode = - variable `{$variable_name}` is bound inconsistently across alternatives separated by `|` - .label = bound in different ways - .first_binding_span = first binding - -resolve_variable_is_a_typo = you might have meant to use the similarly named previously used binding `{$typo}` - -resolve_variable_is_not_bound_in_all_patterns = - variable `{$name}` is not bound in all patterns - -resolve_variable_not_in_all_patterns = variable not in all patterns diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e06ca59771e6..f0dffd8829da 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -60,7 +60,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Create a name definitinon from the given components, and put it into the local module. + /// Create a name definition from the given components, and put it into the local module. fn define_local( &mut self, parent: Module<'ra>, @@ -76,7 +76,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.plant_decl_into_local_module(ident, orig_ident.span, ns, decl); } - /// Create a name definitinon from the given components, and put it into the extern module. + /// Create a name definition from the given components, and put it into the extern module. fn define_extern( &self, parent: Module<'ra>, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5c401c3bf828..ac6188c2c152 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -24,15 +24,15 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_PANIC_IMPORTS, - MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, + ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES, + AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; use rustc_session::utils::was_invoked_from_cargo; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{SourceMap, Spanned}; -use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, SyntaxContext, kw, sym}; +use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::{debug, instrument}; @@ -41,6 +41,7 @@ use crate::errors::{ ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition, MaybeMissingMacroRulesName, }; +use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::{Import, ImportKind}; use crate::late::{DiagMetadata, PatternSource, Rib}; use crate::{ @@ -144,6 +145,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let lint = match ambiguity_warning { + _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES, AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS, AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS, }; @@ -1013,11 +1015,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span, name, param_kind: is_type, - help: self - .tcx - .sess - .is_nightly_build() - .then_some(errs::ParamInNonTrivialAnonConstHelp), + help: self.tcx.sess.is_nightly_build(), }) } ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self @@ -1163,11 +1161,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestions: &mut Vec, scope_set: ScopeSet<'ra>, ps: &ParentScope<'ra>, - ctxt: SyntaxContext, + sp: Span, filter_fn: &impl Fn(Res) -> bool, ) { - let ctxt = DUMMY_SP.with_ctxt(ctxt); - self.cm().visit_scopes(scope_set, ps, ctxt, None, |this, scope, use_prelude, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers(expn_id) => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); @@ -1269,8 +1267,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { filter_fn: &impl Fn(Res) -> bool, ) -> Option { let mut suggestions = Vec::new(); - let ctxt = ident.span.ctxt(); - self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn); + self.add_scope_set_candidates( + &mut suggestions, + scope_set, + parent_scope, + ident.span, + filter_fn, + ); // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); @@ -1422,14 +1425,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // a note about editions let note = if let Some(did) = did { let requires_note = !did.is_local() - && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any( - |attr| { - [sym::TryInto, sym::TryFrom, sym::FromIterator] - .map(|x| Some(x)) - .contains(&attr.value_str()) - }, + && find_attr!( + this.tcx.get_all_attrs(did), + AttributeKind::RustcDiagnosticItem( + sym::TryInto | sym::TryFrom | sym::FromIterator + ) ); - requires_note.then(|| { format!( "'{}' is included in the prelude starting in Edition 2021", @@ -1709,7 +1710,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, None, - false, None, None, ) else { @@ -1990,7 +1990,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity { - let AmbiguityError { kind, ident, b1, b2, scope1, scope2, .. } = *ambiguity_error; + let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } = + *ambiguity_error; let extern_prelude_ambiguity = || { // Note: b1 may come from a module scope, as an extern crate item in module. matches!(scope2, Scope::ExternPreludeFlags) @@ -2069,9 +2070,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None }; + let ambig_vis = ambig_vis.map(|(vis1, vis2)| { + format!( + "{} or {}", + vis1.to_string(CRATE_DEF_ID, self.tcx), + vis2.to_string(CRATE_DEF_ID, self.tcx) + ) + }); + errors::Ambiguity { ident, help, + ambig_vis, kind: kind.descr(), b1_note, b1_help_msgs, @@ -2546,7 +2556,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns_to_try), parent_scope, None, - false, ignore_decl, ignore_import, ) @@ -2650,7 +2659,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ValueNS), parent_scope, None, - false, ignore_decl, ignore_import, ) { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 205f2c6aa539..a9b2dabc8ebe 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,21 +1,31 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; +use crate::Res; use crate::late::PatternSource; -use crate::{Res, fluent_generated as fluent}; #[derive(Diagnostic)] -#[diag(resolve_generic_params_from_outer_item, code = E0401)] -#[note] +#[diag("can't use {$is_self -> + [true] `Self` + *[false] generic parameters + } from outer item", code = E0401)] +#[note( + "nested items are independent from their parent item for everything except for privacy and name resolution" +)] pub(crate) struct GenericParamsFromOuterItem { #[primary_span] - #[label] + #[label( + "use of {$is_self -> + [true] `Self` + *[false] generic parameter + } from outer item" + )] pub(crate) span: Span, #[subdiagnostic] pub(crate) label: Option, @@ -31,7 +41,12 @@ pub(crate) struct GenericParamsFromOuterItem { } #[derive(Subdiagnostic)] -#[label(resolve_generic_params_from_outer_item_inner_item)] +#[label( + "{$is_self -> + [true] `Self` + *[false] generic parameter + } used in this inner {$descr}" +)] pub(crate) struct GenericParamsFromOuterItemInnerItem { #[primary_span] pub(crate) span: Span, @@ -40,27 +55,27 @@ pub(crate) struct GenericParamsFromOuterItemInnerItem { #[derive(Subdiagnostic)] pub(crate) enum GenericParamsFromOuterItemStaticOrConst { - #[note(resolve_generic_params_from_outer_item_static)] + #[note("a `static` is a separate item from the item that contains it")] Static, - #[note(resolve_generic_params_from_outer_item_const)] + #[note("a `const` is a separate item from the item that contains it")] Const, } #[derive(Subdiagnostic)] pub(crate) enum GenericParamsFromOuterItemLabel { - #[label(resolve_generic_params_from_outer_item_self_ty_param)] + #[label("can't use `Self` here")] SelfTyParam(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_self_ty_alias)] + #[label("`Self` type implicitly declared here, by this `impl`")] SelfTyAlias(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_ty_param)] + #[label("type parameter from outer item")] TyParam(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_const_param)] + #[label("const parameter from outer item")] ConstParam(#[primary_span] Span), } #[derive(Subdiagnostic)] #[suggestion( - resolve_suggestion, + "try introducing a local generic parameter here", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -72,7 +87,7 @@ pub(crate) struct GenericParamsFromOuterItemSugg { } #[derive(Subdiagnostic)] #[suggestion( - resolve_refer_to_type_directly, + "refer to the type directly here instead", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -84,21 +99,21 @@ pub(crate) struct UseTypeDirectly { } #[derive(Diagnostic)] -#[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)] +#[diag("the name `{$name}` is already used for a generic parameter in this item's generic parameters", code = E0403)] pub(crate) struct NameAlreadyUsedInParameterList { #[primary_span] - #[label] + #[label("already used")] pub(crate) span: Span, - #[label(resolve_first_use_of_name)] + #[label("first use of `{$name}`")] pub(crate) first_use_span: Span, pub(crate) name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_method_not_member_of_trait, code = E0407)] +#[diag("method `{$method}` is not a member of trait `{$trait_}`", code = E0407)] pub(crate) struct MethodNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) method: Ident, pub(crate) trait_: String, @@ -108,7 +123,7 @@ pub(crate) struct MethodNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_fn_with_similar_name_exists, + "there is an associated function with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -119,10 +134,10 @@ pub(crate) struct AssociatedFnWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_type_not_member_of_trait, code = E0437)] +#[diag("type `{$type_}` is not a member of trait `{$trait_}`", code = E0437)] pub(crate) struct TypeNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) type_: Ident, pub(crate) trait_: String, @@ -132,7 +147,7 @@ pub(crate) struct TypeNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_type_with_similar_name_exists, + "there is an associated type with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -143,10 +158,10 @@ pub(crate) struct AssociatedTypeWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_const_not_member_of_trait, code = E0438)] +#[diag("const `{$const_}` is not a member of trait `{$trait_}`", code = E0438)] pub(crate) struct ConstNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) const_: Ident, pub(crate) trait_: String, @@ -156,7 +171,7 @@ pub(crate) struct ConstNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_const_with_similar_name_exists, + "there is an associated constant with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -167,39 +182,39 @@ pub(crate) struct AssociatedConstWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_variable_bound_with_different_mode, code = E0409)] +#[diag("variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`", code = E0409)] pub(crate) struct VariableBoundWithDifferentMode { #[primary_span] - #[label] + #[label("bound in different ways")] pub(crate) span: Span, - #[label(resolve_first_binding_span)] + #[label("first binding")] pub(crate) first_binding_span: Span, pub(crate) variable_name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = E0415)] +#[diag("identifier `{$identifier}` is bound more than once in this parameter list", code = E0415)] pub(crate) struct IdentifierBoundMoreThanOnceInParameterList { #[primary_span] - #[label] + #[label("used as parameter more than once")] pub(crate) span: Span, pub(crate) identifier: Ident, } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = E0416)] +#[diag("identifier `{$identifier}` is bound more than once in the same pattern", code = E0416)] pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern { #[primary_span] - #[label] + #[label("used in a pattern more than once")] pub(crate) span: Span, pub(crate) identifier: Ident, } #[derive(Diagnostic)] -#[diag(resolve_undeclared_label, code = E0426)] +#[diag("use of undeclared label `{$name}`", code = E0426)] pub(crate) struct UndeclaredLabel { #[primary_span] - #[label] + #[label("undeclared label `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] @@ -211,12 +226,12 @@ pub(crate) struct UndeclaredLabel { } #[derive(Subdiagnostic)] -#[label(resolve_label_with_similar_name_reachable)] +#[label("a label with a similar name is reachable")] pub(crate) struct LabelWithSimilarNameReachable(#[primary_span] pub(crate) Span); #[derive(Subdiagnostic)] #[suggestion( - resolve_try_using_similarly_named_label, + "try using similarly named label", code = "{ident_name}", applicability = "maybe-incorrect" )] @@ -227,38 +242,38 @@ pub(crate) struct TryUsingSimilarlyNamedLabel { } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_with_similar_name_exists)] +#[label("a label with a similar name exists but is unreachable")] pub(crate) struct UnreachableLabelWithSimilarNameExists { #[primary_span] pub(crate) ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)] +#[diag("`self` import can only appear once in an import list", code = E0430)] pub(crate) struct SelfImportCanOnlyAppearOnceInTheList { #[primary_span] - #[label] + #[label("can only appear once in an import list")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)] +#[diag("`self` import can only appear in an import list with a non-empty prefix", code = E0431)] pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix { #[primary_span] - #[label] + #[label("can only appear in an import list with a non-empty prefix")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)] -#[help] +#[diag("can't capture dynamic environment in a fn item", code = E0434)] +#[help("use the `|| {\"{\"} ... {\"}\"}` closure form instead")] pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = E0435)] +#[diag("attempt to use a non-constant value in a constant", code = E0435)] pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { #[primary_span] pub(crate) span: Span, @@ -272,7 +287,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion, + "consider using `{$suggestion}` instead of `{$current}`", style = "verbose", applicability = "has-placeholders" )] @@ -287,14 +302,14 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { } #[derive(Subdiagnostic)] -#[label(resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion)] +#[label("non-constant value")] pub(crate) struct AttemptToUseNonConstantValueInConstantLabelWithSuggestion { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion)] +#[label("this would need to be a `{$suggestion}`")] pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> { #[primary_span] pub(crate) ident_span: Span, @@ -302,7 +317,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> { } #[derive(Diagnostic)] -#[diag(resolve_self_imports_only_allowed_within, code = E0429)] +#[diag("`self` imports are only allowed within a {\"{\"} {\"}\"} list", code = E0429)] pub(crate) struct SelfImportsOnlyAllowedWithin { #[primary_span] pub(crate) span: Span, @@ -314,7 +329,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithin { #[derive(Subdiagnostic)] #[suggestion( - resolve_self_imports_only_allowed_within_suggestion, + "consider importing the module directly", code = "", applicability = "machine-applicable" )] @@ -325,7 +340,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_self_imports_only_allowed_within_multipart_suggestion, + "alternatively, use the multi-path `use` syntax to import `self`", applicability = "machine-applicable" )] pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion { @@ -336,17 +351,17 @@ pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)] +#[diag("{$shadowing_binding}s cannot shadow {$shadowed_binding}s", code = E0530)] pub(crate) struct BindingShadowsSomethingUnacceptable<'a> { #[primary_span] - #[label] + #[label("cannot be named the same as {$article} {$shadowed_binding}")] pub(crate) span: Span, pub(crate) shadowing_binding: PatternSource, pub(crate) shadowed_binding: Res, pub(crate) article: &'a str, #[subdiagnostic] pub(crate) sub_suggestion: Option, - #[label(resolve_label_shadowed_binding)] + #[label("the {$shadowed_binding} `{$name}` is {$participle} here")] pub(crate) shadowed_binding_span: Span, pub(crate) participle: &'a str, pub(crate) name: Symbol, @@ -354,7 +369,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptable<'a> { #[derive(Subdiagnostic)] #[suggestion( - resolve_binding_shadows_something_unacceptable_suggestion, + "try specify the pattern arguments", code = "{name}(..)", applicability = "unspecified" )] @@ -365,83 +380,79 @@ pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_forward_declared_generic_param, code = E0128)] +#[diag("generic parameter defaults cannot reference parameters before they are declared", code = E0128)] pub(crate) struct ForwardDeclaredGenericParam { #[primary_span] - #[label] + #[label("cannot reference `{$param}` before it is declared")] pub(crate) span: Span, pub(crate) param: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_forward_declared_generic_in_const_param_ty)] +#[diag("const parameter types cannot reference parameters before they are declared")] pub(crate) struct ForwardDeclaredGenericInConstParamTy { #[primary_span] - #[label] + #[label("const parameter type cannot reference `{$param}` before it is declared")] pub(crate) span: Span, pub(crate) param: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_param_in_ty_of_const_param, code = E0770)] +#[diag("the type of const parameters must not depend on other generic parameters", code = E0770)] pub(crate) struct ParamInTyOfConstParam { #[primary_span] - #[label] + #[label("the type must not depend on the parameter `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_self_in_generic_param_default, code = E0735)] +#[diag("generic parameters cannot use `Self` in their defaults", code = E0735)] pub(crate) struct SelfInGenericParamDefault { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_in_const_generic_ty)] +#[diag("cannot use `Self` in const parameter type")] pub(crate) struct SelfInConstGenericTy { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_param_in_non_trivial_anon_const)] +#[diag("generic parameters may not be used in const operations")] pub(crate) struct ParamInNonTrivialAnonConst { #[primary_span] - #[label] + #[label("cannot perform const operation using `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] pub(crate) param_kind: ParamKindInNonTrivialAnonConst, - #[subdiagnostic] - pub(crate) help: Option, + #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] + pub(crate) help: bool, } -#[derive(Subdiagnostic)] -#[help(resolve_param_in_non_trivial_anon_const_help)] -pub(crate) struct ParamInNonTrivialAnonConstHelp; - #[derive(Debug)] #[derive(Subdiagnostic)] pub(crate) enum ParamKindInNonTrivialAnonConst { - #[note(resolve_type_param_in_non_trivial_anon_const)] + #[note("type parameters may not be used in const expressions")] Type, - #[help(resolve_const_param_in_non_trivial_anon_const)] + #[help("const parameters may only be used as standalone arguments here, i.e. `{$name}`")] Const { name: Symbol }, - #[note(resolve_lifetime_param_in_non_trivial_anon_const)] + #[note("lifetime parameters may not be used in const expressions")] Lifetime, } #[derive(Diagnostic)] -#[diag(resolve_unreachable_label, code = E0767)] -#[note] +#[diag("use of unreachable label `{$name}`", code = E0767)] +#[note("labels are unreachable through functions, closures, async blocks and modules")] pub(crate) struct UnreachableLabel { #[primary_span] - #[label] + #[label("unreachable label `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, - #[label(resolve_label_definition_span)] + #[label("unreachable label defined here")] pub(crate) definition_span: Span, #[subdiagnostic] pub(crate) sub_suggestion: Option, @@ -453,7 +464,7 @@ pub(crate) struct UnreachableLabel { #[derive(Subdiagnostic)] #[suggestion( - resolve_unreachable_label_suggestion_use_similarly_named, + "try using similarly named label", code = "{ident_name}", applicability = "maybe-incorrect" )] @@ -464,104 +475,114 @@ pub(crate) struct UnreachableLabelSubSuggestion { } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_similar_name_reachable)] +#[label("a label with a similar name is reachable")] pub(crate) struct UnreachableLabelSubLabel { #[primary_span] pub(crate) ident_span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_similar_name_unreachable)] +#[label("a label with a similar name exists but is also unreachable")] pub(crate) struct UnreachableLabelSubLabelUnreachable { #[primary_span] pub(crate) ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_invalid_asm_sym)] -#[help] +#[diag("invalid `sym` operand")] +#[help("`sym` operands must refer to either a function or a static")] pub(crate) struct InvalidAsmSym { #[primary_span] - #[label] + #[label("is a local variable")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_lowercase_self)] +#[diag("attempt to use a non-constant value in a constant")] pub(crate) struct LowercaseSelf { #[primary_span] - #[suggestion(code = "Self", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "try using `Self`", + code = "Self", + applicability = "maybe-incorrect", + style = "short" + )] pub(crate) span: Span, } #[derive(Debug)] #[derive(Diagnostic)] -#[diag(resolve_binding_in_never_pattern)] +#[diag("never patterns cannot contain variable bindings")] pub(crate) struct BindingInNeverPattern { #[primary_span] - #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + #[suggestion( + "use a wildcard `_` instead", + code = "_", + applicability = "machine-applicable", + style = "short" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_duplicate, code = E0201)] +#[diag("duplicate definitions with name `{$name}`:", code = E0201)] pub(crate) struct TraitImplDuplicate { #[primary_span] - #[label] + #[label("duplicate definition")] pub(crate) span: Span, - #[label(resolve_old_span_label)] + #[label("previous definition here")] pub(crate) old_span: Span, - #[label(resolve_trait_item_span)] + #[label("item in trait")] pub(crate) trait_item_span: Span, pub(crate) name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_relative_2018)] +#[diag("relative paths are not supported in visibilities in 2018 edition or later")] pub(crate) struct Relative2018 { #[primary_span] pub(crate) span: Span, - #[suggestion(code = "crate::{path_str}", applicability = "maybe-incorrect")] + #[suggestion("try", code = "crate::{path_str}", applicability = "maybe-incorrect")] pub(crate) path_span: Span, pub(crate) path_str: String, } #[derive(Diagnostic)] -#[diag(resolve_ancestor_only, code = E0742)] +#[diag("visibilities can only be restricted to ancestor modules", code = E0742)] pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_expected_module_found, code = E0577)] +#[diag("expected module, found {$res} `{$path_str}`", code = E0577)] pub(crate) struct ExpectedModuleFound { #[primary_span] - #[label] + #[label("not a module")] pub(crate) span: Span, pub(crate) res: Res, pub(crate) path_str: String, } #[derive(Diagnostic)] -#[diag(resolve_indeterminate, code = E0578)] +#[diag("cannot determine resolution for the visibility", code = E0578)] pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_tool_module_imported)] +#[diag("cannot use a tool module through an import")] pub(crate) struct ToolModuleImported { #[primary_span] pub(crate) span: Span, - #[note] + #[note("the tool module imported here")] pub(crate) import: Span, } #[derive(Diagnostic)] -#[diag(resolve_module_only)] +#[diag("visibility must resolve to a module")] pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_macro_expected_found)] +#[diag("expected {$expected}, found {$found} `{$macro_path}`")] pub(crate) struct MacroExpectedFound<'a> { #[primary_span] - #[label] + #[label("not {$article} {$expected}")] pub(crate) span: Span, pub(crate) found: &'a str, pub(crate) article: &'static str, @@ -574,60 +595,66 @@ pub(crate) struct MacroExpectedFound<'a> { } #[derive(Subdiagnostic)] -#[help(resolve_remove_surrounding_derive)] +#[help("remove from the surrounding `derive()`")] pub(crate) struct RemoveSurroundingDerive { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[help(resolve_add_as_non_derive)] +#[help( + " + add as non-Derive macro + `#[{$macro_path}]`" +)] pub(crate) struct AddAsNonDerive<'a> { pub(crate) macro_path: &'a str, } #[derive(Diagnostic)] -#[diag(resolve_proc_macro_same_crate)] +#[diag("can't use a procedural macro from the same crate that defines it")] pub(crate) struct ProcMacroSameCrate { #[primary_span] pub(crate) span: Span, - #[help] + #[help("you can define integration tests in a directory named `tests`")] pub(crate) is_test: bool, } #[derive(LintDiagnostic)] -#[diag(resolve_proc_macro_derive_resolution_fallback)] +#[diag("cannot find {$ns_descr} `{$ident}` in this scope")] pub(crate) struct ProcMacroDeriveResolutionFallback { - #[label] + #[label("names from parent modules are not accessible without an explicit import")] pub span: Span, pub ns_descr: &'static str, pub ident: Symbol, } #[derive(LintDiagnostic)] -#[diag(resolve_macro_expanded_macro_exports_accessed_by_absolute_paths)] +#[diag( + "macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths" +)] pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths { - #[note] + #[note("the macro is defined here")] pub definition: Span, } #[derive(Diagnostic)] -#[diag(resolve_imported_crate)] +#[diag("`$crate` may not be imported")] pub(crate) struct CrateImported { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_use_extern_crate_self)] +#[diag("`#[macro_use]` is not supported on `extern crate self`")] pub(crate) struct MacroUseExternCrateSelf { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_accessible_unsure)] -#[note] +#[diag("not sure whether the path is accessible or not")] +#[note("the type may have associated items, but we are currently not checking them")] pub(crate) struct CfgAccessibleUnsure { #[primary_span] pub(crate) span: Span, @@ -635,10 +662,10 @@ pub(crate) struct CfgAccessibleUnsure { #[derive(Debug)] #[derive(Diagnostic)] -#[diag(resolve_param_in_enum_discriminant)] +#[diag("generic parameters may not be used in enum discriminant values")] pub(crate) struct ParamInEnumDiscriminant { #[primary_span] - #[label] + #[label("cannot perform const operation using `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] @@ -648,16 +675,16 @@ pub(crate) struct ParamInEnumDiscriminant { #[derive(Debug)] #[derive(Subdiagnostic)] pub(crate) enum ParamKindInEnumDiscriminant { - #[note(resolve_type_param_in_enum_discriminant)] + #[note("type parameters may not be used in enum discriminant values")] Type, - #[note(resolve_const_param_in_enum_discriminant)] + #[note("const parameters may not be used in enum discriminant values")] Const, - #[note(resolve_lifetime_param_in_enum_discriminant)] + #[note("lifetime parameters may not be used in enum discriminant values")] Lifetime, } #[derive(Subdiagnostic)] -#[label(resolve_change_import_binding)] +#[label("you can use `as` to change the binding name of the import")] pub(crate) struct ChangeImportBinding { #[primary_span] pub(crate) span: Span, @@ -665,7 +692,7 @@ pub(crate) struct ChangeImportBinding { #[derive(Subdiagnostic)] #[suggestion( - resolve_change_import_binding, + "you can use `as` to change the binding name of the import", code = "{suggestion}", applicability = "maybe-incorrect" )] @@ -676,7 +703,7 @@ pub(crate) struct ChangeImportBindingSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_imports_cannot_refer_to)] +#[diag("imports cannot refer to {$what}")] pub(crate) struct ImportsCannotReferTo<'a> { #[primary_span] pub(crate) span: Span, @@ -684,7 +711,7 @@ pub(crate) struct ImportsCannotReferTo<'a> { } #[derive(Diagnostic)] -#[diag(resolve_cannot_find_ident_in_this_scope)] +#[diag("cannot find {$expected} `{$ident}` in this scope")] pub(crate) struct CannotFindIdentInThisScope<'a> { #[primary_span] pub(crate) span: Span, @@ -693,7 +720,7 @@ pub(crate) struct CannotFindIdentInThisScope<'a> { } #[derive(Subdiagnostic)] -#[note(resolve_explicit_unsafe_traits)] +#[note("unsafe traits like `{$ident}` should be implemented explicitly")] pub(crate) struct ExplicitUnsafeTraits { #[primary_span] pub(crate) span: Span, @@ -701,14 +728,14 @@ pub(crate) struct ExplicitUnsafeTraits { } #[derive(Subdiagnostic)] -#[note(resolve_macro_defined_later)] +#[note("a macro with the same name exists, but it appears later")] pub(crate) struct MacroDefinedLater { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_consider_move_macro_position)] +#[label("consider moving the definition of `{$ident}` before this call")] pub(crate) struct MacroSuggMovePosition { #[primary_span] pub(crate) span: Span, @@ -717,19 +744,19 @@ pub(crate) struct MacroSuggMovePosition { #[derive(Subdiagnostic)] pub(crate) enum MacroRulesNot { - #[label(resolve_macro_cannot_use_as_fn_like)] + #[label("`{$ident}` exists, but has no rules for function-like invocation")] Func { #[primary_span] span: Span, ident: Ident, }, - #[label(resolve_macro_cannot_use_as_attr)] + #[label("`{$ident}` exists, but has no `attr` rules")] Attr { #[primary_span] span: Span, ident: Ident, }, - #[label(resolve_macro_cannot_use_as_derive)] + #[label("`{$ident}` exists, but has no `derive` rules")] Derive { #[primary_span] span: Span, @@ -738,22 +765,18 @@ pub(crate) enum MacroRulesNot { } #[derive(Subdiagnostic)] -#[note(resolve_missing_macro_rules_name)] +#[note("maybe you have forgotten to define a name for this `macro_rules!`")] pub(crate) struct MaybeMissingMacroRulesName { #[primary_span] pub(crate) spans: MultiSpan, } #[derive(Subdiagnostic)] -#[help(resolve_added_macro_use)] +#[help("have you added the `#[macro_use]` on the module/import?")] pub(crate) struct AddedMacroUse; #[derive(Subdiagnostic)] -#[suggestion( - resolve_consider_adding_a_derive, - code = "{suggestion}", - applicability = "maybe-incorrect" -)] +#[suggestion("consider adding a derive", code = "{suggestion}", applicability = "maybe-incorrect")] pub(crate) struct ConsiderAddingADerive { #[primary_span] pub(crate) span: Span, @@ -761,15 +784,15 @@ pub(crate) struct ConsiderAddingADerive { } #[derive(Diagnostic)] -#[diag(resolve_cannot_determine_import_resolution)] +#[diag("cannot determine resolution for the import")] pub(crate) struct CannotDetermineImportResolution { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_determine_macro_resolution)] -#[note] +#[diag("cannot determine resolution for the {$kind} `{$path}`")] +#[note("import resolution is stuck, try simplifying macro imports")] pub(crate) struct CannotDetermineMacroResolution { #[primary_span] pub(crate) span: Span, @@ -778,7 +801,7 @@ pub(crate) struct CannotDetermineMacroResolution { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = E0364)] +#[diag("`{$ident}` is private, and cannot be re-exported", code = E0364)] pub(crate) struct CannotBeReexportedPrivate { #[primary_span] pub(crate) span: Span, @@ -786,7 +809,7 @@ pub(crate) struct CannotBeReexportedPrivate { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = E0364)] +#[diag("`{$ident}` is only public within the crate, and cannot be re-exported outside", code = E0364)] pub(crate) struct CannotBeReexportedCratePublic { #[primary_span] pub(crate) span: Span, @@ -794,35 +817,40 @@ pub(crate) struct CannotBeReexportedCratePublic { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = E0365)] -#[note(resolve_consider_declaring_with_pub)] +#[diag("`{$ident}` is private, and cannot be re-exported", code = E0365)] +#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedPrivateNS { #[primary_span] - #[label(resolve_reexport_of_private)] + #[label("re-export of private `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = E0365)] -#[note(resolve_consider_declaring_with_pub)] +#[diag("`{$ident}` is only public within the crate, and cannot be re-exported outside", code = E0365)] +#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedCratePublicNS { #[primary_span] - #[label(resolve_reexport_of_crate_public)] + #[label("re-export of crate public `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, } #[derive(LintDiagnostic)] -#[diag(resolve_private_extern_crate_reexport, code = E0365)] +#[diag("extern crate `{$ident}` is private and cannot be re-exported", code = E0365)] pub(crate) struct PrivateExternCrateReexport { pub ident: Ident, - #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] + #[suggestion( + "consider making the `extern crate` item publicly accessible", + code = "pub ", + style = "verbose", + applicability = "maybe-incorrect" + )] pub sugg: Span, } #[derive(Subdiagnostic)] -#[help(resolve_consider_adding_macro_export)] +#[help("consider adding a `#[macro_export]` to the macro in the imported module")] pub(crate) struct ConsiderAddingMacroExport { #[primary_span] pub(crate) span: Span, @@ -830,7 +858,7 @@ pub(crate) struct ConsiderAddingMacroExport { #[derive(Subdiagnostic)] #[suggestion( - resolve_consider_marking_as_pub_crate, + "in case you want to use the macro within this crate only, reduce the visibility to `pub(crate)`", code = "pub(crate)", applicability = "maybe-incorrect" )] @@ -840,7 +868,7 @@ pub(crate) struct ConsiderMarkingAsPubCrate { } #[derive(Subdiagnostic)] -#[note(resolve_consider_marking_as_pub)] +#[note("consider marking `{$ident}` as `pub` in the imported module")] pub(crate) struct ConsiderMarkingAsPub { #[primary_span] pub(crate) span: Span, @@ -848,7 +876,7 @@ pub(crate) struct ConsiderMarkingAsPub { } #[derive(Diagnostic)] -#[diag(resolve_cannot_glob_import_possible_crates)] +#[diag("cannot glob-import all possible crates")] pub(crate) struct CannotGlobImportAllCrates { #[primary_span] pub(crate) span: Span, @@ -856,7 +884,7 @@ pub(crate) struct CannotGlobImportAllCrates { #[derive(Subdiagnostic)] #[suggestion( - resolve_unexpected_res_change_ty_to_const_param_sugg, + "you might have meant to write a const parameter here", code = "const ", style = "verbose" )] @@ -869,7 +897,7 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_unexpected_res_change_ty_to_const_param_sugg, + "you might have meant to write a const parameter here", applicability = "has-placeholders", style = "verbose" )] @@ -882,7 +910,7 @@ pub(crate) struct UnexpectedResChangeTyParamToConstParamSugg { #[derive(Subdiagnostic)] #[suggestion( - resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, + "if you meant to collect the rest of the slice in `{$ident}`, use the at operator", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -895,23 +923,27 @@ pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { } #[derive(Diagnostic)] -#[diag(resolve_extern_crate_loading_macro_not_at_crate_root, code = E0468)] +#[diag("an `extern crate` loading macros must be at the crate root", code = E0468)] pub(crate) struct ExternCrateLoadingMacroNotAtCrateRoot { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_extern_crate_self_requires_renaming)] +#[diag("`extern crate self;` requires renaming")] pub(crate) struct ExternCrateSelfRequiresRenaming { #[primary_span] - #[suggestion(code = "extern crate self as name;", applicability = "has-placeholders")] + #[suggestion( + "rename the `self` crate to be able to import it", + code = "extern crate self as name;", + applicability = "has-placeholders" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_use_name_already_in_use)] -#[note] +#[diag("`{$name}` is already in scope")] +#[note("macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)")] pub(crate) struct MacroUseNameAlreadyInUse { #[primary_span] pub(crate) span: Span, @@ -919,74 +951,80 @@ pub(crate) struct MacroUseNameAlreadyInUse { } #[derive(Diagnostic)] -#[diag(resolve_imported_macro_not_found, code = E0469)] +#[diag("imported macro not found", code = E0469)] pub(crate) struct ImportedMacroNotFound { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_extern_deprecated)] +#[diag("`#[macro_escape]` is a deprecated synonym for `#[macro_use]`")] pub(crate) struct MacroExternDeprecated { #[primary_span] pub(crate) span: Span, - #[help] + #[help("try an outer attribute: `#[macro_use]`")] pub inner_attribute: bool, } #[derive(Diagnostic)] -#[diag(resolve_arguments_macro_use_not_allowed)] +#[diag("arguments to `macro_use` are not allowed here")] pub(crate) struct ArgumentsMacroUseNotAllowed { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_unnamed_crate_root_import)] +#[diag("crate root imports need to be explicitly named: `use crate as name;`")] pub(crate) struct UnnamedCrateRootImport { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)] +#[diag("macro-expanded `extern crate` items cannot shadow names passed with `--extern`")] pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_elided_anonymous_lifetime_report_error, code = E0637)] +#[diag("`&` without an explicit lifetime name cannot be used here", code = E0637)] pub(crate) struct ElidedAnonymousLifetimeReportError { #[primary_span] - #[label] + #[label("explicit lifetime name needed here")] pub(crate) span: Span, #[subdiagnostic] pub(crate) suggestion: Option, } #[derive(Diagnostic)] -#[diag(resolve_lending_iterator_report_error)] +#[diag( + "associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type" +)] pub(crate) struct LendingIteratorReportError { #[primary_span] pub(crate) lifetime: Span, - #[note] + #[note( + "you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type" + )] pub(crate) ty: Span, } #[derive(Diagnostic)] -#[diag(resolve_anonymous_lifetime_non_gat_report_error)] +#[diag("missing lifetime in associated type")] pub(crate) struct AnonymousLifetimeNonGatReportError { #[primary_span] - #[label] + #[label("this lifetime must come from the implemented type")] pub(crate) lifetime: Span, - #[note] + #[note( + "in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type" + )] pub(crate) decl: MultiSpan, } #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_elided_anonymous_lifetime_report_error_suggestion, + "consider introducing a higher-ranked lifetime here", applicability = "machine-applicable" )] pub(crate) struct ElidedAnonymousLifetimeReportErrorSuggestion { @@ -997,15 +1035,15 @@ pub(crate) struct ElidedAnonymousLifetimeReportErrorSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_explicit_anonymous_lifetime_report_error, code = E0637)] +#[diag("`'_` cannot be used here", code = E0637)] pub(crate) struct ExplicitAnonymousLifetimeReportError { #[primary_span] - #[label] + #[label("`'_` is a reserved lifetime name")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_implicit_elided_lifetimes_not_allowed_here, code = E0726)] +#[diag("implicit elided lifetime not allowed here", code = E0726)] pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { #[primary_span] pub(crate) span: Span, @@ -1014,25 +1052,25 @@ pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { } #[derive(Diagnostic)] -#[diag(resolve_underscore_lifetime_is_reserved, code = E0637)] -#[help] +#[diag("`'_` cannot be used here", code = E0637)] +#[help("use another lifetime specifier")] pub(crate) struct UnderscoreLifetimeIsReserved { #[primary_span] - #[label] + #[label("`'_` is a reserved lifetime name")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_static_lifetime_is_reserved, code = E0262)] +#[diag("invalid lifetime parameter name: `{$lifetime}`", code = E0262)] pub(crate) struct StaticLifetimeIsReserved { #[primary_span] - #[label] + #[label("'static is a reserved lifetime name")] pub(crate) span: Span, pub(crate) lifetime: Ident, } #[derive(Diagnostic)] -#[diag(resolve_variable_is_not_bound_in_all_patterns, code = E0408)] +#[diag("variable `{$name}` is not bound in all patterns", code = E0408)] pub(crate) struct VariableIsNotBoundInAllPatterns { #[primary_span] pub(crate) multispan: MultiSpan, @@ -1040,7 +1078,7 @@ pub(crate) struct VariableIsNotBoundInAllPatterns { } #[derive(Subdiagnostic, Debug, Clone)] -#[label(resolve_pattern_doesnt_bind_name)] +#[label("pattern doesn't bind `{$name}`")] pub(crate) struct PatternDoesntBindName { #[primary_span] pub(crate) span: Span, @@ -1048,7 +1086,7 @@ pub(crate) struct PatternDoesntBindName { } #[derive(Subdiagnostic, Debug, Clone)] -#[label(resolve_variable_not_in_all_patterns)] +#[label("variable not in all patterns")] pub(crate) struct VariableNotInAllPatterns { #[primary_span] pub(crate) span: Span, @@ -1056,7 +1094,7 @@ pub(crate) struct VariableNotInAllPatterns { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_variable_is_a_typo, + "you might have meant to use the similarly named previously used binding `{$typo}`", applicability = "maybe-incorrect", style = "verbose" )] @@ -1067,8 +1105,8 @@ pub(crate) struct PatternBindingTypo { } #[derive(Diagnostic)] -#[diag(resolve_name_defined_multiple_time)] -#[note] +#[diag("the name `{$name}` is defined multiple times")] +#[note("`{$name}` must be defined only once in the {$descr} namespace of this {$container}")] pub(crate) struct NameDefinedMultipleTime { #[primary_span] pub(crate) span: Span, @@ -1083,12 +1121,12 @@ pub(crate) struct NameDefinedMultipleTime { #[derive(Subdiagnostic)] pub(crate) enum NameDefinedMultipleTimeLabel { - #[label(resolve_name_defined_multiple_time_reimported)] + #[label("`{$name}` reimported here")] Reimported { #[primary_span] span: Span, }, - #[label(resolve_name_defined_multiple_time_redefined)] + #[label("`{$name}` redefined here")] Redefined { #[primary_span] span: Span, @@ -1097,13 +1135,13 @@ pub(crate) enum NameDefinedMultipleTimeLabel { #[derive(Subdiagnostic)] pub(crate) enum NameDefinedMultipleTimeOldBindingLabel { - #[label(resolve_name_defined_multiple_time_old_binding_import)] + #[label("previous import of the {$old_kind} `{$name}` here")] Import { #[primary_span] span: Span, old_kind: &'static str, }, - #[label(resolve_name_defined_multiple_time_old_binding_definition)] + #[label("previous definition of the {$old_kind} `{$name}` here")] Definition { #[primary_span] span: Span, @@ -1112,42 +1150,42 @@ pub(crate) enum NameDefinedMultipleTimeOldBindingLabel { } #[derive(Diagnostic)] -#[diag(resolve_is_private, code = E0603)] +#[diag("{$ident_descr} `{$ident}` is private", code = E0603)] pub(crate) struct IsPrivate<'a> { #[primary_span] - #[label] + #[label("private {$ident_descr}")] pub(crate) span: Span, pub(crate) ident_descr: &'a str, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(resolve_generic_arguments_in_macro_path)] +#[diag("generic arguments in macro path")] pub(crate) struct GenericArgumentsInMacroPath { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_attributes_starting_with_rustc_are_reserved)] +#[diag("attributes starting with `rustc` are reserved for use by the `rustc` compiler")] pub(crate) struct AttributesStartingWithRustcAreReserved { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_use_through_an_import)] +#[diag("cannot use {$article} {$descr} through an import")] pub(crate) struct CannotUseThroughAnImport { #[primary_span] pub(crate) span: Span, pub(crate) article: &'static str, pub(crate) descr: &'static str, - #[note] + #[note("the {$descr} imported here")] pub(crate) binding_span: Option, } #[derive(Diagnostic)] -#[diag(resolve_name_reserved_in_attribute_namespace)] +#[diag("name `{$ident}` is reserved in attribute namespace")] pub(crate) struct NameReservedInAttributeNamespace { #[primary_span] pub(crate) span: Span, @@ -1155,7 +1193,7 @@ pub(crate) struct NameReservedInAttributeNamespace { } #[derive(Diagnostic)] -#[diag(resolve_cannot_find_builtin_macro_with_name)] +#[diag("cannot find a built-in macro with name `{$ident}`")] pub(crate) struct CannotFindBuiltinMacroWithName { #[primary_span] pub(crate) span: Span, @@ -1163,34 +1201,34 @@ pub(crate) struct CannotFindBuiltinMacroWithName { } #[derive(Diagnostic)] -#[diag(resolve_tool_was_already_registered)] +#[diag("tool `{$tool}` was already registered")] pub(crate) struct ToolWasAlreadyRegistered { #[primary_span] pub(crate) span: Span, pub(crate) tool: Ident, - #[label] + #[label("already registered here")] pub(crate) old_ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_tool_only_accepts_identifiers)] +#[diag("`{$tool}` only accepts identifiers")] pub(crate) struct ToolOnlyAcceptsIdentifiers { #[primary_span] - #[label] + #[label("not an identifier")] pub(crate) span: Span, pub(crate) tool: Symbol, } #[derive(Subdiagnostic)] pub(crate) enum DefinedHere { - #[label(resolve_similarly_named_defined_here)] + #[label("similarly named {$candidate_descr} `{$candidate}` defined here")] SimilarlyNamed { #[primary_span] span: Span, candidate_descr: &'static str, candidate: Symbol, }, - #[label(resolve_single_item_defined_here)] + #[label("{$candidate_descr} `{$candidate}` defined here")] SingleItem { #[primary_span] span: Span, @@ -1200,7 +1238,7 @@ pub(crate) enum DefinedHere { } #[derive(Subdiagnostic)] -#[label(resolve_outer_ident_is_not_publicly_reexported)] +#[label("{$outer_ident_descr} `{$outer_ident}` is not publicly re-exported")] pub(crate) struct OuterIdentIsNotPubliclyReexported { #[primary_span] pub(crate) span: Span, @@ -1209,7 +1247,7 @@ pub(crate) struct OuterIdentIsNotPubliclyReexported { } #[derive(Subdiagnostic)] -#[label(resolve_constructor_private_if_any_field_private)] +#[label("a constructor is private if any of the fields is private")] pub(crate) struct ConstructorPrivateIfAnyFieldPrivate { #[primary_span] pub(crate) span: Span, @@ -1217,7 +1255,10 @@ pub(crate) struct ConstructorPrivateIfAnyFieldPrivate { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_consider_making_the_field_public, + "{ $number_of_fields -> + [one] consider making the field publicly accessible + *[other] consider making the fields publicly accessible + }", applicability = "maybe-incorrect", style = "verbose" )] @@ -1230,7 +1271,7 @@ pub(crate) struct ConsiderMakingTheFieldPublic { #[derive(Subdiagnostic)] pub(crate) enum ImportIdent { #[suggestion( - resolve_suggestion_import_ident_through_reexport, + "import `{$ident}` through the re-export", code = "{path}", applicability = "machine-applicable", style = "verbose" @@ -1242,7 +1283,7 @@ pub(crate) enum ImportIdent { path: String, }, #[suggestion( - resolve_suggestion_import_ident_directly, + "import `{$ident}` directly", code = "{path}", applicability = "machine-applicable", style = "verbose" @@ -1256,7 +1297,18 @@ pub(crate) enum ImportIdent { } #[derive(Subdiagnostic)] -#[note(resolve_note_and_refers_to_the_item_defined_here)] +#[note( + "{$first -> + [true] {$dots -> + [true] the {$binding_descr} `{$binding_name}` is defined here... + *[false] the {$binding_descr} `{$binding_name}` is defined here + } + *[false] {$dots -> + [true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here... + *[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here + } + }" +)] pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> { #[primary_span] pub(crate) span: MultiSpan, @@ -1267,7 +1319,7 @@ pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> { } #[derive(Subdiagnostic)] -#[suggestion(resolve_remove_unnecessary_import, code = "", applicability = "maybe-incorrect")] +#[suggestion("remove unnecessary import", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveUnnecessaryImport { #[primary_span] pub(crate) span: Span, @@ -1275,7 +1327,7 @@ pub(crate) struct RemoveUnnecessaryImport { #[derive(Subdiagnostic)] #[suggestion( - resolve_remove_unnecessary_import, + "remove unnecessary import", code = "", applicability = "maybe-incorrect", style = "tool-only" @@ -1286,7 +1338,7 @@ pub(crate) struct ToolOnlyRemoveUnnecessaryImport { } #[derive(Subdiagnostic)] -#[note(resolve_ident_imported_here_but_it_is_desc)] +#[note("`{$imported_ident}` is imported here, but it is {$imported_ident_desc}")] pub(crate) struct IdentImporterHereButItIsDesc<'a> { #[primary_span] pub(crate) span: Span, @@ -1295,7 +1347,7 @@ pub(crate) struct IdentImporterHereButItIsDesc<'a> { } #[derive(Subdiagnostic)] -#[note(resolve_ident_in_scope_but_it_is_desc)] +#[note("`{$imported_ident}` is in scope, but it is {$imported_ident_desc}")] pub(crate) struct IdentInScopeButItIsDesc<'a> { pub(crate) imported_ident: Ident, pub(crate) imported_ident_desc: &'a str, @@ -1319,50 +1371,55 @@ impl Subdiagnostic for FoundItemConfigureOut { let key = "feature".into(); let value = feature.into_diag_arg(&mut None); let msg = diag.dcx.eagerly_translate_to_string( - fluent::resolve_item_was_behind_feature, + msg!("the item is gated behind the `{$feature}` feature"), [(&key, &value)].into_iter(), ); multispan.push_span_label(span, msg); } ItemWas::CfgOut { span } => { - multispan.push_span_label(span, fluent::resolve_item_was_cfg_out); + multispan.push_span_label(span, msg!("the item is gated here")); } } - diag.span_note(multispan, fluent::resolve_found_an_item_configured_out); + diag.span_note(multispan, msg!("found an item that was configured out")); } } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_mismatch)] +#[diag("item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`")] pub(crate) struct TraitImplMismatch { #[primary_span] - #[label] + #[label("does not match trait")] pub(crate) span: Span, pub(crate) name: Ident, pub(crate) kind: &'static str, pub(crate) trait_path: String, - #[label(resolve_trait_impl_mismatch_label_item)] + #[label("item in trait")] pub(crate) trait_item_span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_legacy_derive_helpers)] +#[diag("derive helper attribute is used before it is introduced")] pub(crate) struct LegacyDeriveHelpers { - #[label] + #[label("the attribute is introduced here")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_unused_extern_crate)] +#[diag("unused extern crate")] pub(crate) struct UnusedExternCrate { - #[label] + #[label("unused")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the unused `extern crate`", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub removal_span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_reexport_private_dependency)] +#[diag("{$kind} `{$name}` from private dependency '{$krate}' is re-exported")] pub(crate) struct ReexportPrivateDependency { pub name: Symbol, pub kind: &'static str, @@ -1370,32 +1427,32 @@ pub(crate) struct ReexportPrivateDependency { } #[derive(LintDiagnostic)] -#[diag(resolve_unused_label)] +#[diag("unused label")] pub(crate) struct UnusedLabel; #[derive(LintDiagnostic)] -#[diag(resolve_unused_macro_use)] +#[diag("unused `#[macro_use]` import")] pub(crate) struct UnusedMacroUse; #[derive(LintDiagnostic)] -#[diag(resolve_macro_use_deprecated)] -#[help] +#[diag("applying the `#[macro_use]` attribute to an `extern crate` item is deprecated")] +#[help("remove it and import macros at use sites with a `use` item instead")] pub(crate) struct MacroUseDeprecated; #[derive(LintDiagnostic)] -#[diag(resolve_macro_is_private)] +#[diag("macro `{$ident}` is private")] pub(crate) struct MacroIsPrivate { pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(resolve_unused_macro_definition)] +#[diag("unused macro definition: `{$name}`")] pub(crate) struct UnusedMacroDefinition { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(resolve_macro_rule_never_used)] +#[diag("rule #{$n} of macro `{$name}` is never used")] pub(crate) struct MacroRuleNeverUsed { pub n: usize, pub name: Symbol, @@ -1412,36 +1469,43 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { } #[derive(LintDiagnostic)] -#[diag(resolve_extern_crate_not_idiomatic)] +#[diag("`extern crate` is not idiomatic in the new edition")] pub(crate) struct ExternCrateNotIdiomatic { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + #[suggestion( + "convert it to a `use`", + style = "verbose", + code = "{code}", + applicability = "machine-applicable" + )] pub span: Span, pub code: &'static str, } #[derive(LintDiagnostic)] -#[diag(resolve_out_of_scope_macro_calls)] -#[help] +#[diag("cannot find macro `{$path}` in the current scope when looking from {$location}")] +#[help("import `macro_rules` with `use` to make it callable above its definition")] pub(crate) struct OutOfScopeMacroCalls { - #[label] + #[label("not found from {$location}")] pub span: Span, pub path: String, pub location: String, } #[derive(LintDiagnostic)] -#[diag(resolve_redundant_import_visibility)] +#[diag( + "glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough" +)] pub(crate) struct RedundantImportVisibility { - #[note] + #[note("the most public imported item is `{$max_vis}`")] pub span: Span, - #[help] + #[help("reduce the glob import's visibility or increase visibility of imported items")] pub help: (), pub import_vis: String, pub max_vis: String, } #[derive(LintDiagnostic)] -#[diag(resolve_unknown_diagnostic_attribute)] +#[diag("unknown diagnostic attribute")] pub(crate) struct UnknownDiagnosticAttribute { #[subdiagnostic] pub typo: Option, @@ -1449,7 +1513,7 @@ pub(crate) struct UnknownDiagnosticAttribute { #[derive(Subdiagnostic)] #[suggestion( - resolve_unknown_diagnostic_attribute_typo_sugg, + "an attribute with a similar name exists", style = "verbose", code = "{typo_name}", applicability = "machine-applicable" @@ -1463,6 +1527,7 @@ pub(crate) struct UnknownDiagnosticAttributeTypoSugg { // FIXME: Make this properly translatable. pub(crate) struct Ambiguity { pub ident: Ident, + pub ambig_vis: Option, pub kind: &'static str, pub help: Option<&'static [&'static str]>, pub b1_note: Spanned, @@ -1473,8 +1538,12 @@ pub(crate) struct Ambiguity { impl Ambiguity { fn decorate<'a>(self, diag: &mut Diag<'a, impl EmissionGuarantee>) { - diag.primary_message(format!("`{}` is ambiguous", self.ident)); - diag.span_label(self.ident.span, "ambiguous name"); + if let Some(ambig_vis) = self.ambig_vis { + diag.primary_message(format!("ambiguous import visibility: {ambig_vis}")); + } else { + diag.primary_message(format!("`{}` is ambiguous", self.ident)); + diag.span_label(self.ident.span, "ambiguous name"); + } diag.note(format!("ambiguous because of {}", self.kind)); diag.span_note(self.b1_note.span, self.b1_note.node); if let Some(help) = self.help { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 26dca5e6e508..d4d373d82064 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -5,6 +5,7 @@ use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_middle::ty::Visibility; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; use rustc_session::parse::feature_err; @@ -54,9 +55,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut self: CmResolver<'r, 'ra, 'tcx>, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, - // Location of the span is not significant, but pass a `Span` instead of `SyntaxContext` - // to avoid extracting and re-packaging the syntax context unnecessarily. - orig_ctxt: Span, + mut ctxt: Macros20NormalizedSyntaxContext, + orig_ident_span: Span, derive_fallback_lint_id: Option, mut visitor: impl FnMut( CmResolver<'_, 'ra, 'tcx>, @@ -128,7 +128,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; - let mut ctxt = Macros20NormalizedSyntaxContext::new(orig_ctxt.ctxt()); let mut use_prelude = !module.no_implicit_prelude; loop { @@ -153,7 +152,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { true } Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true, - Scope::MacroUsePrelude => use_prelude || orig_ctxt.edition().is_rust_2015(), + Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(), Scope::BuiltinAttrs => true, Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { use_prelude || module_and_extern_prelude || extern_prelude @@ -350,7 +349,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Module(ns, module), parent_scope, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), - finalize.is_some(), ignore_decl, None, ) @@ -368,7 +366,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, None, ) @@ -396,14 +393,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, finalize: Option, - force: bool, ignore_decl: Option>, ignore_import: Option>, ) -> Result, Determinacy> { - assert!(force || finalize.is_none()); // `finalize` implies `force` + self.resolve_ident_in_scope_set_inner( + IdentKey::new(orig_ident), + orig_ident.span, + scope_set, + parent_scope, + finalize, + ignore_decl, + ignore_import, + ) + } + fn resolve_ident_in_scope_set_inner<'r>( + self: CmResolver<'r, 'ra, 'tcx>, + ident: IdentKey, + orig_ident_span: Span, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, + finalize: Option, + ignore_decl: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { // Make sure `self`, `super` etc produce an error when passed to here. - if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() { + if !matches!(scope_set, ScopeSet::Module(..)) && ident.name.is_path_segment_keyword() { return Err(Determinacy::Determined); } @@ -437,13 +452,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let break_result = self.visit_scopes( scope_set, parent_scope, - orig_ident.span, + ident.ctxt, + orig_ident_span, derive_fallback_lint_id, |mut this, scope, use_prelude, ctxt| { - let ident = IdentKey { name: orig_ident.name, ctxt }; + let ident = IdentKey { name: ident.name, ctxt }; let res = match this.reborrow().resolve_ident_in_scope( ident, - orig_ident.span, + orig_ident_span, ns, scope, use_prelude, @@ -451,7 +467,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope, // Shadowed decls don't need to be marked as used or non-speculatively loaded. if innermost_results.is_empty() { finalize } else { None }, - force, ignore_decl, ignore_import, ) { @@ -471,20 +486,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We do not need to report them if we are either in speculative resolution, // or in late resolution when everything is already imported and expanded // and no ambiguities exist. - if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) { - return ControlFlow::Break(Ok(decl)); - } + let import_vis = match finalize { + None | Some(Finalize { stage: Stage::Late, .. }) => { + return ControlFlow::Break(Ok(decl)); + } + Some(Finalize { import_vis, .. }) => import_vis, + }; if let Some(&(innermost_decl, _)) = innermost_results.first() { // Found another solution, if the first one was "weak", report an error. if this.get_mut().maybe_push_ambiguity( - orig_ident, + ident, + orig_ident_span, ns, scope_set, parent_scope, decl, scope, &innermost_results, + import_vis, ) { // No need to search for more potential ambiguities, one is enough. return ControlFlow::Break(Ok(innermost_decl)); @@ -509,7 +529,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Scope visiting walked all the scopes and maybe found something in one of them. match innermost_results.first() { Some(&(decl, ..)) => Ok(decl), - None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)), + None => Err(determinacy), } } @@ -523,7 +543,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, finalize: Option, - force: bool, ignore_decl: Option>, ignore_import: Option>, ) -> Result, ControlFlow> { @@ -546,7 +565,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match self.reborrow().resolve_derive_macro_path( derive, parent_scope, - force, + false, ignore_import, ) { Ok((Some(ext), _)) => { @@ -617,11 +636,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(decl) } Err(ControlFlow::Continue(determinacy)) => Err(determinacy), - Err(ControlFlow::Break(determinacy)) => { - return Err(ControlFlow::Break(Determinacy::determined( - determinacy == Determinacy::Determined || force, - ))); - } + Err(ControlFlow::Break(..)) => return decl, } } Scope::ModuleGlobs(module, derive_fallback_lint_id) => { @@ -668,11 +683,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(binding) } Err(ControlFlow::Continue(determinacy)) => Err(determinacy), - Err(ControlFlow::Break(determinacy)) => { - return Err(ControlFlow::Break(Determinacy::determined( - determinacy == Determinacy::Determined || force, - ))); - } + Err(ControlFlow::Break(..)) => return binding, } } Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() { @@ -710,12 +721,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); if let Some(prelude) = self.prelude - && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(*ident.ctxt)), + && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set_inner( + ident, + orig_ident_span, ScopeSet::Module(ns, prelude), parent_scope, None, - false, ignore_decl, ignore_import, ) @@ -765,19 +776,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn maybe_push_ambiguity( &mut self, - orig_ident: Ident, + ident: IdentKey, + orig_ident_span: Span, ns: Namespace, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, decl: Decl<'ra>, scope: Scope<'ra>, innermost_results: &[(Decl<'ra>, Scope<'ra>)], + import_vis: Option, ) -> bool { let (innermost_decl, innermost_scope) = innermost_results[0]; let (res, innermost_res) = (decl.res(), innermost_decl.res()); - if res == innermost_res { + let ambig_vis = if res != innermost_res { + None + } else if let Some(import_vis) = import_vis + && let min = + (|d: Decl<'_>| d.vis().min(import_vis.to_def_id(), self.tcx).expect_local()) + && let (min1, min2) = (min(decl), min(innermost_decl)) + && min1 != min2 + { + Some((min1, min2)) + } else { return false; - } + }; // FIXME: Use `scope` instead of `res` to detect built-in attrs and derive helpers, // it will exclude imports, make slightly more code legal, and will require lang approval. @@ -791,7 +813,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if innermost_res == derive_helper_compat { Some(AmbiguityKind::DeriveHelper) } else if res == derive_helper_compat && innermost_res != derive_helper { - span_bug!(orig_ident.span, "impossible inner resolution kind") + span_bug!(orig_ident_span, "impossible inner resolution kind") } else if matches!(innermost_scope, Scope::MacroRules(_)) && matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..)) && !self.disambiguate_macro_rules_vs_modularized(innermost_decl, decl) @@ -806,7 +828,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // we visit all macro_rules scopes (e.g. textual scope macros) // before we visit any modules (e.g. path-based scope macros) span_bug!( - orig_ident.span, + orig_ident_span, "ambiguous scoped macro resolutions with path-based \ scope resolution as first candidate" ) @@ -855,8 +877,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { // Turn ambiguity errors for core vs std panic into warnings. // FIXME: Remove with lang team approval. - let is_issue_147319_hack = orig_ident.span.edition() <= Edition::Edition2024 - && matches!(orig_ident.name, sym::panic) + let is_issue_147319_hack = orig_ident_span.edition() <= Edition::Edition2024 + && matches!(ident.name, sym::panic) && matches!(scope, Scope::StdLibPrelude) && matches!(innermost_scope, Scope::ModuleGlobs(_, _)) && ((self.is_specific_builtin_macro(res, sym::std_panic) @@ -864,11 +886,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { || (self.is_specific_builtin_macro(res, sym::core_panic) && self.is_specific_builtin_macro(innermost_res, sym::std_panic))); - let warning = is_issue_147319_hack.then_some(AmbiguityWarning::PanicImport); + let warning = if ambig_vis.is_some() { + Some(AmbiguityWarning::GlobImport) + } else if is_issue_147319_hack { + Some(AmbiguityWarning::PanicImport) + } else { + None + }; self.ambiguity_errors.push(AmbiguityError { kind, - ident: orig_ident, + ambig_vis, + ident: ident.orig(orig_ident_span), b1: innermost_decl, b2: decl, scope1: innermost_scope, @@ -896,46 +925,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn resolve_ident_in_module<'r>( - self: CmResolver<'r, 'ra, 'tcx>, - module: ModuleOrUniformRoot<'ra>, - mut ident: Ident, - ns: Namespace, - parent_scope: &ParentScope<'ra>, - finalize: Option, - ignore_decl: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { - let tmp_parent_scope; - let mut adjusted_parent_scope = parent_scope; - match module { - ModuleOrUniformRoot::Module(m) => { - if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { - tmp_parent_scope = - ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; - adjusted_parent_scope = &tmp_parent_scope; - } - } - ModuleOrUniformRoot::ExternPrelude => { - ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); - } - ModuleOrUniformRoot::ModuleAndExternPrelude(..) | ModuleOrUniformRoot::CurrentScope => { - // No adjustments - } - } - self.resolve_ident_in_virt_module_unadjusted( - module, - ident, - ns, - adjusted_parent_scope, - finalize, - ignore_decl, - ignore_import, - ) - } - - /// Attempts to resolve `ident` in namespace `ns` of `module`. - #[instrument(level = "debug", skip(self))] - fn resolve_ident_in_virt_module_unadjusted<'r>( self: CmResolver<'r, 'ra, 'tcx>, module: ModuleOrUniformRoot<'ra>, ident: Ident, @@ -946,21 +935,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option>, ) -> Result, Determinacy> { match module { - ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set( - ident, - ScopeSet::Module(ns, module), - parent_scope, - finalize, - finalize.is_some(), - ignore_decl, - ignore_import, - ), + ModuleOrUniformRoot::Module(module) => { + let (ident_key, def) = IdentKey::new_adjusted(ident, module.expansion); + let adjusted_parent_scope = match def { + Some(def) => ParentScope { module: self.expn_def_scope(def), ..*parent_scope }, + None => *parent_scope, + }; + self.resolve_ident_in_scope_set_inner( + ident_key, + ident.span, + ScopeSet::Module(ns, module), + &adjusted_parent_scope, + finalize, + ignore_decl, + ignore_import, + ) + } ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set( ident, ScopeSet::ModuleAndExternPrelude(ns, module), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ), @@ -968,12 +963,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if ns != TypeNS { Err(Determined) } else { - self.resolve_ident_in_scope_set( - ident, + self.resolve_ident_in_scope_set_inner( + IdentKey::new_adjusted(ident, ExpnId::root()).0, + ident.span, ScopeSet::ExternPrelude, parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -996,7 +991,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -1165,8 +1159,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => return Err(ControlFlow::Continue(Undetermined)), }; let tmp_parent_scope; - let (mut adjusted_parent_scope, mut ctxt) = (parent_scope, *ident.ctxt); - match ctxt.glob_adjust(module.expansion, glob_import.span) { + let (mut adjusted_parent_scope, mut adjusted_ident) = (parent_scope, ident); + match adjusted_ident + .ctxt + .update_unchecked(|ctxt| ctxt.glob_adjust(module.expansion, glob_import.span)) + { Some(Some(def)) => { tmp_parent_scope = ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; @@ -1175,12 +1172,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(None) => {} None => continue, }; - let result = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(ctxt)), + let result = self.reborrow().resolve_ident_in_scope_set_inner( + adjusted_ident, + orig_ident_span, ScopeSet::Module(ns, module), adjusted_parent_scope, None, - false, ignore_decl, ignore_import, ); @@ -1881,7 +1878,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -1957,8 +1953,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } } - Err(Undetermined) => return PathResult::Indeterminate, - Err(Determined) => { + Err(Undetermined) if finalize.is_none() => return PathResult::Indeterminate, + Err(Determined | Undetermined) => { if let Some(ModuleOrUniformRoot::Module(module)) = module && opt_ns.is_some() && !module.is_normal() diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 7ff24bc612df..4e7622d08462 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -406,8 +406,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) { // We are glob-importing the same item but with greater visibility. - old_glob_decl.vis.set_unchecked(glob_decl.vis()); - old_glob_decl + // FIXME: Update visibility in place, but without regressions + // (#152004, #151124, #152347). + glob_decl } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() { // Overwriting a non-ambiguous glob import with an ambiguous glob import. old_glob_decl.ambiguity.set_unchecked(Some(glob_decl)); @@ -1189,7 +1190,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, &import.parent_scope, - Some(Finalize { report_private: false, ..finalize }), + Some(Finalize { + report_private: false, + import_vis: Some(import.vis), + ..finalize + }), bindings[ns].get().decl(), Some(import), ); @@ -1498,7 +1503,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), &import.parent_scope, None, - false, decls[ns].get().decl(), None, ) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4faf7715de6e..0b92792611a1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -9,13 +9,14 @@ use std::borrow::Cow; use std::collections::hash_map::Entry; use std::mem::{replace, swap, take}; -use std::ops::ControlFlow; +use std::ops::{ControlFlow, Range}; use rustc_ast::visit::{ AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list, }; use rustc_ast::*; use rustc_data_structures::debug_assert_matches; +use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; @@ -746,7 +747,8 @@ pub(crate) struct DiagMetadata<'ast> { /// Accumulate the errors due to missed lifetime elision, /// and report them all at once for each function. - current_elision_failures: Vec, + current_elision_failures: + Vec<(MissingLifetime, LifetimeElisionCandidate, Either>)>, } struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { @@ -1782,19 +1784,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match rib.kind { LifetimeRibKind::Item => break, LifetimeRibKind::ConstParamTy => { - self.emit_non_static_lt_in_const_param_ty_error(lifetime); + let guar = self.emit_non_static_lt_in_const_param_ty_error(lifetime); self.record_lifetime_res( lifetime.id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); return; } LifetimeRibKind::ConcreteAnonConst(cause) => { - self.emit_forbidden_non_static_lifetime_error(cause, lifetime); + let guar = self.emit_forbidden_non_static_lifetime_error(cause, lifetime); self.record_lifetime_res( lifetime.id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); return; @@ -1812,8 +1814,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let outer_res = lifetime_rib_iter .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer)); - self.emit_undeclared_lifetime_error(lifetime, outer_res); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named); + let guar = self.emit_undeclared_lifetime_error(lifetime, outer_res); + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Error(guar), + LifetimeElisionCandidate::Named, + ); } #[instrument(level = "debug", skip(self))] @@ -1878,7 +1884,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } LifetimeRibKind::AnonymousReportError => { - if elided { + let guar = if elided { let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| { if let LifetimeRibKind::Generics { span, @@ -1910,7 +1916,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.r.dcx().emit_err(errors::LendingIteratorReportError { lifetime: lifetime.ident.span, ty: ty.span, - }); + }) } else { let decl = if !trait_id.is_local() && let Some(assoc) = self.diag_metadata.current_impl_item @@ -1940,20 +1946,24 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span); - err.emit(); + err.emit() } } else { self.r.dcx().emit_err(errors::ElidedAnonymousLifetimeReportError { span: lifetime.ident.span, suggestion, - }); + }) } } else { self.r.dcx().emit_err(errors::ExplicitAnonymousLifetimeReportError { span: lifetime.ident.span, - }); + }) }; - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Error(guar), + elision_candidate, + ); return; } LifetimeRibKind::Elided(res) => { @@ -1961,8 +1971,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(missing_lifetime); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); + self.diag_metadata.current_elision_failures.push(( + missing_lifetime, + elision_candidate, + Either::Left(lifetime.id), + )); return; } LifetimeRibKind::Item => break, @@ -1973,8 +1986,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } } - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); - self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); + let guar = self.report_missing_lifetime_specifiers([&missing_lifetime], None); + self.record_lifetime_res(lifetime.id, LifetimeRes::Error(guar), elision_candidate); } fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) { @@ -2222,16 +2235,17 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { !segment.has_generic_args, elided_lifetime_span, ); - self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { - span: path_span, - subdiag, - }); + let guar = + self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { + span: path_span, + subdiag, + }); should_lint = false; for id in node_ids { self.record_lifetime_res( id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Named, ); } @@ -2263,14 +2277,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { break; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(missing_lifetime); - for id in node_ids { - self.record_lifetime_res( - id, - LifetimeRes::Error, - LifetimeElisionCandidate::Ignore, - ); - } + self.diag_metadata.current_elision_failures.push(( + missing_lifetime, + LifetimeElisionCandidate::Ignore, + Either::Right(node_ids), + )); break; } // `LifetimeRes::Error`, which would usually be used in the case of @@ -2278,14 +2289,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // we simply resolve to an implicit lifetime, which will be checked later, at // which point a suitable error will be emitted. LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { + let guar = + self.report_missing_lifetime_specifiers([&missing_lifetime], None); for id in node_ids { self.record_lifetime_res( id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); } - self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); break; } LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} @@ -2329,7 +2341,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { candidates.push((res, candidate)); } } - LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} + LifetimeRes::Infer | LifetimeRes::Error(..) | LifetimeRes::ElidedAnchor { .. } => {} } } @@ -2373,7 +2385,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { replace(&mut this.diag_metadata.current_elision_failures, outer_failures); if !elision_failures.is_empty() { let Err(failure_info) = elision_lifetime else { bug!() }; - this.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); + let guar = this.report_missing_lifetime_specifiers( + elision_failures.iter().map(|(missing_lifetime, ..)| missing_lifetime), + Some(failure_info), + ); + let mut record_res = |lifetime, candidate| { + this.record_lifetime_res(lifetime, LifetimeRes::Error(guar), candidate) + }; + for (_, candidate, nodes) in elision_failures { + match nodes { + Either::Left(node_id) => record_res(node_id, candidate), + Either::Right(node_ids) => { + for lifetime in node_ids { + record_res(lifetime, candidate) + } + } + } + } } }); } @@ -2847,11 +2875,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, defaultness: _, }) => { - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::Item( @@ -2871,7 +2898,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - if is_type_const + if rhs_kind.is_type_const() && !this.r.tcx.features().generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { @@ -2888,12 +2915,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); - if let Some(rhs) = rhs { - this.resolve_const_item_rhs( - rhs, - Some((*ident, ConstantItemKind::Const)), - ); - } + this.resolve_const_item_rhs( + rhs_kind, + Some((*ident, ConstantItemKind::Const)), + ); }, ); self.resolve_define_opaques(define_opaque); @@ -3028,9 +3053,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let GenericParamKind::Lifetime = param.kind && let Some(&original) = seen_lifetimes.get(&ident) { - diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident); + let guar = diagnostics::signal_lifetime_shadowing( + self.r.tcx.sess, + original, + param.ident, + ); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } @@ -3038,11 +3067,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { Entry::Occupied(entry) => { let span = *entry.get(); let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span); - self.report_error(param.ident.span, err); + let guar = self.r.report_error(param.ident.span, err); let rib = match param.kind { GenericParamKind::Lifetime => { // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } GenericParamKind::Type { .. } => &mut function_type_rib, @@ -3071,22 +3100,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .iter() .any(|span| span == param.span()); - self.r + let guar = self + .r .dcx() .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) .emit_unless_delay(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } if param.ident.name == kw::StaticLifetime { - self.r.dcx().emit_err(errors::StaticLifetimeIsReserved { + let guar = self.r.dcx().emit_err(errors::StaticLifetimeIsReserved { span: param.ident.span, lifetime: param.ident, }); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } @@ -3242,11 +3272,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AssocItemKind::Const(box ast::ConstItem { generics, ty, - rhs, + rhs_kind, define_opaque, .. }) => { - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -3261,7 +3290,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, |this| { this.visit_generics(generics); - if is_type_const + if rhs_kind.is_type_const() && !this.r.tcx.features().generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { @@ -3278,14 +3307,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. - if let Some(rhs) = rhs { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_item_rhs(rhs, None); - } + // + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_item_rhs(rhs_kind, None); }, ) }, @@ -3463,12 +3491,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -3505,7 +3532,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); this.visit_generics(generics); - if is_type_const + if rhs_kind.is_type_const() && !this .r .tcx @@ -3527,14 +3554,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } else { this.visit_ty(ty); } - if let Some(rhs) = rhs { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_item_rhs(rhs, None); - } + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_item_rhs(rhs_kind, None); }, ) }, @@ -3756,18 +3781,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_const_item_rhs( &mut self, - rhs: &'ast ConstItemRhs, + rhs_kind: &'ast ConstItemRhsKind, item: Option<(Ident, ConstantItemKind)>, ) { - self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs { - ConstItemRhs::TypeConst(anon_const) => { + self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs_kind { + ConstItemRhsKind::TypeConst { rhs: Some(anon_const) } => { this.resolve_anon_const(anon_const, AnonConstKind::ConstArg(IsRepeatExpr::No)); } - ConstItemRhs::Body(expr) => { + ConstItemRhsKind::Body { rhs: Some(expr) } => { this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { this.visit_expr(expr) }); } + _ => (), }) } @@ -5449,6 +5475,32 @@ fn create_delegation_attrs(attrs: &[Attribute]) -> DelegationAttrs { DelegationAttrs { flags, to_inherit: to_inherit_attrs } } +fn required_generic_args_suggestion(generics: &ast::Generics) -> Option { + let required = generics + .params + .iter() + .filter_map(|param| match ¶m.kind { + ast::GenericParamKind::Lifetime => Some("'_"), + ast::GenericParamKind::Type { default } => { + if default.is_none() { + Some("_") + } else { + None + } + } + ast::GenericParamKind::Const { default, .. } => { + if default.is_none() { + Some("_") + } else { + None + } + } + }) + .collect::>(); + + if required.is_empty() { None } else { Some(format!("<{}>", required.join(", "))) } +} + impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_item(&mut self, item: &'ast Item) { match &item.kind { @@ -5507,6 +5559,13 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } + + if let AssocItemKind::Type(box ast::TyAlias { generics, .. }) = &item.kind { + let def_id = self.r.local_def_id(item.id); + if let Some(suggestion) = required_generic_args_suggestion(generics) { + self.r.item_required_generic_args_suggestions.insert(def_id, suggestion); + } + } visit::walk_assoc_item(self, item, ctxt); } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a3ee17ec4a9a..94f8444db142 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -9,8 +9,8 @@ use rustc_ast::{ self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind, }; -use rustc_ast_pretty::pprust::where_bound_predicate_to_string; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize, @@ -21,7 +21,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{MissingLifetimeKind, PrimTy}; +use rustc_hir::{MissingLifetimeKind, PrimTy, find_attr}; use rustc_middle::ty; use rustc_session::{Session, lint}; use rustc_span::edit_distance::{edit_distance, find_best_match_for_name}; @@ -79,6 +79,23 @@ fn is_self_value(path: &[Segment], namespace: Namespace) -> bool { namespace == ValueNS && path.len() == 1 && path[0].ident.name == kw::SelfLower } +fn path_to_string_without_assoc_item_bindings(path: &Path) -> String { + let mut path = path.clone(); + for segment in &mut path.segments { + let mut remove_args = false; + if let Some(args) = segment.args.as_deref_mut() + && let ast::GenericArgs::AngleBracketed(angle_bracketed) = args + { + angle_bracketed.args.retain(|arg| matches!(arg, ast::AngleBracketedArg::Arg(_))); + remove_args = angle_bracketed.args.is_empty(); + } + if remove_args { + segment.args = None; + } + } + path_to_string(&path) +} + /// Gets the stringified path for an enum from an `ImportSuggestion` for an enum variant. fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) { let variant_path = &suggestion.path; @@ -131,7 +148,7 @@ pub(super) struct ElisionFnParameter { /// Description of lifetimes that appear as candidates for elision. /// This is used to suggest introducing an explicit lifetime. -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub(super) enum LifetimeElisionCandidate { /// This is not a real lifetime. Ignore, @@ -169,6 +186,201 @@ impl TypoCandidate { } impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { + fn trait_assoc_type_def_id_by_name( + &mut self, + trait_def_id: DefId, + assoc_name: Symbol, + ) -> Option { + let module = self.r.get_module(trait_def_id)?; + self.r.resolutions(module).borrow().iter().find_map(|(key, resolution)| { + if key.ident.name != assoc_name { + return None; + } + let resolution = resolution.borrow(); + let binding = resolution.best_decl()?; + match binding.res() { + Res::Def(DefKind::AssocTy, def_id) => Some(def_id), + _ => None, + } + }) + } + + /// This does best-effort work to generate suggestions for associated types. + fn suggest_assoc_type_from_bounds( + &mut self, + err: &mut Diag<'_>, + source: PathSource<'_, 'ast, 'ra>, + path: &[Segment], + ident_span: Span, + ) -> bool { + // Filter out cases where we cannot emit meaningful suggestions. + if source.namespace() != TypeNS { + return false; + } + let [segment] = path else { return false }; + if segment.has_generic_args { + return false; + } + if !ident_span.can_be_used_for_suggestions() { + return false; + } + let assoc_name = segment.ident.name; + if assoc_name == kw::Underscore { + return false; + } + + // Map: type parameter name -> (trait def id -> (assoc type def id, trait paths as written)). + // We keep a set of paths per trait so we can detect cases like + // `T: Trait + Trait` where suggesting `T::Assoc` would be ambiguous. + let mut matching_bounds: FxIndexMap< + Symbol, + FxIndexMap)>, + > = FxIndexMap::default(); + + let mut record_bound = |this: &mut Self, + ty_param: Symbol, + poly_trait_ref: &ast::PolyTraitRef| { + // Avoid generating suggestions we can't print in a well-formed way. + if !poly_trait_ref.bound_generic_params.is_empty() { + return; + } + if poly_trait_ref.modifiers != ast::TraitBoundModifiers::NONE { + return; + } + let Some(trait_seg) = poly_trait_ref.trait_ref.path.segments.last() else { + return; + }; + let Some(partial_res) = this.r.partial_res_map.get(&trait_seg.id) else { + return; + }; + let Some(trait_def_id) = partial_res.full_res().and_then(|res| res.opt_def_id()) else { + return; + }; + let Some(assoc_type_def_id) = + this.trait_assoc_type_def_id_by_name(trait_def_id, assoc_name) + else { + return; + }; + + // Preserve `::` and generic args so we don't generate broken suggestions like + // `::Assoc` for bounds written as `T: ::Foo<'a>`, while stripping + // associated-item bindings that are rejected in qualified paths. + let trait_path = + path_to_string_without_assoc_item_bindings(&poly_trait_ref.trait_ref.path); + let trait_bounds = matching_bounds.entry(ty_param).or_default(); + let trait_bounds = trait_bounds + .entry(trait_def_id) + .or_insert_with(|| (assoc_type_def_id, FxIndexSet::default())); + debug_assert_eq!(trait_bounds.0, assoc_type_def_id); + trait_bounds.1.insert(trait_path); + }; + + let mut record_from_generics = |this: &mut Self, generics: &ast::Generics| { + for param in &generics.params { + let ast::GenericParamKind::Type { .. } = param.kind else { continue }; + for bound in ¶m.bounds { + let ast::GenericBound::Trait(poly_trait_ref) = bound else { continue }; + record_bound(this, param.ident.name, poly_trait_ref); + } + } + + for predicate in &generics.where_clause.predicates { + let ast::WherePredicateKind::BoundPredicate(where_bound) = &predicate.kind else { + continue; + }; + + let ast::TyKind::Path(None, bounded_path) = &where_bound.bounded_ty.kind else { + continue; + }; + let [ast::PathSegment { ident, args: None, .. }] = &bounded_path.segments[..] + else { + continue; + }; + + // Only suggest for bounds that are explicitly on an in-scope type parameter. + let Some(partial_res) = this.r.partial_res_map.get(&where_bound.bounded_ty.id) + else { + continue; + }; + if !matches!(partial_res.full_res(), Some(Res::Def(DefKind::TyParam, _))) { + continue; + } + + for bound in &where_bound.bounds { + let ast::GenericBound::Trait(poly_trait_ref) = bound else { continue }; + record_bound(this, ident.name, poly_trait_ref); + } + } + }; + + if let Some(item) = self.diag_metadata.current_item + && let Some(generics) = item.kind.generics() + { + record_from_generics(self, generics); + } + + if let Some(item) = self.diag_metadata.current_item + && matches!(item.kind, ItemKind::Impl(..)) + && let Some(assoc) = self.diag_metadata.current_impl_item + { + let generics = match &assoc.kind { + AssocItemKind::Const(box ast::ConstItem { generics, .. }) + | AssocItemKind::Fn(box ast::Fn { generics, .. }) + | AssocItemKind::Type(box ast::TyAlias { generics, .. }) => Some(generics), + AssocItemKind::Delegation(..) + | AssocItemKind::MacCall(..) + | AssocItemKind::DelegationMac(..) => None, + }; + if let Some(generics) = generics { + record_from_generics(self, generics); + } + } + + let mut suggestions: FxIndexSet = FxIndexSet::default(); + for (ty_param, traits) in matching_bounds { + let ty_param = ty_param.to_ident_string(); + let trait_paths_len: usize = traits.values().map(|(_, paths)| paths.len()).sum(); + if traits.len() == 1 && trait_paths_len == 1 { + let assoc_type_def_id = traits.values().next().unwrap().0; + let assoc_segment = format!( + "{}{}", + assoc_name, + self.r.item_required_generic_args_suggestion(assoc_type_def_id) + ); + suggestions.insert(format!("{ty_param}::{assoc_segment}")); + } else { + for (assoc_type_def_id, trait_paths) in traits.into_values() { + let assoc_segment = format!( + "{}{}", + assoc_name, + self.r.item_required_generic_args_suggestion(assoc_type_def_id) + ); + for trait_path in trait_paths { + suggestions + .insert(format!("<{ty_param} as {trait_path}>::{assoc_segment}")); + } + } + } + } + + if suggestions.is_empty() { + return false; + } + + let mut suggestions: Vec = suggestions.into_iter().collect(); + suggestions.sort(); + + err.span_suggestions_with_style( + ident_span, + "you might have meant to use an associated type of the same name", + suggestions, + Applicability::MaybeIncorrect, + SuggestionStyle::ShowAlways, + ); + + true + } + fn make_base_error( &mut self, path: &[Segment], @@ -1038,6 +1250,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) -> bool { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); + + // Prefer suggestions based on associated types from in-scope bounds (e.g. `T::Item`) + // over purely edit-distance-based identifier suggestions. + // Otherwise suggestions could be verbose. + if self.suggest_assoc_type_from_bounds(err, source, path, ident_span) { + return false; + } + let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let mut fallback = false; @@ -2446,10 +2666,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .iter() .filter_map(|candidate| candidate.did) .find(|did| { - self.r - .tcx - .get_attrs(*did, sym::rustc_diagnostic_item) - .any(|attr| attr.value_str() == Some(sym::Default)) + find_attr!( + self.r.tcx.get_all_attrs(*did), + AttributeKind::RustcDiagnosticItem(sym::Default) + ) }); let Some(default_trait) = default_trait else { return; @@ -2677,7 +2897,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut names, ScopeSet::All(ns), parent_scope, - ctxt, + segment.ident.span.with_ctxt(ctxt), filter_fn, ); break; @@ -3274,7 +3494,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &self, lifetime_ref: &ast::Lifetime, outer_lifetime_ref: Option, - ) { + ) -> ErrorGuaranteed { debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime); let mut err = if let Some(outer) = outer_lifetime_ref { struct_span_code_err!( @@ -3319,7 +3539,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } - err.emit(); + err.emit() } fn suggest_introducing_lifetime( @@ -3473,14 +3693,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - pub(crate) fn emit_non_static_lt_in_const_param_ty_error(&self, lifetime_ref: &ast::Lifetime) { + pub(crate) fn emit_non_static_lt_in_const_param_ty_error( + &self, + lifetime_ref: &ast::Lifetime, + ) -> ErrorGuaranteed { self.r .dcx() .create_err(errors::ParamInTyOfConstParam { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, }) - .emit(); + .emit() } /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. @@ -3490,18 +3713,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &self, cause: NoConstantGenericsReason, lifetime_ref: &ast::Lifetime, - ) { + ) -> ErrorGuaranteed { match cause { - NoConstantGenericsReason::IsEnumDiscriminant => { - self.r - .dcx() - .create_err(errors::ParamInEnumDiscriminant { - span: lifetime_ref.ident.span, - name: lifetime_ref.ident.name, - param_kind: errors::ParamKindInEnumDiscriminant::Lifetime, - }) - .emit(); - } + NoConstantGenericsReason::IsEnumDiscriminant => self + .r + .dcx() + .create_err(errors::ParamInEnumDiscriminant { + span: lifetime_ref.ident.span, + name: lifetime_ref.ident.name, + param_kind: errors::ParamKindInEnumDiscriminant::Lifetime, + }) + .emit(), NoConstantGenericsReason::NonTrivialConstArg => { assert!(!self.r.tcx.features().generic_const_exprs()); self.r @@ -3510,25 +3732,20 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime, - help: self - .r - .tcx - .sess - .is_nightly_build() - .then_some(errors::ParamInNonTrivialAnonConstHelp), + help: self.r.tcx.sess.is_nightly_build(), }) - .emit(); + .emit() } } } - pub(crate) fn report_missing_lifetime_specifiers( + pub(crate) fn report_missing_lifetime_specifiers<'a>( &mut self, - lifetime_refs: Vec, + lifetime_refs: impl Clone + IntoIterator, function_param_lifetimes: Option<(Vec, Vec)>, ) -> ErrorGuaranteed { - let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum(); - let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); + let num_lifetimes: usize = lifetime_refs.clone().into_iter().map(|lt| lt.count).sum(); + let spans: Vec<_> = lifetime_refs.clone().into_iter().map(|lt| lt.span).collect(); let mut err = struct_span_code_err!( self.r.dcx(), @@ -3545,13 +3762,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.emit() } - fn add_missing_lifetime_specifiers_label( + fn add_missing_lifetime_specifiers_label<'a>( &mut self, err: &mut Diag<'_>, - lifetime_refs: Vec, + lifetime_refs: impl Clone + IntoIterator, function_param_lifetimes: Option<(Vec, Vec)>, ) { - for < in &lifetime_refs { + for < in lifetime_refs.clone() { err.span_label( lt.span, format!( @@ -3680,7 +3897,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { (lt.span.shrink_to_hi(), sugg) } }; - for < in &lifetime_refs { + for < in lifetime_refs.clone() { spans_suggs.push(build_sugg(lt)); } debug!(?spans_suggs); @@ -3708,7 +3925,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } 1 => { let post = if maybe_static { - let owned = if let [lt] = &lifetime_refs[..] + let mut lifetime_refs = lifetime_refs.clone().into_iter(); + let owned = if let Some(lt) = lifetime_refs.next() + && lifetime_refs.next().is_none() && lt.kind != MissingLifetimeKind::Ampersand { ", or if you will only have owned values" @@ -3733,7 +3952,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // we identified that the return expression references only one argument, we // would suggest borrowing only that argument, and we'd skip the prior // "use `'static`" suggestion entirely. - if let [lt] = &lifetime_refs[..] + let mut lifetime_refs = lifetime_refs.clone().into_iter(); + if let Some(lt) = lifetime_refs.next() + && lifetime_refs.next().is_none() && (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) { @@ -4029,7 +4250,11 @@ fn mk_where_bound_predicate( } /// Report lifetime/lifetime shadowing as an error. -pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) { +pub(super) fn signal_lifetime_shadowing( + sess: &Session, + orig: Ident, + shadower: Ident, +) -> ErrorGuaranteed { struct_span_code_err!( sess.dcx(), shadower.span, @@ -4039,7 +4264,7 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I ) .with_span_label(orig.span, "first declared here") .with_span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)) - .emit(); + .emit() } struct LifetimeFinder<'ast> { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5fe1be039a88..ff1c30458a98 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -8,17 +8,16 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(assert_matches))] +#![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))] #![feature(arbitrary_self_types)] -#![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_default)] #![feature(const_trait_impl)] #![feature(control_flow_into_value)] -#![feature(decl_macro)] #![feature(default_field_values)] #![feature(if_let_guard)] #![feature(iter_intersperse)] -#![feature(ptr_as_ref_unchecked)] #![feature(rustc_attrs)] #![feature(trim_prefix_suffix)] #![recursion_limit = "256"] @@ -72,7 +71,6 @@ use rustc_middle::ty::{ self, DelegationFnSig, DelegationInfo, Feed, MainDefinition, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, }; -use rustc_query_system::ich::StableHashingContext; use rustc_session::config::CrateType; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -98,8 +96,6 @@ pub use macros::registered_tools_ast; use crate::ref_mut::{CmCell, CmRefCell}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - #[derive(Copy, Clone, PartialEq, Debug)] enum Determinacy { Determined, @@ -575,6 +571,12 @@ impl IdentKey { IdentKey { name: ident.name, ctxt: Macros20NormalizedSyntaxContext::new(ident.span.ctxt()) } } + #[inline] + fn new_adjusted(ident: Ident, expn_id: ExpnId) -> (IdentKey, Option) { + let (ctxt, def) = Macros20NormalizedSyntaxContext::new_adjusted(ident.span.ctxt(), expn_id); + (IdentKey { name: ident.name, ctxt }, def) + } + #[inline] fn with_root_ctxt(name: Symbol) -> Self { let ctxt = Macros20NormalizedSyntaxContext::new_unchecked(SyntaxContext::root()); @@ -963,6 +965,7 @@ enum AmbiguityWarning { struct AmbiguityError<'ra> { kind: AmbiguityKind, + ambig_vis: Option<(Visibility, Visibility)>, ident: Ident, b1: Decl<'ra>, b2: Decl<'ra>, @@ -1334,6 +1337,8 @@ pub struct Resolver<'ra, 'tcx> { /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap = default::fx_hash_map(), + /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. + item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), delegation_infos: LocalDefIdMap = Default::default(), @@ -1552,6 +1557,32 @@ impl<'tcx> Resolver<'_, 'tcx> { } } + fn item_required_generic_args_suggestion(&self, def_id: DefId) -> String { + if let Some(def_id) = def_id.as_local() { + self.item_required_generic_args_suggestions.get(&def_id).cloned().unwrap_or_default() + } else { + let required = self + .tcx + .generics_of(def_id) + .own_params + .iter() + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => Some("'_"), + ty::GenericParamDefKind::Type { has_default, .. } + | ty::GenericParamDefKind::Const { has_default } => { + if has_default { + None + } else { + Some("_") + } + } + }) + .collect::>(); + + if required.is_empty() { String::new() } else { format!("<{}>", required.join(", ")) } + } + } + pub fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1834,10 +1865,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ResolverOutputs { global_ctxt, ast_lowering } } - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new(self.tcx.sess, self.tcx.untracked()) - } - fn cstore(&self) -> FreezeReadGuard<'_, CStore> { CStore::from_tcx(self.tcx) } @@ -1923,7 +1950,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, current_trait: Option>, parent_scope: &ParentScope<'ra>, - ctxt: Span, + sp: Span, assoc_item: Option<(Symbol, Namespace)>, ) -> Vec { let mut found_traits = Vec::new(); @@ -1940,7 +1967,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let scope_set = ScopeSet::All(TypeNS); - self.cm().visit_scopes(scope_set, parent_scope, ctxt, None, |mut this, scope, _, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| { match scope { Scope::ModuleNonGlobs(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); @@ -2080,6 +2108,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(b2) = used_decl.ambiguity.get() { let ambiguity_error = AmbiguityError { kind: AmbiguityKind::GlobVsGlob, + ambig_vis: None, ident, b1: used_decl, b2, @@ -2549,6 +2578,8 @@ struct Finalize { used: Used = Used::Other, /// Finalizing early or late resolution. stage: Stage = Stage::Early, + /// Nominal visibility of the import item, in case we are resolving an import's final segment. + import_vis: Option = None, } impl Finalize { @@ -2723,7 +2754,7 @@ mod ref_mut { } mod hygiene { - use rustc_span::SyntaxContext; + use rustc_span::{ExpnId, SyntaxContext}; /// A newtype around `SyntaxContext` that can only keep contexts produced by /// [SyntaxContext::normalize_to_macros_2_0]. @@ -2736,6 +2767,15 @@ mod hygiene { Macros20NormalizedSyntaxContext(ctxt.normalize_to_macros_2_0()) } + #[inline] + pub(crate) fn new_adjusted( + mut ctxt: SyntaxContext, + expn_id: ExpnId, + ) -> (Macros20NormalizedSyntaxContext, Option) { + let def = ctxt.normalize_to_macros_2_0_and_adjust(expn_id); + (Macros20NormalizedSyntaxContext(ctxt), def) + } + #[inline] pub(crate) fn new_unchecked(ctxt: SyntaxContext) -> Macros20NormalizedSyntaxContext { debug_assert_eq!(ctxt, ctxt.normalize_to_macros_2_0()); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index b7d83d9e130c..e0973271da52 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -222,17 +222,19 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ) -> LocalExpnId { let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id()); - let expn_id = LocalExpnId::fresh( - ExpnData::allow_unstable( - ExpnKind::AstPass(pass), - call_site, - self.tcx.sess.edition(), - features.into(), - None, - parent_module, - ), - self.create_stable_hashing_context(), - ); + let expn_id = self.tcx.with_stable_hashing_context(|hcx| { + LocalExpnId::fresh( + ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + call_site, + self.tcx.sess.edition(), + features.into(), + None, + parent_module, + ), + hcx, + ) + }); let parent_scope = parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); @@ -322,17 +324,19 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let span = invoc.span(); let def_id = if deleg_impl.is_some() { None } else { res.opt_def_id() }; - invoc_id.set_expn_data( - ext.expn_data( - parent_scope.expansion, - span, - fast_print_path(path), - kind, - def_id, - def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), - ), - self.create_stable_hashing_context(), - ); + self.tcx.with_stable_hashing_context(|hcx| { + invoc_id.set_expn_data( + ext.expn_data( + parent_scope.expansion, + span, + fast_print_path(path), + kind, + def_id, + def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), + ), + hcx, + ) + }); Ok(ext) } @@ -799,10 +803,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(kind), parent_scope, None, - force, None, None, ); + let binding = binding.map_err(|determinacy| { + Determinacy::determined(determinacy == Determinacy::Determined || force) + }); if let Err(Determinacy::Undetermined) = binding { return Err(Determinacy::Undetermined); } @@ -958,7 +964,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(kind), &parent_scope, Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), - true, None, None, ) { @@ -1013,7 +1018,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(MacroKind::Attr), &parent_scope, Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), - true, None, None, ); @@ -1117,7 +1121,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(MacroKind::Bang), &ParentScope { macro_rules: no_macro_rules, ..*parent_scope }, None, - false, None, None, ); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 9cea681fcb57..971ac9348fc4 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -243,24 +243,24 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc .flat_map(|super_poly_trait_ref| { tcx.associated_items(super_poly_trait_ref.def_id()) .in_definition_order() - .filter(|item| item.is_type()) + .filter(|item| item.is_type() || item.is_const()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .map(move |assoc_ty| { + .map(move |assoc_item| { super_poly_trait_ref.map_bound(|super_trait_ref| { - let alias_ty = - ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args); - let resolved = tcx.normalize_erasing_regions( - ty::TypingEnv::fully_monomorphized(), - alias_ty.to_ty(tcx), + let projection_term = ty::AliasTerm::new_from_args( + tcx, + assoc_item.def_id, + super_trait_ref.args, ); - debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx)); + let term = tcx.normalize_erasing_regions( + ty::TypingEnv::fully_monomorphized(), + projection_term.to_term(tcx), + ); + debug!("Projection {:?} -> {term}", projection_term.to_term(tcx),); ty::ExistentialPredicate::Projection( ty::ExistentialProjection::erase_self_ty( tcx, - ty::ProjectionPredicate { - projection_term: alias_ty.into(), - term: resolved.into(), - }, + ty::ProjectionPredicate { projection_term, term }, ), ) }) diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 842068a4fc04..f4c7e5519536 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::internal)] -#![cfg_attr(test, feature(test))] #![doc(test(attr(allow(unused_variables), deny(warnings), allow(internal_features))))] #![feature(core_intrinsics)] #![feature(min_specialization)] diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index aebac3880d2f..d66e04f58106 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast = { path = "../rustc_ast" } 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_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl deleted file mode 100644 index 5c851cb90a66..000000000000 --- a/compiler/rustc_session/messages.ftl +++ /dev/null @@ -1,149 +0,0 @@ -session_apple_deployment_target_invalid = - failed to parse deployment target specified in {$env_var}: {$error} - -session_apple_deployment_target_too_low = - deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} - -session_binary_float_literal_not_supported = binary float literal is not supported -session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64 - -session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` - -session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}` - -session_cli_feature_diagnostic_help = - add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable - -session_crate_name_empty = crate name must not be empty - -session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version} - -session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled - -session_expr_parentheses_needed = parentheses are required to parse this as an expression - -session_failed_to_create_profiler = failed to create profiler: {$err} - -session_feature_diagnostic_for_issue = - see issue #{$n} for more information - -session_feature_diagnostic_help = - add `#![feature({$feature})]` to the crate attributes to enable - -session_feature_diagnostic_suggestion = - add `#![feature({$feature})]` to the crate attributes to enable - -session_feature_suggest_upgrade_compiler = - this compiler was built on {$date}; consider upgrading it if it is out of date - -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}` - -session_function_return_requires_x86_or_x86_64 = `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 - -session_function_return_thunk_extern_requires_non_large_code_model = `-Zfunction-return=thunk-extern` is only supported on non-large code models - -session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported - -session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target - .note = compatible flavors are: {$compatible_list} - -session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64 - -session_instrumentation_not_supported = {$us} instrumentation is not supported for this target - -session_int_literal_too_large = integer literal is too large - .note = value exceeds limit of `{$limit}` - -session_invalid_character_in_crate_name = invalid character {$character} in crate name: `{$crate_name}` - -session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal - .label = invalid suffix `{$suffix}` - .help = valid suffixes are `f32` and `f64` - -session_invalid_float_literal_width = invalid width `{$width}` for float literal - .help = valid widths are 32 and 64 - -session_invalid_int_literal_width = invalid width `{$width}` for integer literal - .help = valid widths are 8, 16, 32, 64 and 128 - -session_invalid_literal_suffix = suffixes on {$kind} literals are invalid - .label = invalid suffix `{$suffix}` - -session_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 - -session_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.) - -session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets - -session_must_be_name_of_associated_function = must be a name of an associated function - -session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine - -session_not_supported = not supported - -session_octal_float_literal_not_supported = octal float literal is not supported - -session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist - -session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist - -session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi` - -session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` - -session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` - -session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto` - -session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` - -session_sanitizer_kcfi_arity_requires_kcfi = `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi` - -session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort` - -session_sanitizer_not_supported = {$us} sanitizer is not supported for this target - -session_sanitizers_not_supported = {$us} sanitizers are not supported for this target - -session_skipping_const_checks = skipping const checks - -session_soft_float_deprecated = - `-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead - .note = it will be removed or ignored in a future version of Rust -session_soft_float_deprecated_issue = see issue #129893 for more information - -session_soft_float_ignored = - `-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets - .note = this may become a hard error in a future version of Rust - -session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform - -session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` - -session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` - -session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored - -session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored - -session_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag - .controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}` - .incoherent = manually setting a built-in cfg can and does create incoherent behaviors - -session_unleashed_feature_help_named = skipping check for `{$gate}` feature -session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate - -session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` - -session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is not supported -session_unsupported_dwarf_version_help = supported DWARF versions are 2, 3, 4 and 5 - -session_unsupported_reg_struct_return_arch = `-Zreg-struct-return` is only supported on x86 -session_unsupported_regparm = `-Zregparm={$regparm}` is unsupported (valid values 0-3) -session_unsupported_regparm_arch = `-Zregparm=N` is only supported on x86 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5e2671ef4ef6..b278a6179fe7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -88,7 +88,7 @@ pub enum CFProtection { Full, } -#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)] +#[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic, Encodable, Decodable)] pub enum OptLevel { /// `-Copt-level=0` No, @@ -108,7 +108,7 @@ pub enum OptLevel { /// and taking other command line options into account. /// /// Note that linker plugin-based LTO is a different mechanism entirely. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Encodable, Decodable)] pub enum Lto { /// Don't do any LTO whatsoever. No, @@ -190,7 +190,7 @@ pub enum CoverageLevel { } // The different settings that the `-Z offload` flag can have. -#[derive(Clone, PartialEq, Hash, Debug)] +#[derive(Clone, PartialEq, Hash, Debug, Encodable, Decodable)] pub enum Offload { /// Entry point for `std::offload`, enables kernel compilation for a gpu device Device, @@ -201,7 +201,7 @@ pub enum Offload { } /// The different settings that the `-Z autodiff` flag can have. -#[derive(Clone, PartialEq, Hash, Debug)] +#[derive(Clone, PartialEq, Hash, Debug, Encodable, Decodable)] pub enum AutoDiff { /// Enable the autodiff opt pipeline Enable, @@ -528,7 +528,7 @@ impl FmtDebug { } } -#[derive(Clone, PartialEq, Hash, Debug)] +#[derive(Clone, PartialEq, Hash, Debug, Encodable, Decodable)] pub enum SwitchWithOptPath { Enabled(Option), Disabled, @@ -583,7 +583,7 @@ pub enum MirStripDebugInfo { /// DWARF provides a mechanism which allows the linker to skip the sections which don't require /// link-time relocation - either by putting those sections in DWARF object files, or by keeping /// them in the object file in such a way that the linker will skip them. -#[derive(Clone, Copy, Debug, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)] pub enum SplitDwarfKind { /// Sections which do not require relocation are written into object file but ignored by the /// linker. @@ -1539,7 +1539,7 @@ pub enum EntryFnType { pub use rustc_hir::attrs::CrateType; -#[derive(Clone, Hash, Debug, PartialEq, Eq)] +#[derive(Clone, Hash, Debug, PartialEq, Eq, Encodable, Decodable)] pub enum Passes { Some(Vec), All, diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs index 71d3e222c8a1..28e2d0f94104 100644 --- a/compiler/rustc_session/src/config/native_libs.rs +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -53,7 +53,9 @@ fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib { let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value); let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind { - "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, + "static" => { + NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None } + } "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => NativeLibKind::Framework { as_needed: None }, "link-arg" => { @@ -105,7 +107,7 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li Some(("-", m)) => (m, false), _ => cx.early_dcx.early_fatal( "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", + before one of: bundle, verbatim, whole-archive, as-needed, export-symbols", ), }; @@ -125,6 +127,13 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li ("bundle", _) => early_dcx .early_fatal("linking modifier `bundle` is only compatible with `static` linking kind"), + ("export-symbols", NativeLibKind::Static { export_symbols, .. }) => { + assign_modifier(export_symbols) + } + ("export-symbols", _) => early_dcx.early_fatal( + "linking modifier `export-symbols` is only compatible with `static` linking kind", + ), + ("verbatim", _) => assign_modifier(&mut native_lib.verbatim), ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { @@ -151,7 +160,7 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li _ => early_dcx.early_fatal(format!( "unknown linking modifier `{modifier}`, expected one \ - of: bundle, verbatim, whole-archive, as-needed" + of: bundle, verbatim, whole-archive, as-needed, export-symbols" )), } } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 54e792fd7b59..04a32c20a791 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -15,9 +15,11 @@ use crate::parse::ParseSess; #[derive(Diagnostic)] pub(crate) enum AppleDeploymentTarget { - #[diag(session_apple_deployment_target_invalid)] + #[diag("failed to parse deployment target specified in {$env_var}: {$error}")] Invalid { env_var: &'static str, error: ParseIntError }, - #[diag(session_apple_deployment_target_too_low)] + #[diag( + "deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}" + )] TooLow { env_var: &'static str, version: String, os_min: String }, } @@ -34,13 +36,13 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError { } #[derive(Subdiagnostic)] -#[note(session_feature_diagnostic_for_issue)] +#[note("see issue #{$n} for more information")] pub(crate) struct FeatureDiagnosticForIssue { pub(crate) n: NonZero, } #[derive(Subdiagnostic)] -#[note(session_feature_suggest_upgrade_compiler)] +#[note("this compiler was built on {$date}; consider upgrading it if it is out of date")] pub(crate) struct SuggestUpgradeCompiler { date: &'static str, } @@ -58,14 +60,14 @@ impl SuggestUpgradeCompiler { } #[derive(Subdiagnostic)] -#[help(session_feature_diagnostic_help)] +#[help("add `#![feature({$feature})]` to the crate attributes to enable")] pub(crate) struct FeatureDiagnosticHelp { pub(crate) feature: Symbol, } #[derive(Subdiagnostic)] #[suggestion( - session_feature_diagnostic_suggestion, + "add `#![feature({$feature})]` to the crate attributes to enable", applicability = "maybe-incorrect", code = "#![feature({feature})]\n" )] @@ -76,169 +78,181 @@ pub struct FeatureDiagnosticSuggestion { } #[derive(Subdiagnostic)] -#[help(session_cli_feature_diagnostic_help)] +#[help("add `-Zcrate-attr=\"feature({$feature})\"` to the command-line options to enable")] pub(crate) struct CliFeatureDiagnosticHelp { pub(crate) feature: Symbol, } #[derive(Diagnostic)] -#[diag(session_must_be_name_of_associated_function)] +#[diag("must be a name of an associated function")] pub struct MustBeNameOfAssociatedFunction { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(session_not_circumvent_feature)] +#[diag( + "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine" +)] pub(crate) struct NotCircumventFeature; #[derive(Diagnostic)] -#[diag(session_linker_plugin_lto_windows_not_supported)] +#[diag( + "linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets" +)] pub(crate) struct LinkerPluginToWindowsNotSupported; #[derive(Diagnostic)] -#[diag(session_profile_use_file_does_not_exist)] +#[diag("file `{$path}` passed to `-C profile-use` does not exist")] pub(crate) struct ProfileUseFileDoesNotExist<'a> { pub(crate) path: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_profile_sample_use_file_does_not_exist)] +#[diag("file `{$path}` passed to `-C profile-sample-use` does not exist")] pub(crate) struct ProfileSampleUseFileDoesNotExist<'a> { pub(crate) path: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_target_requires_unwind_tables)] +#[diag("target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`")] pub(crate) struct TargetRequiresUnwindTables; #[derive(Diagnostic)] -#[diag(session_instrumentation_not_supported)] +#[diag("{$us} instrumentation is not supported for this target")] pub(crate) struct InstrumentationNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_sanitizer_not_supported)] +#[diag("{$us} sanitizer is not supported for this target")] pub(crate) struct SanitizerNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_sanitizers_not_supported)] +#[diag("{$us} sanitizers are not supported for this target")] pub(crate) struct SanitizersNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_cannot_mix_and_match_sanitizers)] +#[diag("`-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`")] pub(crate) struct CannotMixAndMatchSanitizers { pub(crate) first: String, pub(crate) second: String, } #[derive(Diagnostic)] -#[diag(session_cannot_enable_crt_static_linux)] +#[diag( + "sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`" +)] pub(crate) struct CannotEnableCrtStaticLinux; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_requires_lto)] +#[diag("`-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`")] pub(crate) struct SanitizerCfiRequiresLto; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_requires_single_codegen_unit)] +#[diag("`-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`")] pub(crate) struct SanitizerCfiRequiresSingleCodegenUnit; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_canonical_jump_tables_requires_cfi)] +#[diag("`-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiCanonicalJumpTablesRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_generalize_pointers_requires_cfi)] +#[diag("`-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)] +#[diag("`-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_kcfi_arity_requires_kcfi)] +#[diag("`-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerKcfiArityRequiresKcfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_kcfi_requires_panic_abort)] +#[diag("`-Z sanitizer=kcfi` requires `-C panic=abort`")] pub(crate) struct SanitizerKcfiRequiresPanicAbort; #[derive(Diagnostic)] -#[diag(session_split_lto_unit_requires_lto)] +#[diag("`-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`")] pub(crate) struct SplitLtoUnitRequiresLto; #[derive(Diagnostic)] -#[diag(session_unstable_virtual_function_elimination)] +#[diag("`-Zvirtual-function-elimination` requires `-Clto`")] pub(crate) struct UnstableVirtualFunctionElimination; #[derive(Diagnostic)] -#[diag(session_unsupported_dwarf_version)] -#[help(session_unsupported_dwarf_version_help)] +#[diag("requested DWARF version {$dwarf_version} is not supported")] +#[help("supported DWARF versions are 2, 3, 4 and 5")] pub(crate) struct UnsupportedDwarfVersion { pub(crate) dwarf_version: u32, } #[derive(Diagnostic)] -#[diag(session_embed_source_insufficient_dwarf_version)] +#[diag( + "`-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version}" +)] pub(crate) struct EmbedSourceInsufficientDwarfVersion { pub(crate) dwarf_version: u32, } #[derive(Diagnostic)] -#[diag(session_embed_source_requires_debug_info)] +#[diag("`-Zembed-source=y` requires debug information to be enabled")] pub(crate) struct EmbedSourceRequiresDebugInfo; #[derive(Diagnostic)] -#[diag(session_target_stack_protector_not_supported)] +#[diag( + "`-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored" +)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) stack_protector: StackProtector, pub(crate) target_triple: &'a TargetTuple, } #[derive(Diagnostic)] -#[diag(session_target_small_data_threshold_not_supported)] +#[diag( + "`-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored" +)] pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> { pub(crate) target_triple: &'a TargetTuple, } #[derive(Diagnostic)] -#[diag(session_branch_protection_requires_aarch64)] +#[diag("`-Zbranch-protection` is only supported on aarch64")] pub(crate) struct BranchProtectionRequiresAArch64; #[derive(Diagnostic)] -#[diag(session_split_debuginfo_unstable_platform)] +#[diag("`-Csplit-debuginfo={$debuginfo}` is unstable on this platform")] pub(crate) struct SplitDebugInfoUnstablePlatform { pub(crate) debuginfo: SplitDebuginfo, } #[derive(Diagnostic)] -#[diag(session_file_is_not_writeable)] +#[diag("output file {$file} is not writeable -- check its permissions")] pub(crate) struct FileIsNotWriteable<'a> { pub(crate) file: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_file_write_fail)] +#[diag("failed to write `{$path}` due to error `{$err}`")] pub(crate) struct FileWriteFail<'a> { pub(crate) path: &'a std::path::Path, pub(crate) err: String, } #[derive(Diagnostic)] -#[diag(session_crate_name_empty)] +#[diag("crate name must not be empty")] pub(crate) struct CrateNameEmpty { #[primary_span] pub(crate) span: Option, } #[derive(Diagnostic)] -#[diag(session_invalid_character_in_crate_name)] +#[diag("invalid character {$character} in crate name: `{$crate_name}`")] pub(crate) struct InvalidCharacterInCrateName { #[primary_span] pub(crate) span: Option, @@ -247,7 +261,10 @@ pub(crate) struct InvalidCharacterInCrateName { } #[derive(Subdiagnostic)] -#[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")] +#[multipart_suggestion( + "parentheses are required to parse this as an expression", + applicability = "machine-applicable" +)] pub struct ExprParenthesesNeeded { #[suggestion_part(code = "(")] left: Span, @@ -262,7 +279,7 @@ impl ExprParenthesesNeeded { } #[derive(Diagnostic)] -#[diag(session_skipping_const_checks)] +#[diag("skipping const checks")] pub(crate) struct SkippingConstChecks { #[subdiagnostic] pub(crate) unleashed_features: Vec, @@ -270,13 +287,13 @@ pub(crate) struct SkippingConstChecks { #[derive(Subdiagnostic)] pub(crate) enum UnleashedFeatureHelp { - #[help(session_unleashed_feature_help_named)] + #[help("skipping check for `{$gate}` feature")] Named { #[primary_span] span: Span, gate: Symbol, }, - #[help(session_unleashed_feature_help_unnamed)] + #[help("skipping check that does not even have a feature gate")] Unnamed { #[primary_span] span: Span, @@ -284,10 +301,10 @@ pub(crate) enum UnleashedFeatureHelp { } #[derive(Diagnostic)] -#[diag(session_invalid_literal_suffix)] +#[diag("suffixes on {$kind} literals are invalid")] struct InvalidLiteralSuffix<'a> { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, // FIXME(#100717) kind: &'a str, @@ -295,8 +312,8 @@ struct InvalidLiteralSuffix<'a> { } #[derive(Diagnostic)] -#[diag(session_invalid_int_literal_width)] -#[help] +#[diag("invalid width `{$width}` for integer literal")] +#[help("valid widths are 8, 16, 32, 64 and 128")] struct InvalidIntLiteralWidth { #[primary_span] span: Span, @@ -304,28 +321,32 @@ struct InvalidIntLiteralWidth { } #[derive(Diagnostic)] -#[diag(session_invalid_num_literal_base_prefix)] -#[note] +#[diag("invalid base prefix for number literal")] +#[note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")] struct InvalidNumLiteralBasePrefix { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] + #[suggestion( + "try making the prefix lowercase", + applicability = "maybe-incorrect", + code = "{fixed}" + )] span: Span, fixed: String, } #[derive(Diagnostic)] -#[diag(session_invalid_num_literal_suffix)] -#[help] +#[diag("invalid suffix `{$suffix}` for number literal")] +#[help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")] struct InvalidNumLiteralSuffix { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, suffix: String, } #[derive(Diagnostic)] -#[diag(session_invalid_float_literal_width)] -#[help] +#[diag("invalid width `{$width}` for float literal")] +#[help("valid widths are 32 and 64")] struct InvalidFloatLiteralWidth { #[primary_span] span: Span, @@ -333,18 +354,18 @@ struct InvalidFloatLiteralWidth { } #[derive(Diagnostic)] -#[diag(session_invalid_float_literal_suffix)] -#[help] +#[diag("invalid suffix `{$suffix}` for float literal")] +#[help("valid suffixes are `f32` and `f64`")] struct InvalidFloatLiteralSuffix { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, suffix: String, } #[derive(Diagnostic)] -#[diag(session_int_literal_too_large)] -#[note] +#[diag("integer literal is too large")] +#[note("value exceeds limit of `{$limit}`")] struct IntLiteralTooLarge { #[primary_span] span: Span, @@ -352,26 +373,26 @@ struct IntLiteralTooLarge { } #[derive(Diagnostic)] -#[diag(session_hexadecimal_float_literal_not_supported)] +#[diag("hexadecimal float literal is not supported")] struct HexadecimalFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } #[derive(Diagnostic)] -#[diag(session_octal_float_literal_not_supported)] +#[diag("octal float literal is not supported")] struct OctalFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } #[derive(Diagnostic)] -#[diag(session_binary_float_literal_not_supported)] +#[diag("binary float literal is not supported")] struct BinaryFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } @@ -457,62 +478,66 @@ pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: } #[derive(Diagnostic)] -#[diag(session_incompatible_linker_flavor)] -#[note] +#[diag("linker flavor `{$flavor}` is incompatible with the current target")] +#[note("compatible flavors are: {$compatible_list}")] pub(crate) struct IncompatibleLinkerFlavor { pub(crate) flavor: &'static str, pub(crate) compatible_list: String, } #[derive(Diagnostic)] -#[diag(session_function_return_requires_x86_or_x86_64)] +#[diag("`-Zfunction-return` (except `keep`) is only supported on x86 and x86_64")] pub(crate) struct FunctionReturnRequiresX86OrX8664; #[derive(Diagnostic)] -#[diag(session_function_return_thunk_extern_requires_non_large_code_model)] +#[diag("`-Zfunction-return=thunk-extern` is only supported on non-large code models")] pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; #[derive(Diagnostic)] -#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)] +#[diag("`-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64")] pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664; #[derive(Diagnostic)] -#[diag(session_unsupported_regparm)] +#[diag("`-Zregparm={$regparm}` is unsupported (valid values 0-3)")] pub(crate) struct UnsupportedRegparm { pub(crate) regparm: u32, } #[derive(Diagnostic)] -#[diag(session_unsupported_regparm_arch)] +#[diag("`-Zregparm=N` is only supported on x86")] pub(crate) struct UnsupportedRegparmArch; #[derive(Diagnostic)] -#[diag(session_unsupported_reg_struct_return_arch)] +#[diag("`-Zreg-struct-return` is only supported on x86")] pub(crate) struct UnsupportedRegStructReturnArch; #[derive(Diagnostic)] -#[diag(session_failed_to_create_profiler)] +#[diag("failed to create profiler: {$err}")] pub(crate) struct FailedToCreateProfiler { pub(crate) err: String, } #[derive(Diagnostic)] -#[diag(session_soft_float_ignored)] -#[note] +#[diag("`-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets")] +#[note("this may become a hard error in a future version of Rust")] pub(crate) struct SoftFloatIgnored; #[derive(Diagnostic)] -#[diag(session_soft_float_deprecated)] -#[note] -#[note(session_soft_float_deprecated_issue)] +#[diag("`-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead")] +#[note("it will be removed or ignored in a future version of Rust")] +#[note("see issue #129893 for more information")] pub(crate) struct SoftFloatDeprecated; #[derive(LintDiagnostic)] -#[diag(session_unexpected_builtin_cfg)] -#[note(session_controlled_by)] -#[note(session_incoherent)] +#[diag("unexpected `--cfg {$cfg}` flag")] +#[note("config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`")] +#[note("manually setting a built-in cfg can and does create incoherent behaviors")] pub(crate) struct UnexpectedBuiltinCfg { pub(crate) cfg: String, pub(crate) cfg_name: Symbol, pub(crate) controlled_by: &'static str, } + +#[derive(Diagnostic)] +#[diag("ThinLTO is not supported by the codegen backend")] +pub(crate) struct ThinLtoNotSupportedByBackend; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 90108e911044..98731a235d41 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -32,8 +32,6 @@ pub mod output; pub use getopts; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index d198675c0b22..62c23424f371 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -280,8 +280,8 @@ pub struct ParseSess { impl ParseSess { /// Used for testing. - pub fn new(locale_resources: Vec<&'static str>) -> Self { - let translator = Translator::with_fallback_bundle(locale_resources, false); + pub fn new() -> Self { + let translator = Translator::new(); let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new( AnnotateSnippetEmitter::new(stderr_destination(ColorConfig::Auto), translator) @@ -313,8 +313,8 @@ impl ParseSess { } } - pub fn emitter_with_note(locale_resources: Vec<&'static str>, note: String) -> Self { - let translator = Translator::with_fallback_bundle(locale_resources, false); + pub fn emitter_with_note(note: String) -> Self { + let translator = Translator::new(); let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(AnnotateSnippetEmitter::new( stderr_destination(ColorConfig::Auto), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 27d6efb8b549..bb22e4a8db04 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -8,7 +8,7 @@ use std::{env, io}; use rand::{RngCore, rng}; use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{DynSend, DynSync, Lock, MappedReadGuard, ReadGuard, RwLock}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; @@ -19,7 +19,7 @@ use rustc_errors::timings::TimingSectionHandler; use rustc_errors::translation::Translator; use rustc_errors::{ Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, - TerminalUrl, fallback_fluent_bundle, + TerminalUrl, }; use rustc_hir::limit::Limit; use rustc_macros::HashStable_Generic; @@ -154,6 +154,13 @@ pub struct Session { /// preserved with a flag like `-C save-temps`, since these files may be /// hard linked. pub invocation_temp: Option, + + /// The names of intrinsics that the current codegen backend replaces + /// with its own implementations. + pub replaced_intrinsics: FxHashSet, + + /// Does the codegen backend support ThinLTO? + pub thin_lto_supported: bool, } #[derive(Clone, Copy)] @@ -602,10 +609,19 @@ impl Session { } config::LtoCli::Thin => { // The user explicitly asked for ThinLTO + if !self.thin_lto_supported { + // Backend doesn't support ThinLTO, disable LTO. + self.dcx().emit_warn(errors::ThinLtoNotSupportedByBackend); + return config::Lto::No; + } return config::Lto::Thin; } } + if !self.thin_lto_supported { + return config::Lto::No; + } + // Ok at this point the target doesn't require anything and the user // hasn't asked for anything. Our next decision is whether or not // we enable "auto" ThinLTO where we use multiple codegen units and @@ -963,8 +979,6 @@ pub fn build_session( sopts: config::Options, io: CompilerIO, fluent_bundle: Option>, - registry: rustc_errors::registry::Registry, - fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap, target: Target, cfg_version: &'static str, @@ -982,19 +996,12 @@ pub fn build_session( let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow); let can_emit_warnings = !(warnings_allow || cap_lints_allow); - let translator = Translator { - fluent_bundle, - fallback_fluent_bundle: fallback_fluent_bundle( - fluent_resources, - sopts.unstable_opts.translate_directionality_markers, - ), - }; + let translator = Translator { fluent_bundle }; let source_map = rustc_span::source_map::get_source_map().unwrap(); let emitter = default_emitter(&sopts, Arc::clone(&source_map), translator); - let mut dcx = DiagCtxt::new(emitter) - .with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)) - .with_registry(registry); + let mut dcx = + DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)); if let Some(ice_file) = ice_file { dcx = dcx.with_ice_file(ice_file); } @@ -1092,6 +1099,8 @@ pub fn build_session( target_filesearch, host_filesearch, invocation_temp, + replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler` + thin_lto_supported: true, // filled by `run_compiler` }; validate_commandline_args_with_session_available(&sess); @@ -1427,8 +1436,7 @@ impl EarlyDiagCtxt { fn mk_emitter(output: ErrorOutputType) -> Box { // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will // need to reference every crate that might emit an early error for translation to work. - let translator = - Translator::with_fallback_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::new(); let emitter: Box = match output { config::ErrorOutputType::HumanReadable { kind, color_config } => match kind { HumanReadableErrorType { short, unicode } => Box::new( diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index a0ccf8d7e798..82d455ab54f0 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -540,7 +540,7 @@ macro_rules! typed_def_id { } // N.B.: when adding new typed `DefId`s update the corresponding trait impls in -// `rustc_middle::dep_graph::def_node` for `DepNodeParams`. +// `rustc_middle::dep_graph::dep_node_key` for `DepNodeKey`. typed_def_id! { ModDefId, LocalModDefId } impl LocalModDefId { diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 2e8037b3f9e4..25834f03af5e 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -30,7 +30,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lock; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; @@ -126,27 +126,6 @@ rustc_index::newtype_index! { impl !Ord for LocalExpnId {} impl !PartialOrd for LocalExpnId {} -/// Assert that the provided `HashStableContext` is configured with the 'default' -/// `HashingControls`. We should always have bailed out before getting to here -/// with a non-default mode. With this check in place, we can avoid the need -/// to maintain separate versions of `ExpnData` hashes for each permutation -/// of `HashingControls` settings. -fn assert_default_hashing_controls(ctx: &impl HashStableContext, msg: &str) { - match ctx.hashing_controls() { - // Note that we require that `hash_spans` be set according to the global - // `-Z incremental-ignore-spans` option. Normally, this option is disabled, - // which will cause us to require that this method always be called with `Span` hashing - // enabled. - // - // Span hashing can also be disabled without `-Z incremental-ignore-spans`. - // This is the case for instance when building a hash for name mangling. - // Such configuration must not be used for metadata. - HashingControls { hash_spans } - if hash_spans != ctx.unstable_opts_incremental_ignore_spans() => {} - other => panic!("Attempted hashing of {msg} with non-default HashingControls: {other:?}"), - } -} - /// A unique hash value associated to an expansion. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] pub struct ExpnHash(Fingerprint); @@ -804,7 +783,7 @@ impl SyntaxContext { /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. #[inline] - pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { HygieneData::with(|data| { *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id) @@ -1506,7 +1485,7 @@ pub fn raw_encode_syntax_context( fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash { // This disambiguator should not have been set yet. assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}"); - assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)"); + ctx.assert_default_hashing_controls("ExpnData (disambiguator)"); let mut expn_hash = expn_data.hash_expn(&mut ctx); let disambiguator = HygieneData::with(|data| { @@ -1556,7 +1535,7 @@ impl HashStable for SyntaxContext { impl HashStable for ExpnId { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - assert_default_hashing_controls(ctx, "ExpnId"); + ctx.assert_default_hashing_controls("ExpnId"); let hash = if *self == ExpnId::root() { // Avoid fetching TLS storage for a trivial often-used value. Fingerprint::ZERO diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index a178f3260d30..00646dc7bcf4 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -54,7 +54,6 @@ use hygiene::Transparency; pub use hygiene::{ DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, }; -use rustc_data_structures::stable_hasher::HashingControls; pub mod def_id; use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LOCAL_CRATE, LocalDefId, StableCrateId}; pub mod edit_distance; @@ -2402,14 +2401,12 @@ impl SourceFile { /// normalized one. Hence we need to convert those offsets to the normalized /// form when constructing spans. pub fn normalized_byte_pos(&self, offset: u32) -> BytePos { - let diff = match self - .normalized_pos - .binary_search_by(|np| (np.pos.0 + np.diff).cmp(&(self.start_pos.0 + offset))) - { - Ok(i) => self.normalized_pos[i].diff, - Err(0) => 0, - Err(i) => self.normalized_pos[i - 1].diff, - }; + let diff = + match self.normalized_pos.binary_search_by(|np| (np.pos.0 + np.diff).cmp(&offset)) { + Ok(i) => self.normalized_pos[i].diff, + Err(0) => 0, + Err(i) => self.normalized_pos[i - 1].diff, + }; BytePos::from_u32(self.start_pos.0 + offset - diff) } @@ -2798,106 +2795,24 @@ impl InnerSpan { /// This is a hack to allow using the [`HashStable_Generic`] derive macro /// instead of implementing everything in rustc_middle. pub trait HashStableContext { + /// The main event: stable hashing of a span. + fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher); + + /// Compute a `DefPathHash`. fn def_path_hash(&self, def_id: DefId) -> DefPathHash; - fn hash_spans(&self) -> bool; - /// Accesses `sess.opts.unstable_opts.incremental_ignore_spans` since - /// we don't have easy access to a `Session` - fn unstable_opts_incremental_ignore_spans(&self) -> bool; - fn def_span(&self, def_id: LocalDefId) -> Span; - fn span_data_to_lines_and_cols( - &mut self, - span: &SpanData, - ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)>; - fn hashing_controls(&self) -> HashingControls; + + /// Assert that the provided `HashStableContext` is configured with the default + /// `HashingControls`. We should always have bailed out before getting to here with a + fn assert_default_hashing_controls(&self, msg: &str); } impl HashStable for Span where CTX: HashStableContext, { - /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` - /// fields (that would be similar to hashing pointers, since those are just - /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column) - /// triple, which stays the same even if the containing `SourceFile` has moved - /// within the `SourceMap`. - /// - /// Also note that we are hashing byte offsets for the column, not unicode - /// codepoint offsets. For the purpose of the hash that's sufficient. - /// Also, hashing filenames is expensive so we avoid doing it twice when the - /// span starts and ends in the same file, which is almost always the case. - /// - /// IMPORTANT: changes to this method should be reflected in implementations of `SpanEncoder`. fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_VALID_SPAN: u8 = 0; - const TAG_INVALID_SPAN: u8 = 1; - const TAG_RELATIVE_SPAN: u8 = 2; - - if !ctx.hash_spans() { - return; - } - - let span = self.data_untracked(); - span.ctxt.hash_stable(ctx, hasher); - span.parent.hash_stable(ctx, hasher); - - if span.is_dummy() { - Hash::hash(&TAG_INVALID_SPAN, hasher); - return; - } - - let parent = span.parent.map(|parent| ctx.def_span(parent).data_untracked()); - if let Some(parent) = parent - && parent.contains(span) - { - // This span is enclosed in a definition: only hash the relative position. - // This catches a subset of the cases from the `file.contains(parent.lo)`, - // But we can do this check cheaply without the expensive `span_data_to_lines_and_cols` query. - Hash::hash(&TAG_RELATIVE_SPAN, hasher); - (span.lo - parent.lo).to_u32().hash_stable(ctx, hasher); - (span.hi - parent.lo).to_u32().hash_stable(ctx, hasher); - return; - } - - // If this is not an empty or invalid span, we want to hash the last - // position that belongs to it, as opposed to hashing the first - // position past it. - let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span) - else { - Hash::hash(&TAG_INVALID_SPAN, hasher); - return; - }; - - if let Some(parent) = parent - && file.contains(parent.lo) - { - // This span is relative to another span in the same file, - // only hash the relative position. - Hash::hash(&TAG_RELATIVE_SPAN, hasher); - Hash::hash(&(span.lo.0.wrapping_sub(parent.lo.0)), hasher); - Hash::hash(&(span.hi.0.wrapping_sub(parent.lo.0)), hasher); - return; - } - - Hash::hash(&TAG_VALID_SPAN, hasher); - Hash::hash(&file.stable_id, hasher); - - // Hash both the length and the end location (line/column) of a span. If we - // hash only the length, for example, then two otherwise equal spans with - // different end locations will have the same hash. This can cause a problem - // during incremental compilation wherein a previous result for a query that - // depends on the end location of a span will be incorrectly reused when the - // end location of the span it depends on has changed (see issue #74890). A - // similar analysis applies if some query depends specifically on the length - // of the span, but we only hash the end location. So hash both. - - let col_lo_trunc = (col_lo.0 as u64) & 0xFF; - let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; - let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; - let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; - let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; - let len = (span.hi - span.lo).0; - Hash::hash(&col_line, hasher); - Hash::hash(&len, hasher); + // `span_hash_stable` does all the work. + ctx.span_hash_stable(*self, hasher) } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b80d624bc496..bf3d28a65440 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -157,6 +157,7 @@ symbols! { Abi, AcqRel, Acquire, + Alignment, Any, Arc, ArcWeak, @@ -211,6 +212,7 @@ symbols! { CoercePointeeValidated, CoerceUnsized, Command, + Const, ConstParamTy, ConstParamTy_, Context, @@ -234,6 +236,7 @@ symbols! { DynTrait, Encodable, Encoder, + Enum, Enumerate, Eq, Equal, @@ -292,6 +295,7 @@ symbols! { IteratorMap, Layout, Left, + Lifetime, LinkedList, LintDiagnostic, LintPass, @@ -372,8 +376,8 @@ symbols! { Stdin, Str, String, + Struct, StructuralPartialEq, - SubdiagMessage, Subdiagnostic, SymbolIntern, Sync, @@ -395,6 +399,8 @@ symbols! { Ty, TyCtxt, TyKind, + Type, + Union, Unknown, Unsize, UnsizedConstParamTy, @@ -577,6 +583,7 @@ symbols! { automatically_derived, available_externally, avr, + avr_target_feature, avx, avx10_target_feature, avx512_target_feature, @@ -642,6 +649,7 @@ symbols! { caller_location, capture_disjoint_fields, carrying_mul_add, + carryless_mul, catch_unwind, cause, cdylib, @@ -1002,6 +1010,7 @@ symbols! { explicit_tail_calls, export_name, export_stable, + export_symbols: "export-symbols", expr, expr_2021, expr_fragment_specifier_2024, @@ -1084,6 +1093,7 @@ symbols! { ffi_returns_twice, field, field_init_shorthand, + fields, file, file_options, flags, @@ -1139,6 +1149,7 @@ symbols! { from_output, from_residual, from_size_align_unchecked, + from_size_alignment_unchecked, from_str, from_str_method, from_str_nonconst, @@ -1172,6 +1183,7 @@ symbols! { generic_const_parameter_types, generic_param_attrs, generic_pattern_types, + generics, get_context, global_alloc_ty, global_allocator, @@ -1451,6 +1463,7 @@ symbols! { meta, meta_sized, metadata_type, + mgca_type_const_syntax, min_const_fn, min_const_generics, min_const_unsafe_fn, @@ -1626,6 +1639,7 @@ symbols! { on_const, on_unimplemented, opaque, + opaque_generic_const_args, opaque_module_name_placeholder: "", open_options_new, ops, @@ -1955,7 +1969,6 @@ symbols! { rustc_deprecated_safe_2024, rustc_diagnostic_item, rustc_diagnostic_macros, - rustc_dirty, rustc_do_not_const_check, rustc_doc_primitive, rustc_driver, @@ -1995,6 +2008,7 @@ symbols! { rustc_no_implicit_autorefs, rustc_no_implicit_bounds, rustc_no_mir_inline, + rustc_non_const_trait_method, rustc_nonnull_optimization_guaranteed, rustc_nounwind, rustc_objc_class, @@ -2082,6 +2096,7 @@ symbols! { simd_bitmask, simd_bitreverse, simd_bswap, + simd_carryless_mul, simd_cast, simd_cast_ptr, simd_ceil, @@ -2336,7 +2351,6 @@ symbols! { type_ascribe, type_ascription, type_changing_struct_update, - type_const, type_id, type_id_eq, type_info, @@ -2471,6 +2485,7 @@ symbols! { values, var, variant_count, + variants, vec, vec_as_mut_slice, vec_as_slice, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 7e126cb6a6e9..35a3d0dac8af 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,7 +88,7 @@ //! DefPaths which are much more robust in the face of changes to the code base. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] // tidy-alphabetical-end use rustc_hir::def::DefKind; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 50935e7caf33..8f842e030011 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,16 +4,14 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{GenericArgs, Instance, TyCtxt}; -use rustc_span::{Symbol, sym}; use crate::errors::{Kind, TestOutput}; -const SYMBOL_NAME: Symbol = sym::rustc_symbol_name; -const DEF_PATH: Symbol = sym::rustc_def_path; - pub fn report_symbol_names(tcx: TyCtxt<'_>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so @@ -54,7 +52,11 @@ impl SymbolNamesTest<'_> { // The formatting of `tag({})` is chosen so that tests can elect // to test the entirety of the string, if they choose, or else just // some subset. - for attr in tcx.get_attrs(def_id, SYMBOL_NAME) { + + if let Some(attr_span) = find_attr!( + tcx.get_all_attrs(def_id), + AttributeKind::RustcSymbolName(span) => span + ) { let def_id = def_id.to_def_id(); let instance = Instance::new_raw( def_id, @@ -62,27 +64,30 @@ impl SymbolNamesTest<'_> { ); let mangled = tcx.symbol_name(instance); tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::SymbolName, content: format!("{mangled}"), }); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::Demangling, content: format!("{demangling}"), }); tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::DemanglingAlt, content: format!("{demangling:#}"), }); } } - for attr in tcx.get_attrs(def_id, DEF_PATH) { + if let Some(attr_span) = find_attr!( + tcx.get_all_attrs(def_id), + AttributeKind::RustcDefPath(span) => span + ) { tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::DefPath, content: with_no_trimmed_paths!(tcx.def_path_str(def_id)), }); diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index fc732170dcb7..f55d03d89e8f 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -1,214 +1,203 @@ -// FIXME: This needs an audit for correctness and completeness. - use rustc_abi::{ - BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Scalar, Size, TyAbiInterface, - TyAndLayout, + Align, BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgAttribute, CastTarget, FnAbi, Uniform}; -use crate::spec::{Env, HasTargetSpec, Os}; +use crate::spec::{HasTargetSpec, Os}; -#[derive(Clone, Debug)] -struct Sdata { - pub prefix: [Option; 8], - pub prefix_index: usize, - pub last_offset: Size, - pub has_float: bool, - pub arg_attribute: ArgAttribute, +// NOTE: GCC and Clang/LLVM have disagreements that the ABI doesn't resolve, we match the +// Clang/LLVM behavior in these cases. + +#[derive(Copy, Clone)] +enum DoubleWord { + F64, + F128Start, + F128End, + Words([Word; 2]), } -fn arg_scalar(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata -where - C: HasDataLayout, -{ - let dl = cx.data_layout(); - - if !matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64)) { - return data; - } - - data.has_float = true; - - if !data.last_offset.is_aligned(dl.f64_align) && data.last_offset < offset { - if data.prefix_index == data.prefix.len() { - return data; - } - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i32().size; - } - - for _ in 0..((offset - data.last_offset).bits() / 64) - .min((data.prefix.len() - data.prefix_index) as u64) - { - data.prefix[data.prefix_index] = Some(Reg::i64()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i64().size; - } - - if data.last_offset < offset { - if data.prefix_index == data.prefix.len() { - return data; - } - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i32().size; - } - - if data.prefix_index == data.prefix.len() { - return data; - } - - if scalar.primitive() == Primitive::Float(Float::F32) { - data.arg_attribute = ArgAttribute::InReg; - data.prefix[data.prefix_index] = Some(Reg::f32()); - data.last_offset = offset + Reg::f32().size; - } else { - data.prefix[data.prefix_index] = Some(Reg::f64()); - data.last_offset = offset + Reg::f64().size; - } - data.prefix_index += 1; - data +#[derive(Copy, Clone)] +enum Word { + F32, + Integer, } -fn arg_scalar_pair( +fn classify<'a, Ty, C>( cx: &C, - scalar1: &Scalar, - scalar2: &Scalar, - mut offset: Size, - mut data: Sdata, -) -> Sdata -where - C: HasDataLayout, -{ - data = arg_scalar(cx, scalar1, offset, data); - match (scalar1.primitive(), scalar2.primitive()) { - (Primitive::Float(Float::F32), _) => offset += Reg::f32().size, - (_, Primitive::Float(Float::F64)) => offset += Reg::f64().size, - (Primitive::Int(i, _signed), _) => offset += i.size(), - (Primitive::Pointer(_), _) => offset += Reg::i64().size, - _ => {} - } - - if !offset.bytes().is_multiple_of(4) - && matches!(scalar2.primitive(), Primitive::Float(Float::F32 | Float::F64)) - { - offset += Size::from_bytes(4 - (offset.bytes() % 4)); - } - data = arg_scalar(cx, scalar2, offset, data); - data -} - -fn parse_structure<'a, Ty, C>( - cx: &C, - layout: TyAndLayout<'a, Ty>, - mut data: Sdata, - mut offset: Size, -) -> Sdata -where + arg_layout: &TyAndLayout<'a, Ty>, + offset: Size, + double_words: &mut [DoubleWord; 4], +) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if let FieldsShape::Union(_) = layout.fields { - return data; - } + // If this function does not update the `double_words` array, the value will be passed via + // integer registers. The array is initialized with `DoubleWord::Words([Word::Integer; 2])`. - match layout.backend_repr { - BackendRepr::Scalar(scalar) => { - data = arg_scalar(cx, &scalar, offset, data); - } - BackendRepr::Memory { .. } => { - for i in 0..layout.fields.count() { - if offset < layout.fields.offset(i) { - offset = layout.fields.offset(i); + match arg_layout.backend_repr { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(float) => { + if offset.is_aligned(Ord::min(*float.align(cx), Align::EIGHT)) { + let index = offset.bytes_usize() / 8; + match float { + Float::F128 => { + double_words[index] = DoubleWord::F128Start; + double_words[index + 1] = DoubleWord::F128End; + } + Float::F64 => { + double_words[index] = DoubleWord::F64; + } + Float::F32 => match &mut double_words[index] { + DoubleWord::Words(words) => { + words[(offset.bytes_usize() % 8) / 4] = Word::F32; + } + _ => unreachable!(), + }, + Float::F16 => { + // Match LLVM by passing `f16` in integer registers. + } + } + } else { + /* pass unaligned floats in integer registers */ } - data = parse_structure(cx, layout.field(cx, i), data.clone(), offset); } - } - _ => { - if let BackendRepr::ScalarPair(scalar1, scalar2) = &layout.backend_repr { - data = arg_scalar_pair(cx, scalar1, scalar2, offset, data); + Primitive::Int(_, _) | Primitive::Pointer(_) => { /* pass in integer registers */ } + }, + BackendRepr::SimdVector { .. } => {} + BackendRepr::ScalableVector { .. } => {} + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { + FieldsShape::Primitive => { + unreachable!("aggregates can't have `FieldsShape::Primitive`") } - } + FieldsShape::Union(_) => { + if !arg_layout.is_zst() { + if arg_layout.is_transparent() { + let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1; + classify(cx, &non_1zst_elem, offset, double_words); + } + } + } + FieldsShape::Array { .. } => {} + FieldsShape::Arbitrary { .. } => match arg_layout.variants { + Variants::Multiple { .. } => {} + Variants::Single { .. } | Variants::Empty => { + // Match Clang by ignoring whether a struct is packed and just considering + // whether individual fields are aligned. GCC currently uses only integer + // registers when passing packed structs. + for i in arg_layout.fields.index_by_increasing_offset() { + classify( + cx, + &arg_layout.field(cx, i), + offset + arg_layout.fields.offset(i), + double_words, + ); + } + } + }, + }, } - - data } -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) -where +fn classify_arg<'a, Ty, C>( + cx: &C, + arg: &mut ArgAbi<'a, Ty>, + in_registers_max: Size, + total_double_word_count: &mut usize, +) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { + // 64-bit SPARC allocates argument stack space in 64-bit chunks (double words), some of which + // are promoted to registers based on their position on the stack. + + // Keep track of the total number of double words used by arguments so far. This allows padding + // arguments to be inserted where necessary to ensure that 16-aligned arguments are passed in an + // aligned set of registers. + + let pad = !total_double_word_count.is_multiple_of(2) && arg.layout.align.abi.bytes() == 16; + // The number of double words used by this argument. + let double_word_count = arg.layout.size.bytes_usize().div_ceil(8); + // The number of double words before this argument, including any padding. + let start_double_word_count = *total_double_word_count + usize::from(pad); + if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { arg.make_indirect(); + *total_double_word_count += 1; return; } + if !arg.layout.is_aggregate() { arg.extend_integer_width_to(64); + *total_double_word_count = start_double_word_count + double_word_count; return; } let total = arg.layout.size; if total > in_registers_max { arg.make_indirect(); + *total_double_word_count += 1; return; } - match arg.layout.fields { - FieldsShape::Primitive => unreachable!(), - FieldsShape::Array { .. } => { - // Arrays are passed indirectly - arg.make_indirect(); - return; + *total_double_word_count = start_double_word_count + double_word_count; + + const ARGUMENT_REGISTERS: usize = 8; + + let mut double_words = [DoubleWord::Words([Word::Integer; 2]); ARGUMENT_REGISTERS / 2]; + classify(cx, &arg.layout, Size::ZERO, &mut double_words); + + let mut regs = [None; ARGUMENT_REGISTERS]; + let mut i = 0; + let mut push = |reg| { + regs[i] = Some(reg); + i += 1; + }; + let mut attrs = ArgAttribute::empty(); + + for (index, double_word) in double_words.into_iter().enumerate() { + if arg.layout.size.bytes_usize() <= index * 8 { + break; } - FieldsShape::Union(_) => { - // Unions and are always treated as a series of 64-bit integer chunks - } - FieldsShape::Arbitrary { .. } => { - // Structures with floating point numbers need special care. - - let mut data = parse_structure( - cx, - arg.layout, - Sdata { - prefix: [None; 8], - prefix_index: 0, - last_offset: Size::ZERO, - has_float: false, - arg_attribute: ArgAttribute::default(), - }, - Size::ZERO, - ); - - if data.has_float { - // Structure { float, int, int } doesn't like to be handled like - // { float, long int }. Other way around it doesn't mind. - if data.last_offset < arg.layout.size - && !data.last_offset.bytes().is_multiple_of(8) - && data.prefix_index < data.prefix.len() - { - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset += Reg::i32().size; + match double_word { + // `f128` must be aligned to be assigned a float register. + DoubleWord::F128Start if (start_double_word_count + index).is_multiple_of(2) => { + push(Reg::f128()); + } + DoubleWord::F128Start => { + // Clang currently handles this case nonsensically, always returning a packed + // `struct { long double x; }` in an aligned quad floating-point register even when + // the `long double` isn't aligned on the stack, which also makes all future + // arguments get passed in the wrong registers. This passes the `f128` in integer + // registers when it is unaligned, same as with `f32` and `f64`. + push(Reg::i64()); + push(Reg::i64()); + } + DoubleWord::F128End => {} // Already handled by `F128Start` + DoubleWord::F64 => push(Reg::f64()), + DoubleWord::Words([Word::Integer, Word::Integer]) => push(Reg::i64()), + DoubleWord::Words(words) => { + attrs |= ArgAttribute::InReg; + for word in words { + match word { + Word::F32 => push(Reg::f32()), + Word::Integer => push(Reg::i32()), + } } - - let mut rest_size = arg.layout.size - data.last_offset; - if !rest_size.bytes().is_multiple_of(8) && data.prefix_index < data.prefix.len() { - data.prefix[data.prefix_index] = Some(Reg::i32()); - rest_size = rest_size - Reg::i32().size; - } - - arg.cast_to( - CastTarget::prefixed(data.prefix, Uniform::new(Reg::i64(), rest_size)) - .with_attrs(data.arg_attribute.into()), - ); - return; } } } - arg.cast_to(Uniform::new(Reg::i64(), total)); + let cast_target = match regs { + [Some(reg), None, rest @ ..] => { + // Just a single register is needed for this value. + debug_assert!(rest.iter().all(|x| x.is_none())); + CastTarget::from(reg) + } + _ => CastTarget::prefixed(regs, Uniform::new(Reg::i8(), Size::ZERO)), + }; + + arg.cast_to_and_pad_i32(cast_target.with_attrs(attrs.into()), pad); } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) @@ -217,23 +206,26 @@ where C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() && fn_abi.ret.layout.is_sized() { - classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32)); + // A return value of 32 bytes or smaller is passed via registers. + classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32), &mut 0); } + // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + let passes_zsts = matches!(cx.target_spec().os, Os::Linux); + + let mut double_word_count = 0; for arg in fn_abi.args.iter_mut() { if !arg.layout.is_sized() { continue; } if arg.is_ignore() { - // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. - if cx.target_spec().os == Os::Linux - && matches!(cx.target_spec().env, Env::Gnu | Env::Musl | Env::Uclibc) - && arg.layout.is_zst() - { + if passes_zsts && arg.layout.is_zst() { arg.make_indirect_from_ignore(); + double_word_count += 1; } - return; + continue; } - classify_arg(cx, arg, Size::from_bytes(16)); + // An argument of 16 bytes or smaller is passed via registers. + classify_arg(cx, arg, Size::from_bytes(16), &mut double_word_count); } } diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 48f7700a86d5..4026c4f471a7 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -28,7 +28,7 @@ where BackendRepr::ScalableVector { .. } => panic!("scalable vectors are unsupported"), BackendRepr::Scalar(scalar) => { if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) { - if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) { + if cx.target_spec().rustc_abi == Some(RustcAbi::Softfloat) { // Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing. } else { // `i128` is returned in xmm0 by Clang and GCC diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index dfa1b2320718..1dc62cb3659c 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -76,7 +76,7 @@ macro_rules! target_spec_enum { pub enum $Name:ident { $( $( #[$variant_attr:meta] )* - $Variant:ident = $string:literal, + $Variant:ident = $string:literal $(,$alias:literal)* , )* } parse_error_type = $parse_error_type:literal; @@ -88,6 +88,7 @@ macro_rules! target_spec_enum { $( $( #[$variant_attr] )* #[serde(rename = $string)] // for JSON schema generation only + $( #[serde(alias = $alias)] )* $Variant, )* } @@ -97,7 +98,10 @@ macro_rules! target_spec_enum { fn from_str(s: &str) -> Result { Ok(match s { - $( $string => Self::$Variant, )* + $( + $string => Self::$Variant, + $($alias => Self::$Variant,)* + )* _ => { let all = [$( concat!("'", $string, "'") ),*].join(", "); return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type)); @@ -123,7 +127,7 @@ macro_rules! target_spec_enum { pub enum $Name:ident { $( $( #[$variant_attr:meta] )* - $Variant:ident = $string:literal, + $Variant:ident = $string:literal $(,$alias:literal)* , )* } $( #[$other_variant_attr:meta] )* @@ -134,6 +138,7 @@ macro_rules! target_spec_enum { pub enum $Name { $( $( #[$variant_attr:meta] )* + $( #[serde(alias = $alias)] )* $Variant, )* /// The vast majority of the time, the compiler deals with a fixed @@ -165,7 +170,10 @@ macro_rules! target_spec_enum { fn from_str(s: &str) -> Result { Ok(match s { - $( $string => Self::$Variant, )* + $( + $string => Self::$Variant, + $($alias => Self::$Variant,)* + )* _ => Self::$OtherVariant(s.to_owned().into()), }) } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 14e83cf3d2de..2d2f15651c43 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1005,8 +1005,8 @@ crate::target_spec_enum! { pub enum RustcAbi { /// On x86-32 only: make use of SSE and SSE2 for ABI purposes. X86Sse2 = "x86-sse2", - /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI. - X86Softfloat = "x86-softfloat", + /// On x86-32/64 and S390x: do not use any FPU or SIMD registers for the ABI. + Softfloat = "softfloat", "x86-softfloat", } parse_error_type = "rustc abi"; @@ -1082,7 +1082,7 @@ crate::target_spec_enum! { } crate::target_spec_enum! { - #[derive(Default)] + #[derive(Default, Encodable, Decodable)] pub enum SplitDebuginfo { /// Split debug-information is disabled, meaning that on supported platforms /// you can find all debug information in the executable itself. This is @@ -1460,6 +1460,7 @@ supported_targets! { ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl), ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu), + ("s390x-unknown-none-softfloat", s390x_unknown_none_softfloat), ("s390x-unknown-linux-musl", s390x_unknown_linux_musl), ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu), ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu), @@ -3204,10 +3205,10 @@ impl Target { Arch::X86, "`x86-sse2` ABI is only valid for x86-32 targets" ), - RustcAbi::X86Softfloat => check_matches!( + RustcAbi::Softfloat => check_matches!( self.arch, - Arch::X86 | Arch::X86_64, - "`x86-softfloat` ABI is only valid for x86 targets" + Arch::X86 | Arch::X86_64 | Arch::S390x, + "`softfloat` ABI is only valid for x86 and s390x targets" ), } } @@ -3363,6 +3364,9 @@ impl Target { Err(format!("could not find specification for target {target_tuple:?}")) } + TargetTuple::TargetJson { ref contents, .. } if !unstable_options => { + Err("custom targets are unstable and require `-Zunstable-options`".to_string()) + } TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents), } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index 0916864ac4cc..513a022adec1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple tvOS".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 2e18abdef399..0f48a36d5d77 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple tvOS Simulator".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index b771b3ff10b9..453809fb3bb3 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple visionOS".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index d4b4d94115b4..1aacb41ffeaa 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple visionOS simulator".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index 9f0a24ddd334..82c986a0f8fe 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple watchOS".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index fabf01d641c3..77b03c1de722 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target, metadata: TargetMetadata { description: Some("ARM64 Apple watchOS Simulator".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(true), }, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index d1810b6fa486..3b158c13521e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(128), // As documented in https://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. - features: "+v8a,+neon,+outline-atomics".into(), + features: "+v8a,+neon".into(), // the AAPCS64 expects use of non-leaf frame pointers per // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index db3cf83ddc99..ce17280b153d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, FramePointer, LinkerFlavor, Lld, Target, TargetMetad pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+outline-atomics".into(); + base.features = "+v8a,+neon".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "arm64pe"]); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index e9f7f51a7a35..0d06bec21f4a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+outline-atomics".into(); + base.features = "+v8a,+neon".into(); // Microsoft recommends enabling frame pointers on Arm64 Windows. // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 47775f968400..69a65e6b0f02 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a,+outline-atomics".into(), + features: "+v8a".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 8a07f98075a8..6489e2bda809 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -5,7 +5,7 @@ use crate::spec::{ pub(crate) fn target() -> Target { let mut base = base::fuchsia::opts(); base.cpu = "generic".into(); - base.features = "+v8a,+crc,+aes,+sha2,+neon,+outline-atomics".into(); + base.features = "+v8a,+crc,+aes,+sha2,+neon".into(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index 14a2f007f1e8..e5e40cb38b91 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a,+outline-atomics".into(), + features: "+v8a".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, ..base::openbsd::opts() diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs index 82811cda00ce..92c477f53f8f 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, Cc, LinkerFlavor, Target, TargetMetadata, base}; +use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -8,8 +8,8 @@ pub(crate) fn target() -> Target { base.features = "-small-data,+hvx-length128b".into(); base.has_rpath = true; - base.linker = Some("rust-lld".into()); - base.linker_flavor = LinkerFlavor::Unix(Cc::Yes); + base.linker = Some("hexagon-unknown-linux-musl-clang".into()); + base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::No); base.c_enum_min_bits = Some(8); diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs index 55ec3697a15e..3809057e255c 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs @@ -1,4 +1,6 @@ -use crate::spec::{Arch, PanicStrategy, Target, TargetMetadata, TargetOptions}; +use crate::spec::{ + Arch, Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata, TargetOptions, +}; pub(crate) fn target() -> Target { Target { @@ -28,6 +30,7 @@ pub(crate) fn target() -> Target { emit_debug_gdb_scripts: false, c_enum_min_bits: Some(8), linker: Some("rust-lld".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs index 746e0cb11dcb..dcc92b4bdcc4 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs @@ -24,8 +24,8 @@ pub(crate) fn target() -> Target { os: Os::Qurt, vendor: "unknown".into(), cpu: "hexagonv69".into(), - linker: Some("rust-lld".into()), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("hexagon-clang".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), exe_suffix: ".elf".into(), dynamic_linking: true, executables: true, diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index 37b202097b46..7696edd5ba71 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -22,7 +22,7 @@ pub(crate) fn target() -> Target { // If you initialize FP units yourself, you can override these flags with custom linker // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".into(); - base.rustc_abi = Some(RustcAbi::X86Softfloat); + base.rustc_abi = Some(RustcAbi::Softfloat); // Turn off DWARF. This fixes an lld warning, "section name .debug_frame is longer than 8 // characters and will use a non-standard string table". That section will not be created if diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs new file mode 100644 index 000000000000..7d42c1fd9244 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs @@ -0,0 +1,39 @@ +use rustc_abi::{Align, Endian}; + +use crate::spec::{ + Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet, + StackProbeType, Target, TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + abi: Abi::SoftFloat, + cpu: "z10".into(), + endian: Endian::Big, + features: "+soft-float,-vector".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + max_atomic_width: Some(128), + min_global_align: Some(Align::from_bits(16).unwrap()), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + rustc_abi: Some(RustcAbi::Softfloat), + stack_probes: StackProbeType::Inline, + supported_sanitizers: SanitizerSet::KERNELADDRESS, + ..Default::default() + }; + + Target { + llvm_target: "s390x-unknown-linux-gnu".into(), + metadata: TargetMetadata { + description: Some("S390x Linux".into()), + host_tools: Some(false), + std: Some(false), + tier: Some(2), + }, + arch: Arch::S390x, + data_layout: "E-S64-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(), + options: opts, + pointer_width: 64, + } +} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index fb735b54dd82..4b6f5b655760 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -19,8 +19,15 @@ pub(crate) fn target() -> Target { pre_link_args, post_link_args, relocation_model: RelocModel::Pic, + // crt_static should always be true for an executable and always false + // for a shared library. There is no easy way to indicate this and it + // doesn't seem to matter much so we set crt_static_allows_dylibs to + // true and leave crt_static as true when linking dynamic libraries. + // wasi also sets crt_static_allows_dylibs: true so this is at least + // aligned between wasm targets. crt_static_respected: true, crt_static_default: true, + crt_static_allows_dylibs: true, panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, families: cvs!["unix", "wasm"], diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index 520a59d6a6f6..0afe7a0b68b0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { relro_level: RelroLevel::Full, linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - rustc_abi: Some(RustcAbi::X86Softfloat), + rustc_abi: Some(RustcAbi::Softfloat), features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(), supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, disable_redzone: true, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 8a494d0e56dd..333e20bd0ac1 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -27,7 +27,7 @@ pub(crate) fn target() -> Target { // If you initialize FP units yourself, you can override these flags with custom linker // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".into(); - base.rustc_abi = Some(RustcAbi::X86Softfloat); + base.rustc_abi = Some(RustcAbi::Softfloat); Target { llvm_target: "x86_64-unknown-windows".into(), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index bc12e1eb9737..f17927484648 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -863,7 +863,7 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("miscellaneous-extensions-3", Stable, &[]), ("miscellaneous-extensions-4", Stable, &[]), ("nnp-assist", Stable, &["vector"]), - ("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]), + ("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]), ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), ("vector", Stable, &[]), ("vector-enhancements-1", Stable, &["vector"]), @@ -898,6 +898,28 @@ static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("addsubiw", Unstable(sym::avr_target_feature), &[]), + ("break", Unstable(sym::avr_target_feature), &[]), + ("eijmpcall", Unstable(sym::avr_target_feature), &[]), + ("elpm", Unstable(sym::avr_target_feature), &[]), + ("elpmx", Unstable(sym::avr_target_feature), &[]), + ("ijmpcall", Unstable(sym::avr_target_feature), &[]), + ("jmpcall", Unstable(sym::avr_target_feature), &[]), + ("lowbytefirst", Unstable(sym::avr_target_feature), &[]), + ("lpm", Unstable(sym::avr_target_feature), &[]), + ("lpmx", Unstable(sym::avr_target_feature), &[]), + ("movw", Unstable(sym::avr_target_feature), &[]), + ("mul", Unstable(sym::avr_target_feature), &[]), + ("rmw", Unstable(sym::avr_target_feature), &[]), + ("spm", Unstable(sym::avr_target_feature), &[]), + ("spmx", Unstable(sym::avr_target_feature), &[]), + ("sram", Forbidden { reason: "devices that have no SRAM are unsupported" }, &[]), + ("tinyencoding", Unstable(sym::avr_target_feature), &[]), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -919,6 +941,7 @@ pub fn all_rust_features() -> impl Iterator { .chain(IBMZ_FEATURES) .chain(SPARC_FEATURES) .chain(M68K_FEATURES) + .chain(AVR_FEATURES) .cloned() .map(|(f, s, _)| (f, s)) } @@ -961,8 +984,11 @@ const RISCV_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'stat const SPARC_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/]; -const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = - &[(512, "hvx-length64b"), (1024, "hvx-length128b")]; +const HEXAGON_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[ + (512, "hvx-length64b"), // HvxVector in 64-byte mode + (1024, "hvx-length128b"), // HvxVector in 128-byte mode, or HvxVectorPair in 64-byte mode + (2048, "hvx-length128b"), // HvxVectorPair in 128-byte mode +]; const MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")]; const CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] = @@ -996,12 +1022,8 @@ impl Target { Arch::S390x => IBMZ_FEATURES, Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES, Arch::M68k => M68K_FEATURES, - Arch::AmdGpu - | Arch::Avr - | Arch::Msp430 - | Arch::SpirV - | Arch::Xtensa - | Arch::Other(_) => &[], + Arch::Avr => AVR_FEATURES, + Arch::AmdGpu | Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[], } } @@ -1023,11 +1045,11 @@ impl Target { MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI } Arch::AmdGpu => AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI, - Arch::Nvptx64 | Arch::Bpf | Arch::M68k => &[], // no vector ABI + Arch::Nvptx64 | Arch::Bpf | Arch::M68k | Arch::Avr => &[], // no vector ABI Arch::CSky => CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI, // FIXME: for some tier3 targets, we are overly cautious and always give warnings // when passing args in vector registers. - Arch::Avr | Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[], + Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[], } } @@ -1098,7 +1120,7 @@ impl Target { incompatible: &["soft-float"], } } - Some(RustcAbi::X86Softfloat) => { + Some(RustcAbi::Softfloat) => { // Softfloat ABI, requires corresponding target feature. That feature trumps // `x87` and all other FPU features so those do not matter. // Note that this one requirement is the entire implementation of the ABI! @@ -1118,7 +1140,7 @@ impl Target { incompatible: &["soft-float"], } } - Some(RustcAbi::X86Softfloat) => { + Some(RustcAbi::Softfloat) => { // Softfloat ABI, requires corresponding target feature. That feature trumps // `x87` and all other FPU features so those do not matter. // Note that this one requirement is the entire implementation of the ABI! @@ -1218,11 +1240,33 @@ impl Target { } } Arch::S390x => { - // We don't currently support a softfloat target on this architecture. - // As usual, we have to reject swapping the `soft-float` target feature. - // The "vector" target feature does not affect the ABI for floats - // because the vector and float registers overlap. - FeatureConstraints { required: &[], incompatible: &["soft-float"] } + // Same as x86, We use our own ABI indicator here; + // LLVM does not have anything native and will switch ABI based + // on the soft-float target feature. + // Every case should require or forbid `soft-float`! + // The "vector" target feature may only be used without soft-float + // because the float and vector registers overlap and the + // standard s390x C ABI may pass vectors via these registers. + match self.rustc_abi { + None => { + // Default hardfloat ABI. + FeatureConstraints { required: &[], incompatible: &["soft-float"] } + } + Some(RustcAbi::Softfloat) => { + // Softfloat ABI, requires corresponding target feature. + // llvm will switch to soft-float ABI just based on this feature. + FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] } + } + Some(r) => { + panic!("invalid Rust ABI for s390x: {r:?}"); + } + } + } + Arch::Avr => { + // SRAM is minimum requirement for C/C++ in both avr-gcc and Clang, + // and backends of them only support assembly for devices have no SRAM. + // See the discussion in https://github.com/rust-lang/rust/pull/146900 for more. + FeatureConstraints { required: &["sram"], incompatible: &[] } } _ => NOTHING, } diff --git a/compiler/rustc_thread_pool/src/sleep/README.md b/compiler/rustc_thread_pool/src/sleep/README.md index 1e11da55f4a4..948c2922a434 100644 --- a/compiler/rustc_thread_pool/src/sleep/README.md +++ b/compiler/rustc_thread_pool/src/sleep/README.md @@ -32,7 +32,7 @@ There are three main thread states: waiting to be awoken. We sometimes refer to the final two states collectively as **inactive**. -Threads begin as idle but transition to idle and finally sleeping when +Threads begin as active but transition to idle and finally sleeping when they're unable to find work to do. ## Sleepy threads @@ -160,7 +160,7 @@ not complete. It is possible -- if unlikely -- that enough activity occurs for Thread A to observe the same JEC value that it saw when getting sleepy. If the new work being published came from *inside* the thread-pool, then this race condition isn't too harmful. It means that we have fewer workers processing the -work then we should, but we won't deadlock. This seems like an acceptable risk +work than we should, but we won't deadlock. This seems like an acceptable risk given that this is unlikely in practice. However, if the work was posted as an *external* job, that is a problem. In that diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d1..cd61a8f65473 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl deleted file mode 100644 index fcb250250871..000000000000 --- a/compiler/rustc_trait_selection/messages.ftl +++ /dev/null @@ -1,470 +0,0 @@ -trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} - -trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}` - -trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` -trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` -trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_adjust_signature_remove_borrow = consider adjusting the signature so it does not borrow its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds - -trait_selection_await_both_futures = consider `await`ing on both `Future`s -trait_selection_await_future = consider `await`ing on the `Future` -trait_selection_await_note = calling an async function returns a future - -trait_selection_but_calling_introduces = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$lifetime_kind -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement - .label1 = {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - } - .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [true] `impl` of `{$impl_path}` - *[false] inherent `impl` - } - -trait_selection_but_needs_to_satisfy = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but it needs to satisfy a `'static` lifetime requirement - .influencer = this data with {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - }... - .require = {$spans_empty -> - *[true] ...is used and required to live as long as `'static` here - [false] ...and is required to live as long as `'static` here - } - .used_here = ...is used here... - .introduced_by_bound = `'static` lifetime requirement introduced by this bound - -trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here - -trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment - -trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}` - .label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}` - -trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here - -trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait -trait_selection_consider_specifying_length = consider specifying the actual array length -trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment - -trait_selection_data_flows = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} flows{$label_var2_exists -> - [true] {" "}into `{$label_var2}` - *[false] {""} -} here - -trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here -trait_selection_data_returned = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} is returned here - -trait_selection_declared_different = this parameter and the return type are declared with different lifetimes... -trait_selection_declared_multiple = this type is declared with multiple lifetimes... -trait_selection_disallowed_positional_argument = positional format arguments are not allowed here - .help = only named format arguments with the name of one of the generic types are allowed in this context - -trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` -trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement -trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement -trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement -trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement - -trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` - -trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type - -trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` - .label = lifetime `{$named}` required - -trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type - .label = lifetime `{$named}` required - -trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}` - -trait_selection_fn_consider_casting_both = consider casting both fn items to fn pointers using `as {$sig}` - -trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same -trait_selection_fps_cast = consider casting to a fn pointer -trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}` - -trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers -trait_selection_fps_remove_ref = consider removing the reference -trait_selection_fps_use_ref = consider using a reference -trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime - -trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}` - .other_label = `{$option_name}` is first declared here - .label = `{$option_name}` is already declared here - -trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement -trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}` - -trait_selection_invalid_format_specifier = invalid format specifier - .help = no format specifier are supported in this position - -trait_selection_label_bad = {$bad_kind -> - *[other] cannot infer type - [more_info] cannot infer {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] the value of const parameter - [const] the value of the constant - } `{$name}`{$has_parent -> - [true] {" "}declared on the {$parent_prefix} `{$parent_name}` - *[false] {""} - } -} - -trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied -trait_selection_lifetime_mismatch = lifetime mismatch - -trait_selection_lifetime_param_suggestion = consider {$is_reuse -> - [true] reusing - *[false] introducing -} a named lifetime parameter{$is_impl -> - [true] {" "}and update trait if needed - *[false] {""} -} -trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime - -trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute - .help = only `message`, `note` and `label` are allowed as options - .label = invalid option found here - -trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b` -trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes -trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes -trait_selection_mismatched_static_lifetime = incompatible lifetime on type -trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute - .help = at least one of the `message`, `note` and `label` options are expected - -trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement -trait_selection_msl_unmet_req = because this has an unmet lifetime requirement - -trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> - [none] {""} - *[default] {" "}for type `{$self_desc}` - }: - .negative_implementation_here = negative implementation here - .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}` - .positive_implementation_here = positive implementation here - .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` - -trait_selection_nothing = {""} - -trait_selection_oc_cant_coerce_force_inline = - cannot coerce functions which must be inlined to function pointers -trait_selection_oc_cant_coerce_intrinsic = cannot coerce intrinsics to function pointers -trait_selection_oc_closure_selfref = closure/coroutine type that references itself -trait_selection_oc_const_compat = const not compatible with trait -trait_selection_oc_fn_lang_correct_type = {$lang_item_name -> - [panic_impl] `#[panic_handler]` - *[lang_item_name] lang item `{$lang_item_name}` - } function has wrong type -trait_selection_oc_fn_main_correct_type = `main` function has wrong type -trait_selection_oc_generic = mismatched types - -trait_selection_oc_if_else_different = `if` and `else` have incompatible types -trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type -trait_selection_oc_match_compat = `match` arms have incompatible types -trait_selection_oc_method_compat = method not compatible with trait -trait_selection_oc_method_correct_type = mismatched `self` parameter type -trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge -trait_selection_oc_no_else = `if` may be missing an `else` clause -trait_selection_oc_try_compat = `?` operator has incompatible types -trait_selection_oc_type_compat = type not compatible with trait - -trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds - .label = opaque type defined here -trait_selection_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$arg}` - .label = {STREQ($arg, "'static") -> - [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type - *[other] this generic parameter must be used with a generic {$kind} parameter - } - -trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type -trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content... - -trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it -trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}` - -trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate - -trait_selection_precise_capturing_overcaptures = use the precise capturing `use<...>` syntax to make the captures explicit - -trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here... -trait_selection_prlf_defined_without_sub = the lifetime defined here... -trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 for more information) - -trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here -trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here -trait_selection_reborrow = ...so that reference does not outlive borrowed content -trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references - -trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at -trait_selection_region_explanation = {$pref_kind -> - *[should_not_happen] [{$pref_kind}] - [ref_valid_for] ...the reference is valid for - [content_valid_for] ...but the borrowed content is only valid for - [type_obj_valid_for] object type is valid for - [source_pointer_valid_for] source pointer is only valid for - [type_satisfy] type must satisfy - [type_outlive] type must outlive - [lf_param_instantiated_with] lifetime parameter instantiated with - [lf_param_must_outlive] but lifetime parameter must outlive - [lf_instantiated_with] lifetime instantiated with - [lf_must_outlive] but lifetime must outlive - [pointer_valid_for] the pointer is valid for - [data_valid_for] but the referenced data is only valid for - [empty] {""} -}{$pref_kind -> - [empty] {""} - *[other] {" "} -}{$desc_kind -> - *[should_not_happen] [{$desc_kind}] - [restatic] the static lifetime - [revar] lifetime {$desc_arg} - [as_defined] the lifetime `{$desc_arg}` as defined here - [as_defined_anon] the anonymous lifetime as defined here - [defined_here] the anonymous lifetime defined here - [defined_here_reg] the lifetime `{$desc_arg}` as defined here -}{$suff_kind -> - *[should_not_happen] [{$suff_kind}] - [empty]{""} - [continues] ... - [req_by_binding] {" "}as required by this binding -} - -trait_selection_relate_object_bound = ...so that it can be closed over into an object -trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> - [true] ... - *[false] {""} -} -trait_selection_relate_param_bound_2 = ...that is required by this bound -trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied -trait_selection_ril_because_of = because of this returned expression -trait_selection_ril_introduced_by = requirement introduced by this return type -trait_selection_ril_introduced_here = `'static` requirement introduced here -trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type - -trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]` - .label = empty `on`-clause here -trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause - .label = expected an identifier here, not `{$path}` -trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)` - .label = unexpected quantity of predicates here -trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause - .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` -trait_selection_rustc_on_unimplemented_invalid_name = invalid name in `on`-clause - .label = expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}` -trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid - .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` -trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value - .label = expected value here - .note = e.g. `#[rustc_on_unimplemented(message="foo")]` -trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported - .label = unexpected literal here - -trait_selection_source_kind_closure_return = - try giving this closure an explicit return type - -# coroutine_kind may need to be translated -trait_selection_source_kind_fully_qualified = - try using a fully qualified path to specify the expected types - -trait_selection_source_kind_subdiag_generic_label = - cannot infer {$is_type -> - [true] type - *[false] the value - } of the {$is_type -> - [true] type - *[false] const - } {$parent_exists -> - [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` - *[false] parameter {$param_name} - } - -trait_selection_source_kind_subdiag_generic_suggestion = - consider specifying the generic {$arg_count -> - [one] argument - *[other] arguments - } - -trait_selection_source_kind_subdiag_let = {$kind -> - [with_pattern] consider giving `{$name}` an explicit type - [closure] consider giving this closure parameter an explicit type - *[other] consider giving this pattern a type -}{$x_kind -> - [has_name] , where the {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] value of const parameter - [const] value of the constant - } `{$arg_name}` is specified - [underscore] , where the placeholders `_` are specified - *[empty] {""} -} - -trait_selection_srs_add = consider returning the local binding `{$ident}` -trait_selection_srs_add_one = consider returning one of these bindings - -trait_selection_srs_remove = consider removing this semicolon -trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions -trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}` - -trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}` -trait_selection_subtype = ...so that the {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` 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 -} -trait_selection_subtype_2 = ...so that {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` 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 -} - -trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}` - -trait_selection_suggest_add_let_for_letchains = consider adding `let` - -trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait -trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - -trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one - -trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature - .found = found `{$found}` - .expected = expected `{$expected}` - .expected_found = expected signature `{$expected}` - {" "}found signature `{$found}` - -trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough - .label_satisfy = doesn't satisfy where-clause - .label_where = due to a where-clause on `{$def_id}`... - .label_dup = implementation of `{$trait_def_id}` is not general enough - -trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}` - -trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element - -trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead -trait_selection_type_annotations_needed = {$source_kind -> - [closure] type annotations needed for the closure `{$source_name}` - [normal] type annotations needed for `{$source_name}` - *[other] type annotations needed -} - .label = type must be known at this point - -trait_selection_types_declared_different = these two types are declared with different lifetimes... - -trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} - -trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` - .help = expect either a generic argument name or {"`{Self}`"} as format argument - -trait_selection_warn_removing_apit_params_for_overcapture = you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable - -trait_selection_warn_removing_apit_params_for_undercapture = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable - -trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait - -trait_selection_where_remove = remove the `where` clause -trait_selection_wrapped_parser_error = {$description} - .label = {$label} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 47810e2578df..2b2f9a07890f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -58,6 +58,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; @@ -72,12 +73,17 @@ use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, sym}; use tracing::{debug, instrument}; use crate::error_reporting::TypeErrCtxt; +use crate::error_reporting::traits::ambiguity::{ + CandidateSource, compute_applicable_impls_for_diagnostics, +}; use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags}; use crate::infer; use crate::infer::relate::{self, RelateResult, TypeRelation}; use crate::infer::{InferCtxt, InferCtxtExt as _, TypeTrace, ValuePairs}; use crate::solve::deeply_normalize_for_diagnostics; -use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode}; +use crate::traits::{ + MatchExpressionArmCause, Obligation, ObligationCause, ObligationCauseCode, specialization_graph, +}; mod note_and_explain; mod suggest; @@ -149,11 +155,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { actual: Ty<'tcx>, err: TypeError<'tcx>, ) -> Diag<'a> { - self.report_and_explain_type_error( + let mut diag = self.report_and_explain_type_error( TypeTrace::types(cause, expected, actual), param_env, err, - ) + ); + + self.suggest_param_env_shadowing(&mut diag, expected, actual, param_env); + + diag } pub fn report_mismatched_consts( @@ -240,6 +250,76 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { false } + fn suggest_param_env_shadowing( + &self, + diag: &mut Diag<'_>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) { + let (alias, concrete) = match (expected.kind(), found.kind()) { + (ty::Alias(ty::Projection, proj), _) => (proj, found), + (_, ty::Alias(ty::Projection, proj)) => (proj, expected), + _ => return, + }; + + let tcx = self.tcx; + + let trait_ref = alias.trait_ref(tcx); + let obligation = + Obligation::new(tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(trait_ref)); + + let applicable_impls = compute_applicable_impls_for_diagnostics(self.infcx, &obligation); + + for candidate in applicable_impls { + let impl_def_id = match candidate { + CandidateSource::DefId(did) => did, + CandidateSource::ParamEnv(_) => continue, + }; + + let is_shadowed = self.infcx.probe(|_| { + let impl_substs = self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_substs); + + let expected_trait_ref = alias.trait_ref(tcx); + + if let Err(_) = self.infcx.at(&ObligationCause::dummy(), param_env).eq( + DefineOpaqueTypes::No, + expected_trait_ref, + impl_trait_ref, + ) { + return false; + } + + let leaf_def = match specialization_graph::assoc_def(tcx, impl_def_id, alias.def_id) + { + Ok(leaf) => leaf, + Err(_) => return false, + }; + + let trait_def_id = alias.trait_def_id(tcx); + let rebased_args = alias.args.rebase_onto(tcx, trait_def_id, impl_substs); + + let impl_item_def_id = leaf_def.item.def_id; + let impl_assoc_ty = tcx.type_of(impl_item_def_id).instantiate(tcx, rebased_args); + + self.infcx.can_eq(param_env, impl_assoc_ty, concrete) + }); + + if is_shadowed { + diag.note(format!( + "the associated type `{}` is defined as `{}` in the implementation, \ + but the where-bound `{}` shadows this definition\n\ + see issue #152409 for more information", + self.ty_to_string(tcx.mk_ty_from_kind(ty::Alias(ty::Projection, *alias))), + self.ty_to_string(concrete), + self.ty_to_string(alias.self_ty()) + )); + return; + } + } + } + fn note_error_origin( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e3c8bfe4a452..80e97d36c23f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -12,7 +12,7 @@ use rustc_hir::{ }; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind, @@ -615,7 +615,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // first adjustment was not a builtin deref. let adjustment = match typeck_results.expr_adjustments(receiver) { [ - Adjustment { kind: Adjust::Deref(None), target: _ }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ }, .., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ }, ] => "", @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(segment, ..) => { if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) { let generics = tcx.generics_of(def_id); - let insertable: Option<_> = try { + let insertable = try { if generics.has_impl_trait() { None? } @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // // FIXME: We deal with that one separately for now, // would be good to remove this special case. - let last_segment_using_path_data: Option<_> = try { + let last_segment_using_path_data = try { let generics_def_id = tcx.res_generics_def_id(path.res)?; let generics = tcx.generics_of(generics_def_id); if generics.has_impl_trait() { @@ -1117,19 +1117,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { }; let generics = tcx.generics_of(def_id); - let segment: Option<_> = try { - if !segment.infer_args || generics.has_impl_trait() { - do yeet (); - } + let segment = if !segment.infer_args || generics.has_impl_trait() { + None + } else { let span = tcx.hir_span(segment.hir_id); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); - InsertableGenericArgs { + Some(InsertableGenericArgs { insert_span, args, generics_def_id: def_id, def_id, have_turbofish: false, - } + }) }; let parent_def_id = generics.parent.unwrap(); @@ -1263,7 +1262,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .iter() .position(|&arg| self.generic_arg_contains_target(arg)) { - if generics.parent.is_none() && generics.has_self { + if generics.has_own_self() { argument_index += 1; } let args = self.tecx.resolve_vars_if_possible(args); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 8fe4ffebd865..7d061e65df80 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -190,8 +190,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { } Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)) => { - debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); - debug!("id={:?}", id); + debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {debruijn_index:?}"); + debug!("id={id:?}"); if debruijn_index == self.current_index && id.to_def_id() == self.region_def_id { return ControlFlow::Break(()); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index 3bab09bc587f..05a1e3fe95dd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -34,14 +34,18 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { (Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id))) } ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }; let (sup_span, sup_symbol) = match *sup_name { ty::BoundRegionKind::Named(def_id) => { (Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id))) } ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }; 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_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 3ee6e6b739c0..3ed1f7c3481f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -239,14 +239,14 @@ pub fn suggest_new_region_bound( }; spans_suggs.push((fn_return.span.shrink_to_hi(), format!(" + {name} "))); err.multipart_suggestion_verbose( - format!("{declare} `{ty}` {captures}, {use_lt}",), + format!("{declare} `{ty}` {captures}, {use_lt}"), spans_suggs, Applicability::MaybeIncorrect, ); } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - format!("{declare} `{ty}` {captures}, {explicit}",), + format!("{declare} `{ty}` {captures}, {explicit}"), &plus_lt, Applicability::MaybeIncorrect, ); @@ -257,7 +257,7 @@ pub fn suggest_new_region_bound( if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - format!("{declare} the trait object {captures}, {explicit}",), + format!("{declare} the trait object {captures}, {explicit}"), &plus_lt, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 2a3268d3339e..5a8dd0364bee 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -16,7 +16,7 @@ use tracing::debug; use crate::error_reporting::infer::nice_region_error::NiceRegionError; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; -use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; +use crate::errors::{ConsiderBorrowingParamHelp, TraitImplDiff}; use crate::infer::{RegionResolutionError, ValuePairs}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -117,7 +117,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { trait_sp, note: (), param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() }, - rel_help: visitor.types.is_empty().then_some(RelationshipHelp), + rel_help: visitor.types.is_empty(), expected, found, }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index fdaf2d619dd5..fa30ef3af7e1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err, + Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, msg, struct_span_code_err, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -25,7 +25,6 @@ use crate::errors::{ self, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, note_and_explain, }; -use crate::fluent_generated as fluent; use crate::infer::region_constraints::GenericKind; use crate::infer::{ BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin, @@ -228,18 +227,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), - SubregionOrigin::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow } - .add_to_diag(err) + SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain { + span, + msg: msg!("...so that reference does not outlive borrowed content"), } + .add_to_diag(err), SubregionOrigin::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound } - .add_to_diag(err); + RegionOriginNote::Plain { + span, + msg: msg!("...so that it can be closed over into an object"), + } + .add_to_diag(err); } SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_reference_outlives_referent, + msg: msg!("...so that the reference type `{$name}` does not outlive the data it points at"), name: &self.ty_to_string(ty), continues: false, } @@ -248,7 +251,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_relate_param_bound, + msg: msg!( + "...so that the type `{$name}` will meet its required lifetime bounds{$continues -> + [true] ... + *[false] {\"\"} + }" + ), name: &self.ty_to_string(ty), continues: opt_span.is_some(), } @@ -256,7 +264,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(span) = opt_span { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_param_bound_2, + msg: msg!("...that is required by this bound"), } .add_to_diag(err); } @@ -264,14 +272,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_region_param_bound, + msg: msg!("...so that the declared lifetime parameter bounds are satisfied"), } .add_to_diag(err); } SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_compare_impl_item_obligation, + msg: msg!( + "...so that the definition in impl matches the definition from the trait" + ), } .add_to_diag(err); } @@ -279,11 +289,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_region_origin(err, parent); } SubregionOrigin::AscribeUserTypeProvePredicate(span) => { - RegionOriginNote::Plain { - span, - msg: fluent::trait_selection_ascribe_user_type_prove_predicate, - } - .add_to_diag(err); + RegionOriginNote::Plain { span, msg: msg!("...so that the where clause holds") } + .add_to_diag(err); } } } @@ -1009,7 +1016,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some((sup_expected, sup_found)) = self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path()) && let Some((sub_expected, sub_found)) = - self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path()) + self.values_str(sub_trace.values, &sub_trace.cause, err.long_ty_path()) && sub_expected == sup_expected && sub_found == sup_found { @@ -1052,7 +1059,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } fn report_inference_failure(&self, var_origin: RegionVariableOrigin<'tcx>) -> Diag<'_> { - let br_string = |br: ty::BoundRegionKind| { + let br_string = |br: ty::BoundRegionKind<'tcx>| { let mut s = match br { ty::BoundRegionKind::Named(def_id) => self.tcx.item_name(def_id).to_string(), _ => String::new(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index eb72f71382ef..16c4ac68cdf0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -710,7 +710,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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"),) + format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::>().join("\n")) } else if post.len() == 1 { format!(": `{}`", post[0]) } else { @@ -722,7 +722,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.note(format!("cannot satisfy `{predicate}`")); } (0, _, 1) => { - err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,)); + err.note(format!("{msg} in the `{}` crate{post}", crates[0])); } (0, _, _) => { err.note(format!( @@ -739,7 +739,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (_, 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,)); + err.note(format!("and another `impl` found in the `{}` crate{post}", crates[0])); } _ => { let span: MultiSpan = spans.into(); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6872d038fb7f..d9c6d339328a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, + Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg, pluralize, struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -277,6 +277,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg); + + let trait_def_id = main_trait_predicate.def_id(); + if self.tcx.is_diagnostic_item(sym::From, trait_def_id) + || self.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) + { + let found_ty = leaf_trait_predicate.skip_binder().trait_ref.args.type_at(1); + let ty = main_trait_predicate.skip_binder().self_ty(); + if let Some(cast_ty) = self.find_explicit_cast_type( + obligation.param_env, + found_ty, + ty, + ) { + let found_ty_str = self.tcx.short_string(found_ty, &mut long_ty_file); + let cast_ty_str = self.tcx.short_string(cast_ty, &mut long_ty_file); + err.help( + format!( + "consider casting the `{found_ty_str}` value to `{cast_ty_str}`", + ), + ); + } + } + *err.long_ty_path() = long_ty_file; let mut suggested = false; @@ -1607,6 +1629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some(lhs) = lhs.to_alias_term() + && let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = lhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = derive_better_type_error(lhs, rhs) { @@ -1615,6 +1638,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { better_type_err, ) } else if let Some(rhs) = rhs.to_alias_term() + && let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = rhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = derive_better_type_error(rhs, lhs) { @@ -2239,7 +2263,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.highlighted_span_help( self.tcx.def_span(def_id), vec![ - StringPart::normal(format!("the trait `{trait_}` ",)), + StringPart::normal(format!("the trait `{trait_}` ")), StringPart::highlighted("is"), StringPart::normal(desc), StringPart::highlighted(self_ty), @@ -2930,6 +2954,69 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + /// If `found_ty` is a reference that can be explicitly cast to another reference type for which + /// a `From` / `TryFrom` impl exists for `self_ty`, return that type. + fn find_explicit_cast_type( + &self, + param_env: ty::ParamEnv<'tcx>, + found_ty: Ty<'tcx>, + self_ty: Ty<'tcx>, + ) -> Option> { + let ty::Ref(region, inner_ty, mutbl) = *found_ty.kind() else { + return None; + }; + + let mut derefs = (self.autoderef_steps)(inner_ty).into_iter(); + derefs.next(); // skip the first one, which is inner_ty itself + let deref_target = derefs.into_iter().next()?.0; + + let cast_ty = Ty::new_ref(self.tcx, region, deref_target, mutbl); + + let Some(from_def_id) = self.tcx.get_diagnostic_item(sym::From) else { + return None; + }; + let Some(try_from_def_id) = self.tcx.get_diagnostic_item(sym::TryFrom) else { + return None; + }; + + if self.has_impl_for_type( + param_env, + ty::TraitRef::new( + self.tcx, + from_def_id, + self.tcx.mk_args(&[self_ty.into(), cast_ty.into()]), + ), + ) { + Some(cast_ty) + } else if self.has_impl_for_type( + param_env, + ty::TraitRef::new( + self.tcx, + try_from_def_id, + self.tcx.mk_args(&[self_ty.into(), cast_ty.into()]), + ), + ) { + Some(cast_ty) + } else { + None + } + } + + fn has_impl_for_type( + &self, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + ) -> bool { + let obligation = Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive }, + ); + + self.predicate_must_hold_modulo_regions(&obligation) + } + fn add_tuple_trait_message( &self, obligation_cause_code: &ObligationCauseCode<'tcx>, @@ -3001,7 +3088,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { err.span_help( self.tcx.def_span(trait_def_id), - crate::fluent_generated::trait_selection_trait_has_no_impls, + msg!("this trait has no implementations, consider adding one"), ); } else if !suggested && trait_predicate.polarity() == ty::PredicatePolarity::Positive { // Can't show anything else useful, try to find similar impls. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 0a6af42e122b..a98f952d55a3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -360,10 +360,10 @@ pub enum AppendConstMessage { } #[derive(LintDiagnostic)] -#[diag(trait_selection_malformed_on_unimplemented_attr)] -#[help] +#[diag("malformed `on_unimplemented` attribute")] +#[help("only `message`, `note` and `label` are allowed as options")] pub struct MalformedOnUnimplementedAttrLint { - #[label] + #[label("invalid option found here")] pub span: Span, } @@ -374,17 +374,17 @@ impl MalformedOnUnimplementedAttrLint { } #[derive(LintDiagnostic)] -#[diag(trait_selection_missing_options_for_on_unimplemented_attr)] -#[help] +#[diag("missing options for `on_unimplemented` attribute")] +#[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; #[derive(LintDiagnostic)] -#[diag(trait_selection_ignored_diagnostic_option)] +#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")] pub struct IgnoredDiagnosticOption { pub option_name: &'static str, - #[label] + #[label("`{$option_name}` is already declared here")] pub span: Span, - #[label(trait_selection_other_label)] + #[label("`{$option_name}` is first declared here")] pub prev_span: Span, } @@ -410,7 +410,7 @@ impl IgnoredDiagnosticOption { } #[derive(LintDiagnostic)] -#[diag(trait_selection_wrapped_parser_error)] +#[diag("{$description}")] pub struct WrappedParserError { pub description: String, pub label: String, @@ -888,7 +888,7 @@ impl<'tcx> OnUnimplementedFormatString { } } else { let reported = - struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description,) + struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description) .emit(); result = Err(reported); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index 1954f8a1f639..8488d76e2c77 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -310,25 +310,27 @@ pub mod errors { use super::*; #[derive(LintDiagnostic)] - #[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)] - #[help] + #[diag("there is no parameter `{$argument_name}` on trait `{$trait_name}`")] + #[help("expect either a generic argument name or {\"`{Self}`\"} as format argument")] pub struct UnknownFormatParameterForOnUnimplementedAttr { pub argument_name: Symbol, pub trait_name: Ident, } #[derive(LintDiagnostic)] - #[diag(trait_selection_disallowed_positional_argument)] - #[help] + #[diag("positional format arguments are not allowed here")] + #[help( + "only named format arguments with the name of one of the generic types are allowed in this context" + )] pub struct DisallowedPositionalArgument; #[derive(LintDiagnostic)] - #[diag(trait_selection_invalid_format_specifier)] - #[help] + #[diag("invalid format specifier")] + #[help("no format specifier are supported in this position")] pub struct InvalidFormatSpecifier; #[derive(LintDiagnostic)] - #[diag(trait_selection_missing_options_for_on_unimplemented_attr)] - #[help] + #[diag("missing options for `on_unimplemented` attribute")] + #[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d54f3812350d..63fd61cb257b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -954,7 +954,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let new_obligation = self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); - if self.predicate_must_hold_modulo_regions(&new_obligation) { + if !matches!(tail_expr.kind, hir::ExprKind::Err(_)) + && self.predicate_must_hold_modulo_regions(&new_obligation) + { err.span_suggestion_short( stmt.span.with_lo(tail_expr.span.hi()), "remove this semicolon", @@ -3581,11 +3583,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(of_trait) = of_trait { + if let Some(of_trait) = of_trait + && !of_trait.trait_ref.path.span.in_derive_expansion() + { spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); + let mut derived = false; if matches!( self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) @@ -3593,9 +3598,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { + derived = true; spans.push_span_label( data.span, - "unsatisfied trait bound introduced in this `derive` macro", + if data.span.in_derive_expansion() { + format!("type parameter would need to implement `{trait_name}`") + } else { + format!("unsatisfied trait bound") + }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { // `Sized` may be an explicit or implicit trait bound. If it is @@ -3621,6 +3631,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); + if derived && trait_name != "Copy" { + err.help(format!( + "consider manually implementing `{trait_name}` to avoid undesired \ + bounds", + )); + } point_at_assoc_type_restriction( tcx, err, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index af241099c014..8f353cae0beb 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,12 +17,11 @@ use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; -use crate::fluent_generated as fluent; pub mod note_and_explain; #[derive(Diagnostic)] -#[diag(trait_selection_unable_to_construct_constant_value)] +#[diag("unable to construct a constant value for the unevaluated constant {$unevaluated}")] pub struct UnableToConstructConstantValue<'a> { #[primary_span] pub span: Span, @@ -31,60 +30,64 @@ pub struct UnableToConstructConstantValue<'a> { #[derive(Diagnostic)] pub enum InvalidOnClause { - #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)] + #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)] Empty { #[primary_span] - #[label] + #[label("empty `on`-clause here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)] + #[diag("expected a single predicate in `not(..)`", code = E0232)] ExpectedOnePredInNot { #[primary_span] - #[label] + #[label("unexpected quantity of predicates here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)] + #[diag("literals inside `on`-clauses are not supported", code = E0232)] UnsupportedLiteral { #[primary_span] - #[label] + #[label("unexpected literal here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)] + #[diag("expected an identifier inside this `on`-clause", code = E0232)] ExpectedIdentifier { #[primary_span] - #[label] + #[label("expected an identifier here, not `{$path}`")] span: Span, path: Path, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)] + #[diag("this predicate is invalid", code = E0232)] InvalidPredicate { #[primary_span] - #[label] + #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")] span: Span, invalid_pred: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)] + #[diag("invalid flag in `on`-clause", code = E0232)] InvalidFlag { #[primary_span] - #[label] + #[label( + "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`" + )] span: Span, invalid_flag: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)] + #[diag("invalid name in `on`-clause", code = E0232)] InvalidName { #[primary_span] - #[label] + #[label( + "expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}`" + )] span: Span, invalid_name: Symbol, }, } #[derive(Diagnostic)] -#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)] -#[note] +#[diag("this attribute must have a value", code = E0232)] +#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")] pub struct NoValueInOnUnimplemented { #[primary_span] - #[label] + #[label("expected value here")] pub span: Span, } @@ -99,26 +102,35 @@ pub struct NegativePositiveConflict<'tcx> { impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict); + let mut diag = Diag::new( + dcx, + level, + msg!( + "found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> + [none] {\"\"} + *[default] {\" \"}for type `{$self_desc}` + }:" + ), + ); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); diag.code(E0751); match self.negative_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_negative_implementation_here); + diag.span_label(span, msg!("negative implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_negative_implementation_in_crate); + diag.note(msg!("negative implementation in crate `{$negative_impl_cname}`")); diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_positive_implementation_here); + diag.span_label(span, msg!("positive implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_positive_implementation_in_crate); + diag.note(msg!("positive implementation in crate `{$positive_impl_cname}`")); diag.arg("positive_impl_cname", cname.to_string()); } } @@ -127,7 +139,7 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { } #[derive(Diagnostic)] -#[diag(trait_selection_inherent_projection_normalization_overflow)] +#[diag("overflow evaluating associated type `{$ty}`")] pub struct InherentProjectionNormalizationOverflow { #[primary_span] pub span: Span, @@ -143,17 +155,27 @@ impl Subdiagnostic for AdjustSignatureBorrow { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { - diag.arg("len", to_borrow.len()); + diag.arg("borrow_len", to_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_borrow, + msg!( + "consider adjusting the signature so it borrows its {$borrow_len -> + [one] argument + *[other] arguments + }" + ), to_borrow, Applicability::MaybeIncorrect, ); } AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { - diag.arg("len", remove_borrow.len()); + diag.arg("remove_borrow_len", remove_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_remove_borrow, + msg!( + "consider adjusting the signature so it does not borrow its {$remove_borrow_len -> + [one] argument + *[other] arguments + }" + ), remove_borrow, Applicability::MaybeIncorrect, ); @@ -163,14 +185,14 @@ impl Subdiagnostic for AdjustSignatureBorrow { } #[derive(Diagnostic)] -#[diag(trait_selection_closure_kind_mismatch, code = E0525)] +#[diag("expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}`", code = E0525)] pub struct ClosureKindMismatch { #[primary_span] - #[label] + #[label("this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}`")] pub closure_span: Span, pub expected: ClosureKind, pub found: ClosureKind, - #[label(trait_selection_closure_kind_requirement)] + #[label("the requirement to implement `{$trait_prefix}{$expected}` derives from here")] pub cause_span: Span, pub trait_prefix: &'static str, @@ -183,7 +205,9 @@ pub struct ClosureKindMismatch { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_once_label)] +#[label( + "closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment" +)] pub struct ClosureFnOnceLabel { #[primary_span] pub span: Span, @@ -191,7 +215,7 @@ pub struct ClosureFnOnceLabel { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_mut_label)] +#[label("closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here")] pub struct ClosureFnMutLabel { #[primary_span] pub span: Span, @@ -199,7 +223,9 @@ pub struct ClosureFnMutLabel { } #[derive(Diagnostic)] -#[diag(trait_selection_coro_closure_not_fn)] +#[diag( + "{$coro_kind}closure does not implement `{$kind}` because it captures state from its environment" +)] pub(crate) struct CoroClosureNotFn { #[primary_span] pub span: Span, @@ -208,13 +234,17 @@ pub(crate) struct CoroClosureNotFn { } #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0282)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0282)] pub struct AnnotationRequired<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -226,13 +256,17 @@ pub struct AnnotationRequired<'a> { // Copy of `AnnotationRequired` for E0283 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0283)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0283)] pub struct AmbiguousImpl<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -244,13 +278,17 @@ pub struct AmbiguousImpl<'a> { // Copy of `AnnotationRequired` for E0284 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0284)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0284)] pub struct AmbiguousReturn<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -262,7 +300,19 @@ pub struct AmbiguousReturn<'a> { // Used when a better one isn't available #[derive(Subdiagnostic)] -#[label(trait_selection_label_bad)] +#[label( + "{$bad_kind -> +*[other] cannot infer type +[more_info] cannot infer {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] the value of const parameter +[const] the value of the constant +} `{$name}`{$has_parent -> +[true] {\" \"}declared on the {$parent_prefix} `{$parent_name}` +*[false] {\"\"} +} +}" +)] pub struct InferenceBadError<'a> { #[primary_span] pub span: Span, @@ -278,7 +328,19 @@ pub struct InferenceBadError<'a> { #[derive(Subdiagnostic)] pub enum SourceKindSubdiag<'a> { #[suggestion( - trait_selection_source_kind_subdiag_let, + "{$kind -> + [with_pattern] consider giving `{$name}` an explicit type + [closure] consider giving this closure parameter an explicit type + *[other] consider giving this pattern a type + }{$x_kind -> + [has_name] , where the {$prefix_kind -> + *[type] type for {$prefix} + [const_with_param] value of const parameter + [const] value of the constant + } `{$arg_name}` is specified + [underscore] , where the placeholders `_` are specified + *[empty] {\"\"} + }", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -294,7 +356,18 @@ pub enum SourceKindSubdiag<'a> { prefix: &'a str, arg_name: String, }, - #[label(trait_selection_source_kind_subdiag_generic_label)] + #[label( + "cannot infer {$is_type -> + [true] type + *[false] the value + } of the {$is_type -> + [true] type + *[false] const + } {$parent_exists -> + [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` + *[false] parameter {$param_name} + }" + )] GenericLabel { #[primary_span] span: Span, @@ -305,7 +378,10 @@ pub enum SourceKindSubdiag<'a> { parent_name: String, }, #[suggestion( - trait_selection_source_kind_subdiag_generic_suggestion, + "consider specifying the generic {$arg_count -> + [one] argument + *[other] arguments + }", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -321,7 +397,7 @@ pub enum SourceKindSubdiag<'a> { #[derive(Subdiagnostic)] pub enum SourceKindMultiSuggestion<'a> { #[multipart_suggestion( - trait_selection_source_kind_fully_qualified, + "try using a fully qualified path to specify the expected types", style = "verbose", applicability = "has-placeholders" )] @@ -335,7 +411,7 @@ pub enum SourceKindMultiSuggestion<'a> { successor_pos: &'a str, }, #[multipart_suggestion( - trait_selection_source_kind_closure_return, + "try giving this closure an explicit return type", style = "verbose", applicability = "has-placeholders" )] @@ -427,7 +503,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { requirement, expected_found: Some((expected, found)), } => { - label_or_note(span, fluent::trait_selection_subtype); + label_or_note( + span, + msg!( + "...so that the {$requirement -> + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` 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 + }" + ), + ); diag.arg("requirement", requirement); diag.note_expected_found("", expected, "", found); @@ -436,7 +529,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note(span, fluent::trait_selection_subtype_2); + label_or_note( + span, + msg!( + "...so that {$requirement -> + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` 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 + }" + ), + ); diag.arg("requirement", requirement); } }; @@ -464,9 +574,17 @@ impl Subdiagnostic for LifetimeMismatchLabels { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { - diag.span_label(param_span, fluent::trait_selection_declared_different); - diag.span_label(ret_span, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_returned); + diag.span_label(param_span, msg!("this parameter and the return type are declared with different lifetimes...")); + diag.span_label(ret_span, msg!("{\"\"}")); + diag.span_label( + span, + msg!( + "...but data{$label_var1_exists -> + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } is returned here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } @@ -479,13 +597,33 @@ impl Subdiagnostic for LifetimeMismatchLabels { sub: label_var2, } => { if hir_equal { - diag.span_label(ty_sup, fluent::trait_selection_declared_multiple); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_lifetime_flow); + diag.span_label( + ty_sup, + msg!("this type is declared with multiple lifetimes..."), + ); + diag.span_label(ty_sub, msg!("{\"\"}")); + diag.span_label( + span, + msg!("...but data with one lifetime flows into the other here"), + ); } else { - diag.span_label(ty_sup, fluent::trait_selection_types_declared_different); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_flows); + diag.span_label( + ty_sup, + msg!("these two types are declared with different lifetimes..."), + ); + diag.span_label(ty_sub, msg!("{\"\"}")); + diag.span_label( + span, + msg!( + "...but data{$label_var1_exists -> + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } flows{$label_var2_exists -> + [true] {\" \"}into `{$label_var2}` + *[false] {\"\"} + } here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); diag.arg("label_var2_exists", label_var2.is_some()); @@ -651,7 +789,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { visitor.suggestions.push(new_param_suggestion); } diag.multipart_suggestion_verbose( - fluent::trait_selection_lifetime_param_suggestion, + msg!( + "consider {$is_reuse -> + [true] reusing + *[false] introducing + } a named lifetime parameter{$is_impl -> + [true] {\" \"}and update trait if needed + *[false] {\"\"} + }" + ), visitor.suggestions, Applicability::MaybeIncorrect, ); @@ -661,13 +807,13 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { true }; if mk_suggestion() && self.add_note { - diag.note(fluent::trait_selection_lifetime_param_suggestion_elided); + diag.note(msg!("each elided lifetime in input position becomes a distinct lifetime")); } } } #[derive(Diagnostic)] -#[diag(trait_selection_lifetime_mismatch, code = E0623)] +#[diag("lifetime mismatch", code = E0623)] pub struct LifetimeMismatch<'a> { #[primary_span] pub span: Span, @@ -684,33 +830,42 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { - self.unmet_requirements - .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); - diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); + self.unmet_requirements.push_span_label( + self.binding_span, + msg!("introduces a `'static` lifetime requirement"), + ); + diag.span_note( + self.unmet_requirements, + msg!("because this has an unmet lifetime requirement"), + ); } } // FIXME(#100717): replace with a `Option` when subdiagnostic supports that #[derive(Subdiagnostic)] pub enum DoesNotOutliveStaticFromImpl { - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Spanned { #[primary_span] span: Span, }, - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Unspanned, } #[derive(Subdiagnostic)] pub enum ImplicitStaticLifetimeSubdiag { - #[note(trait_selection_implicit_static_lifetime_note)] + #[note("this has an implicit `'static` lifetime requirement")] Note { #[primary_span] span: Span, }, #[suggestion( - trait_selection_implicit_static_lifetime_suggestion, + "consider relaxing the implicit `'static` requirement", style = "verbose", code = " + '_", applicability = "maybe-incorrect" @@ -722,7 +877,7 @@ pub enum ImplicitStaticLifetimeSubdiag { } #[derive(Diagnostic)] -#[diag(trait_selection_mismatched_static_lifetime)] +#[diag("incompatible lifetime on type")] pub struct MismatchedStaticLifetime<'a> { #[primary_span] pub cause_span: Span, @@ -738,15 +893,15 @@ pub struct MismatchedStaticLifetime<'a> { #[derive(Diagnostic)] pub enum ExplicitLifetimeRequired<'a> { - #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)] + #[diag("explicit lifetime required in the type of `{$simple_ident}`", code = E0621)] WithIdent { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, simple_ident: Ident, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_ident, + "add explicit lifetime `{$named}` to the type of `{$simple_ident}`", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -755,14 +910,14 @@ pub enum ExplicitLifetimeRequired<'a> { #[skip_arg] new_ty: Ty<'a>, }, - #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)] + #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_param_type, + "add explicit lifetime `{$named}` to type", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -789,7 +944,10 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { - #[note(trait_selection_actual_impl_expl_expected_signature_two)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -797,27 +955,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_any)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_some)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_nothing)] + #[note( + "{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_passive_two)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -825,27 +997,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_any)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_some)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_nothing)] + #[note( + "{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + )] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_other_two)] + #[note("{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -853,40 +1039,70 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_any)] + #[note( + "{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + )] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_some)] + #[note( + "{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + )] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_nothing)] + #[note( + "{$leading_ellipsis -> + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)] + #[note( + "...but it actually implements `{$trait_path}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" + )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, }, - #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)] + #[note( + "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" + )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)] + #[note( + "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" + )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, @@ -978,15 +1194,15 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } #[derive(Diagnostic)] -#[diag(trait_selection_trait_placeholder_mismatch)] +#[diag("implementation of `{$trait_def_id}` is not general enough")] pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label(trait_selection_label_satisfy)] + #[label("doesn't satisfy where-clause")] pub satisfy_span: Option, - #[label(trait_selection_label_where)] + #[label("due to a where-clause on `{$def_id}`...")] pub where_span: Option, - #[label(trait_selection_label_dup)] + #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -1004,33 +1220,33 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); + type_param_span + .push_span_label(span, msg!("consider borrowing this type parameter in the trait")); } - let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help); + let msg = diag.eagerly_translate(msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); diag.span_help(type_param_span, msg); } } -#[derive(Subdiagnostic)] -#[help(trait_selection_tid_rel_help)] -pub struct RelationshipHelp; - #[derive(Diagnostic)] -#[diag(trait_selection_trait_impl_diff)] +#[diag("`impl` item signature doesn't match `trait` item signature")] pub struct TraitImplDiff { #[primary_span] - #[label(trait_selection_found)] + #[label("found `{$found}`")] pub sp: Span, - #[label(trait_selection_expected)] + #[label("expected `{$expected}`")] pub trait_sp: Span, - #[note(trait_selection_expected_found)] + #[note( + "expected signature `{$expected}` + {\" \"}found signature `{$found}`" + )] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, - #[subdiagnostic] - // Seems like subdiagnostics are always pushed to the end, so this one - // also has to be a subdiagnostic to maintain order. - pub rel_help: Option, + #[help( + "verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output" + )] + pub rel_help: bool, pub expected: String, pub found: String, } @@ -1043,12 +1259,18 @@ pub struct DynTraitConstraintSuggestion { impl Subdiagnostic for DynTraitConstraintSuggestion { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); - multi_span - .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note); + multi_span.push_span_label( + self.span, + msg!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + self.ident.span, + msg!("calling this method introduces the `impl`'s `'static` requirement"), + ); + let msg = diag.eagerly_translate(msg!("the used `impl` has a `'static` requirement")); diag.span_note(multi_span, msg); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion); + let msg = + diag.eagerly_translate(msg!("consider relaxing the implicit `'static` requirement")); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1059,12 +1281,26 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(trait_selection_but_calling_introduces, code = E0772)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement", code = E0772)] pub struct ButCallingIntroduces { - #[label(trait_selection_label1)] + #[label( + "{$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }" + )] pub param_ty_span: Span, #[primary_span] - #[label(trait_selection_label2)] + #[label("...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [true] `impl` of `{$impl_path}` + *[false] inherent `impl` + }")] pub cause_span: Span, pub has_param_name: bool, @@ -1087,32 +1323,58 @@ pub struct ReqIntroducedLocations { impl Subdiagnostic for ReqIntroducedLocations { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { for sp in self.spans { - self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); + self.span.push_span_label(sp, msg!("`'static` requirement introduced here")); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); + self.span.push_span_label( + self.fn_decl_span, + msg!("requirement introduced by this return type"), + ); } - self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); - let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by); + self.span.push_span_label(self.cause_span, msg!("because of this returned expression")); + let msg = diag.eagerly_translate(msg!( + "\"`'static` lifetime requirement introduced by the return type" + )); diag.span_note(self.span, msg); } } #[derive(Diagnostic)] -#[diag(trait_selection_but_needs_to_satisfy, code = E0759)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement", code = E0759)] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(trait_selection_influencer)] + #[label( + "this data with {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }..." + )] pub influencer_point: Span, - #[label(trait_selection_used_here)] + #[label("...is used here...")] pub spans: Vec, - #[label(trait_selection_require)] + #[label( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_label: Option, - #[note(trait_selection_require)] + #[note( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_note: Option, - #[note(trait_selection_introduced_by_bound)] + #[note("`'static` lifetime requirement introduced by this bound")] pub bound: Option, pub has_param_name: bool, @@ -1123,7 +1385,7 @@ pub struct ButNeedsToSatisfy { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_content, code = E0312)] +#[diag("lifetime of reference outlives lifetime of borrowed content...", code = E0312)] pub struct OutlivesContent<'a> { #[primary_span] pub span: Span, @@ -1132,7 +1394,7 @@ pub struct OutlivesContent<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_bound, code = E0476)] +#[diag("lifetime of the source pointer does not outlive lifetime bound of the object type", code = E0476)] pub struct OutlivesBound<'a> { #[primary_span] pub span: Span, @@ -1141,7 +1403,7 @@ pub struct OutlivesBound<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_fulfill_req_lifetime, code = E0477)] +#[diag("the type `{$ty}` does not fulfill the required lifetime", code = E0477)] pub struct FulfillReqLifetime<'a> { #[primary_span] pub span: Span, @@ -1151,7 +1413,7 @@ pub struct FulfillReqLifetime<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)] +#[diag("lifetime bound not satisfied", code = E0478)] pub struct LfBoundNotSatisfied<'a> { #[primary_span] pub span: Span, @@ -1160,7 +1422,7 @@ pub struct LfBoundNotSatisfied<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_ref_longer_than_data, code = E0491)] +#[diag("in type `{$ty}`, reference has a longer lifetime than the data it references", code = E0491)] pub struct RefLongerThanData<'a> { #[primary_span] pub span: Span, @@ -1172,7 +1434,7 @@ pub struct RefLongerThanData<'a> { #[derive(Subdiagnostic)] pub enum WhereClauseSuggestions { #[suggestion( - trait_selection_where_remove, + "remove the `where` clause", code = "", applicability = "machine-applicable", style = "verbose" @@ -1182,7 +1444,7 @@ pub enum WhereClauseSuggestions { span: Span, }, #[suggestion( - trait_selection_where_copy_predicates, + "copy the `where` clause predicates from the trait", code = "{space}where {trait_predicates}", applicability = "machine-applicable", style = "verbose" @@ -1198,7 +1460,7 @@ pub enum WhereClauseSuggestions { #[derive(Subdiagnostic)] pub enum SuggestRemoveSemiOrReturnBinding { #[multipart_suggestion( - trait_selection_srs_remove_and_box, + "consider removing this semicolon and boxing the expressions", applicability = "machine-applicable" )] RemoveAndBox { @@ -1214,7 +1476,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_remove, + "consider removing this semicolon", style = "short", code = "", applicability = "machine-applicable" @@ -1224,7 +1486,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_add, + "consider returning the local binding `{$ident}`", style = "verbose", code = "{code}", applicability = "maybe-incorrect" @@ -1235,7 +1497,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { code: String, ident: Ident, }, - #[note(trait_selection_srs_add_one)] + #[note("consider returning one of these bindings")] AddOne { #[primary_span] spans: MultiSpan, @@ -1244,9 +1506,12 @@ pub enum SuggestRemoveSemiOrReturnBinding { #[derive(Subdiagnostic)] pub enum ConsiderAddingAwait { - #[help(trait_selection_await_both_futures)] + #[help("consider `await`ing on both `Future`s")] BothFuturesHelp, - #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "consider `await`ing on both `Future`s", + applicability = "maybe-incorrect" + )] BothFuturesSugg { #[suggestion_part(code = ".await")] first: Span, @@ -1254,7 +1519,7 @@ pub enum ConsiderAddingAwait { second: Span, }, #[suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", code = ".await", style = "verbose", applicability = "maybe-incorrect" @@ -1263,13 +1528,13 @@ pub enum ConsiderAddingAwait { #[primary_span] span: Span, }, - #[note(trait_selection_await_note)] + #[note("calling an async function returns a future")] FutureSuggNote { #[primary_span] span: Span, }, #[multipart_suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", style = "verbose", applicability = "maybe-incorrect" )] @@ -1281,69 +1546,79 @@ pub enum ConsiderAddingAwait { #[derive(Diagnostic)] pub enum PlaceholderRelationLfNotSatisfied { - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasBoth { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sub_symbol: Symbol, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSub { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, sub_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSup { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasNone { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] OnlyPrimarySpan { #[primary_span] span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_captures_lifetime, code = E0700)] +#[diag("hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds", code = E0700)] pub struct OpaqueCapturesLifetime<'tcx> { #[primary_span] pub span: Span, - #[label] + #[label("opaque type defined here")] pub opaque_ty_span: Span, pub opaque_ty: Ty<'tcx>, } @@ -1351,7 +1626,7 @@ pub struct OpaqueCapturesLifetime<'tcx> { #[derive(Subdiagnostic)] pub enum FunctionPointerSuggestion<'a> { #[suggestion( - trait_selection_fps_use_ref, + "consider using a reference", code = "&", style = "verbose", applicability = "maybe-incorrect" @@ -1361,7 +1636,7 @@ pub enum FunctionPointerSuggestion<'a> { span: Span, }, #[suggestion( - trait_selection_fps_remove_ref, + "consider removing the reference", code = "{fn_name}", style = "verbose", applicability = "maybe-incorrect" @@ -1373,7 +1648,7 @@ pub enum FunctionPointerSuggestion<'a> { fn_name: String, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = "&({fn_name} as {sig})", style = "verbose", applicability = "maybe-incorrect" @@ -1387,7 +1662,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = " as {sig}", style = "verbose", applicability = "maybe-incorrect" @@ -1399,7 +1674,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = " as {found_sig}", style = "hidden", applicability = "maybe-incorrect" @@ -1412,7 +1687,7 @@ pub enum FunctionPointerSuggestion<'a> { expected_sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = "&({fn_name} as {found_sig})", style = "hidden", applicability = "maybe-incorrect" @@ -1429,21 +1704,21 @@ pub enum FunctionPointerSuggestion<'a> { } #[derive(Subdiagnostic)] -#[note(trait_selection_fps_items_are_distinct)] +#[note("fn items are distinct from fn pointers")] pub struct FnItemsAreDistinct; #[derive(Subdiagnostic)] -#[note(trait_selection_fn_uniq_types)] +#[note("different fn items have unique types, even if their signatures are the same")] pub struct FnUniqTypes; #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting)] +#[help("consider casting the fn item to a fn pointer: `{$casting}`")] pub struct FnConsiderCasting { pub casting: String, } #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting_both)] +#[help("consider casting both fn items to fn pointers using `as {$sig}`")] pub struct FnConsiderCastingBoth<'a> { pub sig: Binder<'a, FnSig<'a>>, } @@ -1451,7 +1726,7 @@ pub struct FnConsiderCastingBoth<'a> { #[derive(Subdiagnostic)] pub enum SuggestAccessingField<'a> { #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "{snippet}.{name}", applicability = "maybe-incorrect", style = "verbose" @@ -1464,7 +1739,7 @@ pub enum SuggestAccessingField<'a> { ty: Ty<'a>, }, #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "unsafe {{ {snippet}.{name} }}", applicability = "maybe-incorrect", style = "verbose" @@ -1479,7 +1754,10 @@ pub enum SuggestAccessingField<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try wrapping the pattern in `{$variant}`", + applicability = "maybe-incorrect" +)] pub struct SuggestTuplePatternOne { pub variant: String, #[suggestion_part(code = "{variant}(")] @@ -1497,7 +1775,8 @@ pub struct SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many); + let message = + diag.eagerly_translate(msg!("try wrapping the pattern in a variant of `{$path}`")); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { @@ -1514,7 +1793,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { #[derive(Subdiagnostic)] pub enum TypeErrorAdditionalDiags { #[suggestion( - trait_selection_meant_byte_literal, + "if you meant to write a byte literal, prefix with `b`", code = "b'{code}'", applicability = "machine-applicable" )] @@ -1524,7 +1803,7 @@ pub enum TypeErrorAdditionalDiags { code: String, }, #[suggestion( - trait_selection_meant_char_literal, + "if you meant to write a `char` literal, use single quotes", code = "'{code}'", applicability = "machine-applicable" )] @@ -1533,7 +1812,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, code: String, }, - #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a string literal, use double quotes", + applicability = "machine-applicable" + )] MeantStrLiteral { #[suggestion_part(code = "\"")] start: Span, @@ -1541,7 +1823,7 @@ pub enum TypeErrorAdditionalDiags { end: Span, }, #[suggestion( - trait_selection_consider_specifying_length, + "consider specifying the actual array length", code = "{length}", applicability = "maybe-incorrect" )] @@ -1550,10 +1832,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, length: u64, }, - #[note(trait_selection_try_cannot_convert)] + #[note("`?` operator cannot convert from `{$found}` to `{$expected}`")] TryCannotConvert { found: String, expected: String }, #[suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", code = ",", applicability = "machine-applicable" )] @@ -1562,7 +1844,7 @@ pub enum TypeErrorAdditionalDiags { span: Span, }, #[multipart_suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", applicability = "machine-applicable" )] TupleAlsoParentheses { @@ -1572,7 +1854,7 @@ pub enum TypeErrorAdditionalDiags { span_high: Span, }, #[suggestion( - trait_selection_suggest_add_let_for_letchains, + "consider adding `let`", style = "verbose", applicability = "machine-applicable", code = "let " @@ -1585,66 +1867,71 @@ pub enum TypeErrorAdditionalDiags { #[derive(Diagnostic)] pub enum ObligationCauseFailureCode { - #[diag(trait_selection_oc_method_compat, code = E0308)] + #[diag("method not compatible with trait", code = E0308)] MethodCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_type_compat, code = E0308)] + #[diag("type not compatible with trait", code = E0308)] TypeCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_const_compat, code = E0308)] + #[diag("const not compatible with trait", code = E0308)] ConstCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_try_compat, code = E0308)] + #[diag("`?` operator has incompatible types", code = E0308)] TryCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_match_compat, code = E0308)] + #[diag("`match` arms have incompatible types", code = E0308)] MatchCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_if_else_different, code = E0308)] + #[diag("`if` and `else` have incompatible types", code = E0308)] IfElseDifferent { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_no_else, code = E0317)] + #[diag("`if` may be missing an `else` clause", code = E0317)] NoElse { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_no_diverge, code = E0308)] + #[diag("`else` clause of `let...else` does not diverge", code = E0308)] NoDiverge { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)] + #[diag("`main` function has wrong type", code = E0580)] FnMainCorrectType { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] + #[diag( + "{$lang_item_name -> + [panic_impl] `#[panic_handler]` + *[lang_item_name] lang item `{$lang_item_name}` + } function has wrong type" + , code = E0308)] FnLangCorrectType { #[primary_span] span: Span, @@ -1652,40 +1939,40 @@ pub enum ObligationCauseFailureCode { subdiags: Vec, lang_item_name: Symbol, }, - #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)] + #[diag("intrinsic has wrong type", code = E0308)] IntrinsicCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_method_correct_type, code = E0308)] + #[diag("mismatched `self` parameter type", code = E0308)] MethodCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_closure_selfref, code = E0644)] + #[diag("closure/coroutine type that references itself", code = E0644)] ClosureSelfref { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)] + #[diag("cannot coerce functions which must be inlined to function pointers", code = E0308)] CantCoerceForceInline { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)] + #[diag("cannot coerce intrinsics to function pointers", code = E0308)] CantCoerceIntrinsic { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_generic, code = E0308)] + #[diag("mismatched types", code = E0308)] Generic { #[primary_span] span: Span, @@ -1697,7 +1984,7 @@ pub enum ObligationCauseFailureCode { #[derive(Subdiagnostic)] pub enum AddPreciseCapturing { #[suggestion( - trait_selection_precise_capturing_new, + "add a `use<...>` bound to explicitly capture `{$new_lifetime}`", style = "verbose", code = " + use<{concatenated_bounds}>", applicability = "machine-applicable" @@ -1709,7 +1996,7 @@ pub enum AddPreciseCapturing { concatenated_bounds: String, }, #[suggestion( - trait_selection_precise_capturing_existing, + "add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it", style = "verbose", code = "{pre}{new_lifetime}{post}", applicability = "machine-applicable" @@ -1733,13 +2020,13 @@ impl Subdiagnostic for AddPreciseCapturingAndParams { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_new_but_apit, + msg!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), self.suggs, Applicability::MaybeIncorrect, ); diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_undercapture, + msg!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), ); } } @@ -1880,26 +2167,29 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { Applicability::MaybeIncorrect }; diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_overcaptures, + msg!("use the precise capturing `use<...>` syntax to make the captures explicit"), self.suggs, applicability, ); if !self.apit_spans.is_empty() { diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_overcapture, + msg!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), ); } } } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] +#[diag("expected generic {$kind} parameter, found `{$arg}`", code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub arg: GenericArg<'tcx>, pub kind: &'a str, #[primary_span] pub span: Span, - #[label] + #[label("{STREQ($arg, \"'static\") -> + [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + *[other] this generic parameter must be used with a generic {$kind} parameter + }")] pub param_span: Span, } diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 3471036256db..08618be03e75 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,11 +1,10 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, msg}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Span, kw}; use crate::error_reporting::infer::nice_region_error::find_anon_type; -use crate::fluent_generated as fluent; struct DescriptionCtx<'a> { span: Option, @@ -170,7 +169,40 @@ impl Subdiagnostic for RegionExplanation<'_> { diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation); + let msg = diag.eagerly_translate(msg!( + "{$pref_kind -> + *[should_not_happen] [{$pref_kind}] + [ref_valid_for] ...the reference is valid for + [content_valid_for] ...but the borrowed content is only valid for + [type_obj_valid_for] object type is valid for + [source_pointer_valid_for] source pointer is only valid for + [type_satisfy] type must satisfy + [type_outlive] type must outlive + [lf_param_instantiated_with] lifetime parameter instantiated with + [lf_param_must_outlive] but lifetime parameter must outlive + [lf_instantiated_with] lifetime instantiated with + [lf_must_outlive] but lifetime must outlive + [pointer_valid_for] the pointer is valid for + [data_valid_for] but the referenced data is only valid for + [empty] {\"\"} + }{$pref_kind -> + [empty] {\"\"} + *[other] {\" \"} + }{$desc_kind -> + *[should_not_happen] [{$desc_kind}] + [restatic] the static lifetime + [revar] lifetime {$desc_arg} + [as_defined] the lifetime `{$desc_arg}` as defined here + [as_defined_anon] the anonymous lifetime as defined here + [defined_here] the anonymous lifetime defined here + [defined_here_reg] the lifetime `{$desc_arg}` as defined here + }{$suff_kind -> + *[should_not_happen] [{$suff_kind}] + [empty]{\"\"} + [continues] ... + [req_by_binding] {\" \"}as required by this binding + }" + )); diag.restore_args(); if let Some(span) = self.desc.span { diag.span_note(span, msg); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 561a95bad50c..708e0b9e8497 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,7 +11,7 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(default_field_values)] @@ -34,5 +34,3 @@ pub mod opaque_types; pub mod regions; pub mod solve; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index ea8360c10b6f..b8da64b9729a 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -443,9 +443,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { pub(crate) fn visit_with>(&self, visitor: &mut V) -> V::Result { if self.depth < visitor.config().max_depth { try_visit!(visitor.visit_goal(self)); + V::Result::output() + } else { + visitor.on_recursion_limit() } - - V::Result::output() } } @@ -460,6 +461,10 @@ pub trait ProofTreeVisitor<'tcx> { } fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result; + + fn on_recursion_limit(&mut self) -> Self::Result { + Self::Result::output() + } } #[extension(pub trait InferCtxtProofTreeExt<'tcx>)] diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2aae5f2cde1e..fc628e78a3e2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -8,8 +8,10 @@ use std::fmt::Debug; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::find_attr; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::PredicateObligations; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -23,7 +25,7 @@ use rustc_middle::ty::{ }; pub use rustc_next_trait_solver::coherence::*; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, warn}; use super::ObligationCtxt; @@ -566,7 +568,7 @@ fn plug_infer_with_placeholders<'tcx>( ty, Ty::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderType::new( self.universe, ty::BoundTy { var: self.next_var(), kind: ty::BoundTyKind::Anon }, ), @@ -592,9 +594,9 @@ fn plug_infer_with_placeholders<'tcx>( ct, ty::Const::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderConst::new( self.universe, - ty::BoundConst { var: self.next_var() }, + ty::BoundConst::new(self.next_var()), ), ), ) @@ -623,7 +625,7 @@ fn plug_infer_with_placeholders<'tcx>( r, ty::Region::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderRegion::new( self.universe, ty::BoundRegion { var: self.next_var(), @@ -758,10 +760,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { } = cand.kind() && let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) { - let message = infcx - .tcx - .get_attr(def_id, sym::rustc_reservation_impl) - .and_then(|a| a.value_str()); + let message = find_attr!(infcx.tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message }); } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index be70612653ce..512973e45287 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,9 +7,9 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, find_attr}; +use rustc_hir::{self as hir, LangItem}; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -332,7 +332,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( if tcx.features().min_generic_const_args() { if !tcx.generics_of(item.def_id).is_own_empty() { errors.push(AssocConstViolation::Generic); - } else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) { + } else if !tcx.is_type_const(item.def_id) { errors.push(AssocConstViolation::NonType); } @@ -833,8 +833,10 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { match ct.kind() { ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => { match self.allow_self_projections { - AllowSelfProjections::Yes => { - let trait_def_id = self.tcx.parent(proj.def); + AllowSelfProjections::Yes + if let trait_def_id = self.tcx.parent(proj.def) + && self.tcx.def_kind(trait_def_id) == DefKind::Trait => + { let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args); // Only walk contained consts if the parent trait is not a supertrait. @@ -844,7 +846,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { ct.super_visit_with(self) } } - AllowSelfProjections::No => ct.super_visit_with(self), + _ => ct.super_visit_with(self), } } _ => ct.super_visit_with(self), diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f33196bab647..2fd3a6e738cf 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause}; pub enum CopyImplementationError<'tcx> { InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), NotAnAdt, - HasDestructor, + HasDestructor(hir::def_id::DefId), HasUnsafeFields, } @@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>( ) .map_err(CopyImplementationError::InfringingFields)?; - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); + if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) { + return Err(CopyImplementationError::HasDestructor(did)); } if impl_safety.is_safe() && self_type.has_unsafe_fields() { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5839a8c2e295..1fde7e5d43b7 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -16,7 +16,7 @@ pub mod project; pub mod query; #[allow(hidden_glob_reexports)] mod select; -mod specialize; +pub mod specialize; mod structural_normalize; #[allow(hidden_glob_reexports)] mod util; @@ -681,6 +681,20 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } + Some(ty::AnonConstKind::OGCA) => { + if infcx.typing_mode() != TypingMode::PostAnalysis { + // OGCA anon consts should be treated as always having generics + // during anything before codegen (or maybe MIR opts too). + return Err(EvaluateConstErr::HasGenericsOrInfers); + } + + if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { + return Err(EvaluateConstErr::HasGenericsOrInfers); + } + + let typing_env = ty::TypingEnv::fully_monomorphized(); + (uv.args, typing_env) + } Some(ty::AnonConstKind::MCG) | Some(ty::AnonConstKind::NonTypeSystem) | None => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately @@ -772,7 +786,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( self.idx += 1; ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst { var: idx }), + ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst::new(idx)), ) } else { c.super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 24854990fe71..1475e5f5f243 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,6 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::msg; use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -294,7 +295,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.cause.span, false, |diag| { - diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); + diag.note(msg!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); }, ); } @@ -452,7 +453,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // been emitted earlier in compilation. // // That's because we can only end up with an Unevaluated ty::Const for a const item - // if it was marked with `#[type_const]`. Using this attribute without the mgca + // if it was marked with `type const`. Using this attribute without the mgca // feature gate causes a parse error. let ct = match tcx.def_kind(uv.def) { DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 02438b24ca7f..2f83ee046498 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -376,10 +376,14 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { // `tcx.normalize_canonicalized_projection` may normalize to a type that // still has unevaluated consts, so keep normalizing here if that's the case. // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer - // of type and we need to continue folding it to reveal the TAIT behind it. + // of type/const and we need to continue folding it to reveal the TAIT behind it + // or further normalize nested unevaluated consts. if res != term.to_term(tcx) - && (res.as_type().map_or(false, |t| t.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)) - || term.kind(tcx) == ty::AliasTermKind::FreeTy) + && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) + || matches!( + term.kind(tcx), + ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst + )) { res.try_fold_with(self) } else { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 78e7aef78f1b..91a025131855 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -1,3 +1,4 @@ +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_infer::traits::Obligation; use rustc_middle::traits::query::NoSolution; @@ -96,6 +97,26 @@ fn relate_mir_and_user_args<'tcx>( let tcx = ocx.infcx.tcx; let cause = ObligationCause::dummy_with_span(span); + // For IACs, the user args are in the format [SelfTy, GAT_args...] but type_of expects [impl_args..., GAT_args...]. + // We need to infer the impl args by equating the impl's self type with the user-provided self type. + let is_inherent_assoc_const = tcx.def_kind(def_id) == DefKind::AssocConst + && tcx.def_kind(tcx.parent(def_id)) == DefKind::Impl { of_trait: false } + && tcx.is_type_const(def_id); + + let args = if is_inherent_assoc_const { + let impl_def_id = tcx.parent(def_id); + let impl_args = ocx.infcx.fresh_args_for_item(span, impl_def_id); + let impl_self_ty = + ocx.normalize(&cause, param_env, tcx.type_of(impl_def_id).instantiate(tcx, impl_args)); + let user_self_ty = ocx.normalize(&cause, param_env, args[0].expect_ty()); + ocx.eq(&cause, param_env, impl_self_ty, user_self_ty)?; + + let gat_args = &args[1..]; + tcx.mk_args_from_iter(impl_args.iter().chain(gat_args.iter().copied())) + } else { + args + }; + let ty = tcx.type_of(def_id).instantiate(tcx, args); let ty = ocx.normalize(&cause, param_env, ty); debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); 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 f5bf74a79919..935834b832f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -312,7 +312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `async`/`gen` constructs get lowered to a special kind of coroutine that // should *not* `impl Coroutine`. ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => { - debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",); + debug!(?self_ty, ?obligation, "assemble_coroutine_candidates"); candidates.vec.push(CoroutineCandidate); } @@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // async constructs get lowered to a special kind of coroutine that // should directly `impl Future`. if self.tcx().coroutine_is_async(*did) { - debug!(?self_ty, ?obligation, "assemble_future_candidates",); + debug!(?self_ty, ?obligation, "assemble_future_candidates"); candidates.vec.push(FutureCandidate); } @@ -352,7 +352,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::Coroutine(did, ..) = self_ty.kind() && self.tcx().coroutine_is_gen(*did) { - debug!(?self_ty, ?obligation, "assemble_iterator_candidates",); + debug!(?self_ty, ?obligation, "assemble_iterator_candidates"); candidates.vec.push(IteratorCandidate); } @@ -378,7 +378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // gen constructs get lowered to a special kind of coroutine that // should directly `impl AsyncIterator`. if self.tcx().coroutine_is_async_gen(did) { - debug!(?self_ty, ?obligation, "assemble_iterator_candidates",); + debug!(?self_ty, ?obligation, "assemble_iterator_candidates"); // Can only confirm this candidate if we have constrained // the `Yield` type to at least `Poll>`.. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4f65b30775ed..b0e045274d0d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1246,6 +1246,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + /// This trait is indirectly exposed on stable, so do *not* extend the set of types that + /// implement the trait without FCP! fn confirm_bikeshed_guaranteed_no_drop_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 787dd4ea6254..3c3160bc533e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -12,9 +12,9 @@ use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; -use rustc_hir as hir; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, LangItem, find_attr}; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; @@ -33,7 +33,7 @@ use rustc_middle::ty::{ may_use_unstable_feature, }; use rustc_next_trait_solver::solve::AliasBoundKind; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -1223,7 +1223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && self.match_fresh_trait_preds(stack.fresh_trait_pred, prev.fresh_trait_pred) }) { - debug!("evaluate_stack --> unbound argument, recursive --> giving up",); + debug!("evaluate_stack --> unbound argument, recursive --> giving up"); return Ok(EvaluatedToAmbigStackDependent); } @@ -1445,8 +1445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { - let message = - tcx.get_attr(def_id, sym::rustc_reservation_impl).and_then(|a| a.value_str()); + let message = find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { debug!( "filter_reservation_impls: \ diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 19ccf6a55bf1..c3f46aa51c73 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -220,9 +220,9 @@ pub fn with_replaced_escaping_bound_vars< /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came. pub struct PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, - mapped_regions: FxIndexMap, ty::BoundRegion>, - mapped_types: FxIndexMap, ty::BoundTy>, - mapped_consts: FxIndexMap, ty::BoundConst>, + mapped_regions: FxIndexMap, ty::BoundRegion<'tcx>>, + mapped_types: FxIndexMap, ty::BoundTy<'tcx>>, + mapped_consts: FxIndexMap, ty::BoundConst<'tcx>>, universe_indices: &'a [Option], current_index: ty::DebruijnIndex, } @@ -230,9 +230,9 @@ pub struct PlaceholderReplacer<'a, 'tcx> { impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> { pub fn replace_placeholders>>( infcx: &'a InferCtxt<'tcx>, - mapped_regions: FxIndexMap, ty::BoundRegion>, - mapped_types: FxIndexMap, ty::BoundTy>, - mapped_consts: FxIndexMap, ty::BoundConst>, + mapped_regions: FxIndexMap, ty::BoundRegion<'tcx>>, + mapped_types: FxIndexMap, ty::BoundTy<'tcx>>, + mapped_consts: FxIndexMap, ty::BoundConst<'tcx>>, universe_indices: &'a [Option], value: T, ) -> T { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 584c8e2a27c8..825c06883a54 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -12,7 +12,7 @@ use rustc_span::DUMMY_SP; use smallvec::{SmallVec, smallvec}; use tracing::debug; -use crate::traits::{impossible_predicates, is_vtable_safe_method}; +use crate::traits::is_vtable_safe_method; #[derive(Clone, Debug)] pub enum VtblSegment<'tcx> { @@ -271,11 +271,7 @@ fn vtable_entries<'tcx>( // do not hold for this particular set of type parameters. // Note that this method could then never be called, so we // do not want to try and codegen it, in that case (see #23435). - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); - if impossible_predicates( - tcx, - predicates.map(|(predicate, _)| predicate).collect(), - ) { + if tcx.instantiate_and_check_impossible_predicates((def_id, args)) { debug!("vtable_entries: predicates do not hold"); return VtblEntry::Vacant; } @@ -434,7 +430,16 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( } }; - prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() + prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap_or_else(|| { + // This can happen if the trait hierarchy is malformed (e.g., due to + // missing generics on a supertrait bound). There should already be an error + // emitted for this, so we just delay the ICE. + tcx.dcx().delayed_bug(format!( + "could not find the supertrait vtable slot for `{}` -> `{}`", + source, target + )); + None + }) } pub(super) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d383cb9d91dd..358f14221a0d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -951,6 +951,34 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), )); } + + if !t.has_escaping_bound_vars() { + for projection in data.projection_bounds() { + let pred_binder = projection + .with_self_ty(tcx, t) + .map_bound(|p| { + p.term.as_const().map(|ct| { + let assoc_const_ty = tcx + .type_of(p.projection_term.def_id) + .instantiate(tcx, p.projection_term.args); + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + ct, + assoc_const_ty, + )) + }) + }) + .transpose(); + if let Some(pred_binder) = pred_binder { + self.out.push(traits::Obligation::with_depth( + tcx, + self.cause(ObligationCauseCode::WellFormed(None)), + self.recursion_depth, + self.param_env, + pred_binder, + )); + } + } + } } // Inference variables are the complicated case, since we don't diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index ce08b300cc80..682cf941561f 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -9,7 +9,6 @@ itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl deleted file mode 100644 index c1684bfb43b6..000000000000 --- a/compiler/rustc_ty_utils/messages.ftl +++ /dev/null @@ -1,61 +0,0 @@ -ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants - -ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants - -ty_utils_array_not_supported = array construction is not supported in generic constants - -ty_utils_assign_not_supported = assignment is not supported in generic constants - -ty_utils_binary_not_supported = unsupported binary operation in generic constants - -ty_utils_block_not_supported = blocks are not supported in generic constants - -ty_utils_borrow_not_supported = borrowing is not supported in generic constants - -ty_utils_box_not_supported = allocations are not allowed in generic constants - -ty_utils_by_use_not_supported = .use is not allowed in generic constants - -ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants - -ty_utils_const_block_not_supported = const blocks are not supported in generic constants - -ty_utils_control_flow_not_supported = control flow is not supported in generic constants - -ty_utils_field_not_supported = field access is not supported in generic constants - -ty_utils_generic_constant_too_complex = overly complex generic constant - .help = consider moving this anonymous constant into a `const` function - .maybe_supported = this operation may be supported in the future - -ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope - .label = generic argument `{$arg}` used twice - .note = for this opaque type - -ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope - .label = argument `{$arg}` is not a generic parameter - .note = for this opaque type - -ty_utils_index_not_supported = indexing is not supported in generic constants - -ty_utils_inline_asm_not_supported = assembly is not supported in generic constants - -ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow - -ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants - -ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop - -ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants - -ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}` - -ty_utils_operation_not_supported = unsupported operation in generic constants - -ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants - -ty_utils_tuple_not_supported = tuple construction is not supported in generic constants - -ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item - -ty_utils_yield_not_supported = coroutine control flow is not allowed in generic constants diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 34c080c4938f..72f31bbf62a6 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -306,8 +306,12 @@ fn arg_attrs_for_rust_scalar<'tcx>( let kind = if let Some(kind) = pointee.safe { Some(kind) } else if let Some(pointee) = drop_target_pointee { + assert_eq!(pointee, layout.ty.builtin_deref(true).unwrap()); + assert_eq!(offset, Size::ZERO); // The argument to `drop_in_place` is semantically equivalent to a mutable reference. - Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env) }) + let mutref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, pointee); + let layout = cx.layout_of(mutref).unwrap(); + layout.pointee_info_at(&cx, offset).and_then(|pi| pi.safe) } else { None }; diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index 7219f40710e0..a3f1be77f47a 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -8,36 +8,43 @@ use rustc_span::DUMMY_SP; use rustc_trait_selection::traits; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, LangItem::Copy) + is_trait_raw(tcx, query, LangItem::Copy) } fn is_use_cloned_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> bool { - is_item_raw(tcx, query, LangItem::UseCloned) + is_trait_raw(tcx, query, LangItem::UseCloned) } fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, LangItem::Sized) + is_trait_raw(tcx, query, LangItem::Sized) } fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, LangItem::Freeze) + is_trait_raw(tcx, query, LangItem::Freeze) +} + +fn is_unsafe_unpin_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, +) -> bool { + is_trait_raw(tcx, query, LangItem::UnsafeUnpin) } fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, LangItem::Unpin) + is_trait_raw(tcx, query, LangItem::Unpin) } fn is_async_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, ) -> bool { - is_item_raw(tcx, query, LangItem::AsyncDrop) + is_trait_raw(tcx, query, LangItem::AsyncDrop) } -fn is_item_raw<'tcx>( +fn is_trait_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, item: LangItem, @@ -53,6 +60,7 @@ pub(crate) fn provide(providers: &mut Providers) { is_use_cloned_raw, is_sized_raw, is_freeze_raw, + is_unsafe_unpin_raw, is_unpin_raw, is_async_drop_raw, ..*providers diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index f6d08bd458bd..0edbe9624c4b 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -1,12 +1,11 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::query::Providers; use rustc_middle::thir::visit; use rustc_middle::thir::visit::Visitor; use rustc_middle::ty::abstract_const::CastKind; -use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Expr, LitToConstInput, TyCtxt, TypeVisitableExt}; use rustc_middle::{mir, thir}; use rustc_span::Span; use tracing::instrument; @@ -59,7 +58,10 @@ fn recurse_build<'tcx>( } &ExprKind::Literal { lit, neg } => { let sp = node.span; - tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg }) + match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg }) { + Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty), + None => ty::Const::new_misc_error(tcx), + } } &ExprKind::NonHirLiteral { lit, user_ty: _ } => { let val = ty::ValTree::from_scalar_int(tcx, lit); diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index f92c405242ce..ccea5a49bd7c 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -6,18 +6,18 @@ use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(ty_utils_needs_drop_overflow)] +#[diag("overflow while checking whether `{$query_ty}` requires drop")] pub(crate) struct NeedsDropOverflow<'tcx> { pub query_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(ty_utils_generic_constant_too_complex)] -#[help] +#[diag("overly complex generic constant")] +#[help("consider moving this anonymous constant into a `const` function")] pub(crate) struct GenericConstantTooComplex { #[primary_span] pub span: Span, - #[note(ty_utils_maybe_supported)] + #[note("this operation may be supported in the future")] pub maybe_supported: bool, #[subdiagnostic] pub sub: GenericConstantTooComplexSub, @@ -25,84 +25,88 @@ pub(crate) struct GenericConstantTooComplex { #[derive(Subdiagnostic)] pub(crate) enum GenericConstantTooComplexSub { - #[label(ty_utils_borrow_not_supported)] + #[label("borrowing is not supported in generic constants")] BorrowNotSupported(#[primary_span] Span), - #[label(ty_utils_address_and_deref_not_supported)] + #[label("dereferencing or taking the address is not supported in generic constants")] AddressAndDerefNotSupported(#[primary_span] Span), - #[label(ty_utils_array_not_supported)] + #[label("array construction is not supported in generic constants")] ArrayNotSupported(#[primary_span] Span), - #[label(ty_utils_block_not_supported)] + #[label("blocks are not supported in generic constants")] BlockNotSupported(#[primary_span] Span), - #[label(ty_utils_never_to_any_not_supported)] + #[label("coercing the `never` type is not supported in generic constants")] NeverToAnyNotSupported(#[primary_span] Span), - #[label(ty_utils_tuple_not_supported)] + #[label("tuple construction is not supported in generic constants")] TupleNotSupported(#[primary_span] Span), - #[label(ty_utils_index_not_supported)] + #[label("indexing is not supported in generic constants")] IndexNotSupported(#[primary_span] Span), - #[label(ty_utils_field_not_supported)] + #[label("field access is not supported in generic constants")] FieldNotSupported(#[primary_span] Span), - #[label(ty_utils_const_block_not_supported)] + #[label("const blocks are not supported in generic constants")] ConstBlockNotSupported(#[primary_span] Span), - #[label(ty_utils_adt_not_supported)] + #[label("struct/enum construction is not supported in generic constants")] AdtNotSupported(#[primary_span] Span), - #[label(ty_utils_pointer_not_supported)] + #[label("pointer casts are not allowed in generic constants")] PointerNotSupported(#[primary_span] Span), - #[label(ty_utils_yield_not_supported)] + #[label("coroutine control flow is not allowed in generic constants")] YieldNotSupported(#[primary_span] Span), - #[label(ty_utils_loop_not_supported)] + #[label("loops and loop control flow are not supported in generic constants")] LoopNotSupported(#[primary_span] Span), - #[label(ty_utils_box_not_supported)] + #[label("allocations are not allowed in generic constants")] BoxNotSupported(#[primary_span] Span), - #[label(ty_utils_binary_not_supported)] + #[label("unsupported binary operation in generic constants")] BinaryNotSupported(#[primary_span] Span), - #[label(ty_utils_by_use_not_supported)] + #[label(".use is not allowed in generic constants")] ByUseNotSupported(#[primary_span] Span), - #[label(ty_utils_logical_op_not_supported)] + #[label( + "unsupported operation in generic constants, short-circuiting operations would imply control flow" + )] LogicalOpNotSupported(#[primary_span] Span), - #[label(ty_utils_assign_not_supported)] + #[label("assignment is not supported in generic constants")] AssignNotSupported(#[primary_span] Span), - #[label(ty_utils_closure_and_return_not_supported)] + #[label("closures and function keywords are not supported in generic constants")] ClosureAndReturnNotSupported(#[primary_span] Span), - #[label(ty_utils_control_flow_not_supported)] + #[label("control flow is not supported in generic constants")] ControlFlowNotSupported(#[primary_span] Span), - #[label(ty_utils_inline_asm_not_supported)] + #[label("assembly is not supported in generic constants")] InlineAsmNotSupported(#[primary_span] Span), - #[label(ty_utils_operation_not_supported)] + #[label("unsupported operation in generic constants")] OperationNotSupported(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(ty_utils_unexpected_fnptr_associated_item)] +#[diag("`FnPtr` trait with unexpected associated item")] pub(crate) struct UnexpectedFnPtrAssociatedItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ty_utils_non_primitive_simd_type)] +#[diag( + "monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`" +)] pub(crate) struct NonPrimitiveSimdType<'tcx> { pub ty: Ty<'tcx>, pub e_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_duplicate_arg)] +#[diag("non-defining opaque type use in defining scope")] pub(crate) struct DuplicateArg<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] - #[label] + #[label("generic argument `{$arg}` used twice")] pub span: Span, - #[note] + #[note("for this opaque type")] pub opaque_span: Span, } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_not_param, code = E0792)] +#[diag("non-defining opaque type use in defining scope", code = E0792)] pub(crate) struct NotParam<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] - #[label] + #[label("argument `{$arg}` is not a generic parameter")] pub span: Span, - #[note] + #[note("for this opaque type")] pub opaque_span: Span, } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 62f3667ad7f4..5a41e46f3a6b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -764,14 +764,22 @@ fn layout_of_uncached<'tcx>( } ty::Alias(..) => { - // NOTE(eddyb) `layout_of` query should've normalized these away, - // if that was possible, so there's no reason to try again here. - let err = if ty.has_param() { + // In case we're still in a generic context, aliases might be rigid. E.g. + // if we've got a `T: Trait` where-bound, `T::Assoc` cannot be normalized + // in the current context. + // + // For some builtin traits, generic aliases can be rigid even in an empty environment, + // e.g. `::Metadata`. + // + // Due to trivial bounds, this can even be the case if the alias does not reference + // any generic parameters, e.g. a `for<'a> u32: Trait<'a>` where-bound means that + // `>::Assoc` is rigid. + let err = if ty.has_param() || !cx.typing_env.param_env.caller_bounds().is_empty() { LayoutError::TooGeneric(ty) } else { - // This is only reachable with unsatisfiable predicates. For example, if we have - // `u8: Iterator`, then we can't compute the layout of `::Item`. - LayoutError::Unknown(ty) + LayoutError::ReferencesError(cx.tcx().dcx().delayed_bug(format!( + "unexpected rigid alias in layout_of after normalization: {ty:?}" + ))) }; return Err(error(cx, err)); } diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index d8b50b2d2e42..b7f73fd5570e 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,7 +5,7 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(if_let_guard)] @@ -31,8 +31,6 @@ pub mod sig_types; mod structural_match; mod ty; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { abi::provide(providers); assoc::provide(providers); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 0ef435b1a0e2..06eef7e95145 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -1,13 +1,14 @@ //! Check whether a type has (potentially) non-trivial drop glue. use rustc_data_structures::fx::FxHashSet; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::find_attr; use rustc_hir::limit::Limit; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; -use rustc_span::sym; use tracing::{debug, instrument}; use crate::errors::NeedsDropOverflow; @@ -396,8 +397,7 @@ fn adt_consider_insignificant_dtor<'tcx>( tcx: TyCtxt<'tcx>, ) -> impl Fn(ty::AdtDef<'tcx>) -> Option { move |adt_def: ty::AdtDef<'tcx>| { - let is_marked_insig = tcx.has_attr(adt_def.did(), sym::rustc_insignificant_dtor); - if is_marked_insig { + if find_attr!(tcx.get_all_attrs(adt_def.did()), AttributeKind::RustcInsignificantDtor) { // In some cases like `std::collections::HashMap` where the struct is a wrapper around // a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies // outside stdlib, we might choose to still annotate the wrapper (std HashMap) with diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index bb25a14ef744..d6a29aba22b9 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -210,7 +210,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, predicates: &'a mut Vec>, fn_def_id: DefId, - bound_vars: &'tcx ty::List, + bound_vars: &'tcx ty::List>, seen: FxHashSet, depth: ty::DebruijnIndex, } diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 315ab8b97e9b..fbe382712893 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -8,7 +8,7 @@ edition = "2024" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" derive-where = "1.2.7" -ena = "0.14.3" +ena = "0.14.4" indexmap = "2.0.0" rustc-hash = "2.0.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index b5c9080154ce..fc8b39f7c01f 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,11 +1,14 @@ use std::fmt; +use std::hash::Hash; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; -use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use tracing::instrument; use crate::data_structures::SsoHashSet; @@ -23,8 +26,11 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex}; /// for more details. /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. -#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. #[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)] #[derive(GenericTypeVisitable)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct Binder { @@ -359,9 +365,12 @@ impl TypeVisitor for ValidateBoundVars { /// `instantiate`. /// /// See for more details. -#[derive_where(Clone, PartialEq, Ord, Hash, Debug; I: Interner, T)] -#[derive_where(PartialOrd; I: Interner, T: Ord)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. +#[derive_where(Ord; I: Interner, T: Ord)] #[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)] #[derive(GenericTypeVisitable)] #[cfg_attr( feature = "nightly", @@ -955,11 +964,12 @@ pub enum BoundVarIndexKind { /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are /// identified by both a universe, as well as a name residing within that universe. Distinct bound /// regions/types/consts within the same universe simply have an unknown relationship to one -/// another. -#[derive_where(Clone, PartialEq, Ord, Hash; I: Interner, T)] -#[derive_where(PartialOrd; I: Interner, T: Ord)] -#[derive_where(Copy; I: Interner, T: Copy, T)] -#[derive_where(Eq; T)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. +#[derive_where(Ord; I: Interner, T: Ord)] +#[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr( feature = "nightly", @@ -973,12 +983,6 @@ pub struct Placeholder { _tcx: PhantomData I>, } -impl Placeholder { - pub fn new(universe: UniverseIndex, bound: T) -> Self { - Placeholder { universe, bound, _tcx: PhantomData } - } -} - impl fmt::Debug for ty::Placeholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.universe == ty::UniverseIndex::ROOT { @@ -1003,3 +1007,321 @@ where }) } } + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] + +pub enum BoundRegionKind { + /// An anonymous region parameter for a given fn (&T) + Anon, + + /// An anonymous region parameter with a `Symbol` name. + /// + /// Used to give late-bound regions names for things like pretty printing. + NamedForPrinting(I::Symbol), + + /// Late-bound regions that appear in the AST. + Named(I::DefId), + + /// Anonymous region for the implicit env pointer parameter + /// to a closure + ClosureEnv, +} + +impl fmt::Debug for ty::BoundRegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::BoundRegionKind::Anon => write!(f, "BrAnon"), + ty::BoundRegionKind::NamedForPrinting(name) => { + write!(f, "BrNamedForPrinting({:?})", name) + } + ty::BoundRegionKind::Named(did) => { + write!(f, "BrNamed({did:?})") + } + ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"), + } + } +} + +impl BoundRegionKind { + pub fn is_named(&self, tcx: I) -> bool { + self.get_name(tcx).is_some() + } + + pub fn get_name(&self, tcx: I) -> Option { + match *self { + ty::BoundRegionKind::Named(def_id) => { + let name = tcx.item_name(def_id); + if name.is_kw_underscore_lifetime() { None } else { Some(name) } + } + ty::BoundRegionKind::NamedForPrinting(name) => Some(name), + _ => None, + } + } + + pub fn get_id(&self) -> Option { + match *self { + ty::BoundRegionKind::Named(id) => Some(id), + _ => None, + } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum BoundTyKind { + Anon, + Param(I::DefId), +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum BoundVariableKind { + Ty(BoundTyKind), + Region(BoundRegionKind), + Const, +} + +impl BoundVariableKind { + pub fn expect_region(self) -> BoundRegionKind { + match self { + BoundVariableKind::Region(lt) => lt, + _ => panic!("expected a region, but found another kind"), + } + } + + pub fn expect_ty(self) -> BoundTyKind { + match self { + BoundVariableKind::Ty(ty) => ty, + _ => panic!("expected a type, but found another kind"), + } + } + + pub fn expect_const(self) { + match self { + BoundVariableKind::Const => (), + _ => panic!("expected a const, but found another kind"), + } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, HashStable_NoContext, Decodable_NoContext) +)] +pub struct BoundRegion { + pub var: ty::BoundVar, + pub kind: BoundRegionKind, +} + +impl core::fmt::Debug for BoundRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.kind { + BoundRegionKind::Anon => write!(f, "{:?}", self.var), + BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var), + BoundRegionKind::Named(def) => { + write!(f, "{:?}.Named({:?})", self.var, def) + } + BoundRegionKind::NamedForPrinting(symbol) => { + write!(f, "{:?}.NamedAnon({:?})", self.var, symbol) + } + } + } +} + +impl BoundRegion { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + assert_eq!(self.kind, var.expect_region()) + } +} + +pub type PlaceholderRegion = ty::Placeholder>; + +impl PlaceholderRegion { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var() + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundRegion) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundRegion { var, kind: BoundRegionKind::Anon }; + Self { universe: ui, bound, _tcx: PhantomData } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub struct BoundTy { + pub var: ty::BoundVar, + pub kind: BoundTyKind, +} + +impl Lift for BoundTy +where + BoundTyKind: Lift>, +{ + type Lifted = BoundTy; + + fn lift_to_interner(self, cx: U) -> Option { + Some(BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx)? }) + } +} + +impl fmt::Debug for ty::BoundTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + ty::BoundTyKind::Anon => write!(f, "{:?}", self.var), + ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"), + } + } +} + +impl BoundTy { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + assert_eq!(self.kind, var.expect_ty()) + } +} + +pub type PlaceholderType = ty::Placeholder>; + +impl PlaceholderType { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundTy) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundTy { var, kind: BoundTyKind::Anon }; + Self { universe: ui, bound, _tcx: PhantomData } + } +} + +#[derive_where(Clone, Copy, PartialEq, Debug, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub struct BoundConst { + pub var: ty::BoundVar, + #[derive_where(skip(Debug))] + pub _tcx: PhantomData I>, +} + +impl BoundConst { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + var.expect_const() + } + + pub fn new(var: ty::BoundVar) -> Self { + Self { var, _tcx: PhantomData } + } +} + +pub type PlaceholderConst = ty::Placeholder>; + +impl PlaceholderConst { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundConst) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundConst::new(var); + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { + let mut candidates = env.caller_bounds().iter().filter_map(|clause| { + // `ConstArgHasType` are never desugared to be higher ranked. + match clause.kind().skip_binder() { + ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { + assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); + + match placeholder_ct.kind() { + ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { + Some(ty) + } + _ => None, + } + } + _ => None, + } + }); + + // N.B. it may be tempting to fix ICEs by making this function return + // `Option>` instead of `Ty<'tcx>`; however, this is generally + // considered to be a bandaid solution, since it hides more important + // underlying issues with how we construct generics and predicates of + // items. It's advised to fix the underlying issue rather than trying + // to modify this function. + let ty = candidates.next().unwrap_or_else(|| { + panic!("cannot find `{self:?}` in param-env: {env:#?}"); + }); + assert!( + candidates.next().is_none(), + "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" + ); + ty + } +} diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 12d222258b0c..8e7414674c6e 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -108,7 +108,7 @@ pub enum CanonicalVarKind { Float, /// A "placeholder" that represents "any type". - PlaceholderTy(I::PlaceholderTy), + PlaceholderTy(ty::PlaceholderType), /// Region variable `'?R`. Region(UniverseIndex), @@ -116,13 +116,13 @@ pub enum CanonicalVarKind { /// A "placeholder" that represents "any region". Created when you /// are solving a goal like `for<'a> T: Foo<'a>` to represent the /// bound region `'a`. - PlaceholderRegion(I::PlaceholderRegion), + PlaceholderRegion(ty::PlaceholderRegion), /// Some kind of const inference variable. Const(UniverseIndex), /// A "placeholder" that represents "any const". - PlaceholderConst(I::PlaceholderConst), + PlaceholderConst(ty::PlaceholderConst), } impl Eq for CanonicalVarKind {} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 5b136ae03121..1c39f31469b1 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -26,10 +26,10 @@ pub enum ConstKind { Infer(InferConst), /// Bound const variable, used only when preparing a trait query. - Bound(BoundVarIndexKind, I::BoundConst), + Bound(BoundVarIndexKind, ty::BoundConst), /// A placeholder const - universally quantified higher-ranked const. - Placeholder(I::PlaceholderConst), + Placeholder(ty::PlaceholderConst), /// An unnormalized const item such as an anon const or assoc const or free const item. /// Right now anything other than anon consts does not actually work properly but this @@ -200,3 +200,23 @@ impl ValTreeKind { } } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum AnonConstKind { + /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope + GCE, + /// stable `min_const_generics` anon consts are not allowed to use any generic parameters + MCG, + /// `feature(opaque_generic_const_args)` anon consts are allowed to use arbitrary + /// generic parameters in scope, but only if they syntactically reference them. + OGCA, + /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters + /// but must not depend on the actual instantiation. See #76200 for more information + RepeatExprCount, + /// anon consts outside of the type system, e.g. enum discriminants + NonTypeSystem, +} diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 502622aa50ca..eba4c7c6644a 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -33,7 +33,7 @@ pub enum TypeError { ArgCount, RegionsDoesNotOutlive(I::Region, I::Region), - RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region), + RegionsInsufficientlyPolymorphic(ty::BoundRegion, I::Region), RegionsPlaceholderMismatch, Sorts(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 4323b1ca6469..c9580d589d21 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -12,8 +12,8 @@ use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; -use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; +use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; +use crate::{self as ty, ClauseKind, CollectAndApply, Interner, PredicateKind, UpcastFrom}; pub trait Ty>: Copy @@ -42,9 +42,9 @@ pub trait Ty>: fn new_param(interner: I, param: I::ParamTy) -> Self; - fn new_placeholder(interner: I, param: I::PlaceholderTy) -> Self; + fn new_placeholder(interner: I, param: ty::PlaceholderType) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; @@ -228,7 +228,7 @@ pub trait Region>: + Flags + Relate { - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundRegion) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; @@ -236,7 +236,7 @@ pub trait Region>: fn new_static(interner: I) -> Self; - fn new_placeholder(interner: I, var: I::PlaceholderRegion) -> Self; + fn new_placeholder(interner: I, var: ty::PlaceholderRegion) -> Self; fn is_bound(self) -> bool { matches!(self.kind(), ty::ReBound(..)) @@ -260,13 +260,13 @@ pub trait Const>: fn new_var(interner: I, var: ty::ConstVid) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: I::BoundConst) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: ty::BoundConst) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self; - fn new_placeholder(interner: I, param: I::PlaceholderConst) -> Self; + fn new_placeholder(interner: I, param: ty::PlaceholderConst) -> Self; fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; @@ -478,8 +478,27 @@ pub trait Predicate>: } } - // FIXME: Eventually uplift the impl out of rustc and make this defaulted. - fn allow_normalization(self) -> bool; + fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { + false + } + PredicateKind::Clause(ClauseKind::Trait(_)) + | PredicateKind::Clause(ClauseKind::HostEffect(..)) + | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) + | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) + | PredicateKind::Clause(ClauseKind::Projection(_)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) + | PredicateKind::DynCompatible(_) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::NormalizesTo(..) + | PredicateKind::Ambiguous => true, + } + } } pub trait Clause>: @@ -543,68 +562,12 @@ pub trait Clauses>: { } -/// Common capabilities of placeholder kinds -pub trait PlaceholderLike: Copy + Debug + Hash + Eq { - fn universe(self) -> ty::UniverseIndex; - fn var(self) -> ty::BoundVar; - - type Bound: BoundVarLike; - fn new(ui: ty::UniverseIndex, bound: Self::Bound) -> Self; - fn new_anon(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self; - fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self; -} - -pub trait PlaceholderConst: PlaceholderLike { - fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty; -} -impl PlaceholderConst for I::PlaceholderConst { - fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { - let mut candidates = env.caller_bounds().iter().filter_map(|clause| { - // `ConstArgHasType` are never desugared to be higher ranked. - match clause.kind().skip_binder() { - ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { - assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); - - match placeholder_ct.kind() { - ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { - Some(ty) - } - _ => None, - } - } - _ => None, - } - }); - - // N.B. it may be tempting to fix ICEs by making this function return - // `Option>` instead of `Ty<'tcx>`; however, this is generally - // considered to be a bandaid solution, since it hides more important - // underlying issues with how we construct generics and predicates of - // items. It's advised to fix the underlying issue rather than trying - // to modify this function. - let ty = candidates.next().unwrap_or_else(|| { - panic!("cannot find `{self:?}` in param-env: {env:#?}"); - }); - assert!( - candidates.next().is_none(), - "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" - ); - ty - } -} - pub trait IntoKind { type Kind; fn kind(self) -> Self::Kind; } -pub trait BoundVarLike: Copy + Debug + Hash + Eq { - fn var(self) -> ty::BoundVar; - - fn assert_eq(self, var: I::BoundVarKind); -} - pub trait ParamLike: Copy + Debug + Hash + Eq { fn index(self) -> u32; } @@ -768,3 +731,7 @@ impl<'a, S: SliceLike> SliceLike for &'a S { (*self).as_slice() } } + +pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { + fn is_kw_underscore_lifetime(self) -> bool; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0ab27a65c687..8f446cdfba6d 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -61,8 +61,12 @@ pub trait Interner: type GenericArg: GenericArg; type Term: Term; - type BoundVarKinds: Copy + Debug + Hash + Eq + SliceLike + Default; - type BoundVarKind: Copy + Debug + Hash + Eq; + type BoundVarKinds: Copy + + Debug + + Hash + + Eq + + SliceLike> + + Default; type PredefinedOpaques: Copy + Debug @@ -120,9 +124,7 @@ pub trait Interner: type Tys: Tys; type FnInputTys: Copy + Debug + Hash + Eq + SliceLike + TypeVisitable; type ParamTy: ParamLike; - type BoundTy: BoundVarLike; - type PlaceholderTy: PlaceholderLike; - type Symbol: Copy + Hash + PartialEq + Eq + Debug; + type Symbol: Symbol; // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; @@ -149,8 +151,6 @@ pub trait Interner: // Kinds of consts type Const: Const; type ParamConst: Copy + Debug + Hash + Eq + ParamLike; - type BoundConst: BoundVarLike; - type PlaceholderConst: PlaceholderConst; type ValueConst: ValueConst; type ExprConst: ExprConst; type ValTree: ValTree; @@ -160,8 +160,6 @@ pub trait Interner: type Region: Region; type EarlyParamRegion: ParamLike; type LateParamRegion: Copy + Debug + Hash + Eq; - type BoundRegion: BoundVarLike; - type PlaceholderRegion: PlaceholderLike; type RegionAssumptions: Copy + Debug @@ -207,6 +205,7 @@ pub trait Interner: fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId) -> ty::EarlyBinder; fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; @@ -411,6 +410,8 @@ pub trait Interner: self, canonical_goal: CanonicalInput, ) -> (QueryResult, Self::Probe); + + fn item_name(self, item_index: Self::DefId) -> Self::Symbol; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index dc286ee7f625..3d9fc7f5c998 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -5,10 +5,7 @@ #![allow(rustc::usage_of_type_ir_inherent)] #![allow(rustc::usage_of_type_ir_traits)] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr( - feature = "nightly", - feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) -)] +#![cfg_attr(feature = "nightly", feature(associated_type_defaults, rustc_attrs, negative_impls))] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index c7dccea6adc1..300e5c0b4695 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -14,7 +14,7 @@ use crate::{self as ty, Interner}; pub enum Component { Region(I::Region), Param(I::ParamTy), - Placeholder(I::PlaceholderTy), + Placeholder(ty::PlaceholderType), UnresolvedInferenceVariable(ty::InferTy), // Projections like `T::Foo` are tricky because a constraint like diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 9acf9ff8557e..e08c274f9f14 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -8,7 +8,7 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContex use rustc_type_ir_macros::GenericTypeVisitable; use self::RegionKind::*; -use crate::{BoundVarIndexKind, Interner}; +use crate::{BoundRegion, BoundVarIndexKind, Interner, PlaceholderRegion}; rustc_index::newtype_index! { /// A **region** **v**ariable **ID**. @@ -149,7 +149,7 @@ pub enum RegionKind { /// Bound regions inside of types **must not** be erased, as they impact trait /// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and /// `fn(&'static ())` are different types and have to be treated as such. - ReBound(BoundVarIndexKind, I::BoundRegion), + ReBound(BoundVarIndexKind, BoundRegion), /// Late-bound function parameters are represented using a `ReBound`. When /// inside of a function, we convert these bound variables to placeholder @@ -170,7 +170,7 @@ pub enum RegionKind { /// Should not exist outside of type inference. /// /// Used when instantiating a `forall` binder via `infcx.enter_forall`. - RePlaceholder(I::PlaceholderRegion), + RePlaceholder(PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. ReErased, @@ -214,9 +214,9 @@ impl fmt::Debug for RegionKind { impl HashStable for RegionKind where I::EarlyParamRegion: HashStable, - I::BoundRegion: HashStable, I::LateParamRegion: HashStable, - I::PlaceholderRegion: HashStable, + I::DefId: HashStable, + I::Symbol: HashStable, { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 498797bef653..7cb71387e868 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -233,7 +233,7 @@ pub enum TyKind { /// /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html - Bound(BoundVarIndexKind, I::BoundTy), + Bound(BoundVarIndexKind, ty::BoundTy), /// A placeholder type, used during higher ranked subtyping to instantiate /// bound variables. @@ -243,7 +243,7 @@ pub enum TyKind { /// to the bound variable's index from the binder from which it was instantiated), /// and `U` is the universe index in which it is instantiated, or totally omitted /// if the universe index is zero. - Placeholder(I::PlaceholderTy), + Placeholder(ty::PlaceholderType), /// A type variable used during type checking. /// diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index cd1c2ea8fcd1..263bb1036d8c 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -5,7 +5,7 @@ #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use core::alloc::*; -use core::ptr::{self, NonNull}; +use core::ptr::{self, Alignment, NonNull}; use core::{cmp, hint}; unsafe extern "Rust" { @@ -18,19 +18,19 @@ unsafe extern "Rust" { #[rustc_nounwind] #[rustc_std_internal_symbol] #[rustc_allocator_zeroed_variant = "__rust_alloc_zeroed"] - fn __rust_alloc(size: usize, align: usize) -> *mut u8; + fn __rust_alloc(size: usize, align: Alignment) -> *mut u8; #[rustc_deallocator] #[rustc_nounwind] #[rustc_std_internal_symbol] - fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + fn __rust_dealloc(ptr: *mut u8, size: usize, align: Alignment); #[rustc_reallocator] #[rustc_nounwind] #[rustc_std_internal_symbol] - fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; + fn __rust_realloc(ptr: *mut u8, old_size: usize, align: Alignment, new_size: usize) -> *mut u8; #[rustc_allocator_zeroed] #[rustc_nounwind] #[rustc_std_internal_symbol] - fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + fn __rust_alloc_zeroed(size: usize, align: Alignment) -> *mut u8; #[rustc_nounwind] #[rustc_std_internal_symbol] @@ -92,7 +92,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { // stable code until it is actually stabilized. __rust_no_alloc_shim_is_unstable_v2(); - __rust_alloc(layout.size(), layout.align()) + __rust_alloc(layout.size(), layout.alignment()) } } @@ -112,7 +112,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { - unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } + unsafe { __rust_dealloc(ptr, layout.size(), layout.alignment()) } } /// Reallocates memory with the global allocator. @@ -132,7 +132,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } + unsafe { __rust_realloc(ptr, layout.size(), layout.alignment(), new_size) } } /// Allocates zero-initialized memory with the global allocator. @@ -175,7 +175,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { // stable code until it is actually stabilized. __rust_no_alloc_shim_is_unstable_v2(); - __rust_alloc_zeroed(layout.size(), layout.align()) + __rust_alloc_zeroed(layout.size(), layout.alignment()) } } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 0844239826bf..6391a6977b61 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1514,7 +1514,7 @@ impl Box { /// Recreate a `Box` which was previously converted to a `NonNull` pointer /// using [`Box::into_non_null_with_allocator`]: /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -1524,7 +1524,7 @@ impl Box { /// ``` /// Manually create a `Box` from scratch by using the system allocator: /// ``` - /// #![feature(allocator_api, box_vec_non_null, slice_ptr_get)] + /// #![feature(allocator_api)] /// /// use std::alloc::{Allocator, Layout, System}; /// @@ -1629,7 +1629,7 @@ impl Box { /// Converting the `NonNull` pointer back into a `Box` with /// [`Box::from_non_null_in`] for automatic cleanup: /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -1640,7 +1640,7 @@ impl Box { /// Manual cleanup by explicitly running the destructor and deallocating /// the memory: /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::{Allocator, Layout, System}; /// diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index 338c7ac7f887..e0d88b27672e 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -477,9 +477,8 @@ impl PartialEq for ByteString { macro_rules! impl_partial_eq_ord_cow { ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { let other: &[u8] = (&**other).as_ref(); @@ -487,9 +486,8 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { let this: &[u8] = (&**self).as_ref(); @@ -497,9 +495,8 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$rhs> for $lhs { + impl PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { let other: &[u8] = (&**other).as_ref(); @@ -507,9 +504,8 @@ macro_rules! impl_partial_eq_ord_cow { } } - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$lhs> for $rhs { + impl PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { let this: &[u8] = (&**self).as_ref(); @@ -667,9 +663,9 @@ impl From> for Arc<[u8]> { impl_partial_eq!(ByteStr, Vec); // PartialOrd with `String` omitted to avoid inference failures impl_partial_eq!(ByteStr, String); -impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, ByteStr>); -impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, str>); -impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, [u8]>); +impl_partial_eq_ord_cow!(&ByteStr, Cow<'_, ByteStr>); +impl_partial_eq_ord_cow!(&ByteStr, Cow<'_, str>); +impl_partial_eq_ord_cow!(&ByteStr, Cow<'_, [u8]>); #[unstable(feature = "bstr", issue = "134915")] impl<'a> TryFrom<&'a ByteStr> for String { diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 5710b2a3a91d..4ddfcde57280 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -581,6 +581,40 @@ impl BinaryHeap { pub fn with_capacity_in(capacity: usize, alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::with_capacity_in(capacity, alloc) } } + + /// Creates a `BinaryHeap` using the supplied `vec`. This does not rebuild the heap, + /// so `vec` must already be a max-heap. + /// + /// # Safety + /// + /// The supplied `vec` must be a max-heap, i.e. for all indices `0 < i < vec.len()`, + /// `vec[(i - 1) / 2] >= vec[i]`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_from_raw_vec)] + /// + /// use std::collections::BinaryHeap; + /// let heap = BinaryHeap::from([1, 2, 3]); + /// let vec = heap.into_vec(); + /// + /// // Safety: vec is the output of heap.from_vec(), so is a max-heap. + /// let mut new_heap = unsafe { + /// BinaryHeap::from_raw_vec(vec) + /// }; + /// assert_eq!(new_heap.pop(), Some(3)); + /// assert_eq!(new_heap.pop(), Some(2)); + /// assert_eq!(new_heap.pop(), Some(1)); + /// assert_eq!(new_heap.pop(), None); + /// ``` + #[unstable(feature = "binary_heap_from_raw_vec", issue = "152500")] + #[must_use] + pub unsafe fn from_raw_vec(vec: Vec) -> BinaryHeap { + BinaryHeap { data: vec } + } } impl BinaryHeap { @@ -649,6 +683,33 @@ impl BinaryHeap { }) } + /// Removes and returns the greatest item from the binary heap if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the heap + /// is empty (the predicate will not be called in that case). + /// + /// # Examples + /// + /// ``` + /// #![feature(binary_heap_pop_if)] + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from([1, 2]); + /// let pred = |x: &i32| *x % 2 == 0; + /// + /// assert_eq!(heap.pop_if(pred), Some(2)); + /// assert_eq!(heap.as_slice(), [1]); + /// assert_eq!(heap.pop_if(pred), None); + /// assert_eq!(heap.as_slice(), [1]); + /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop_if` on a heap containing *n* elements is *O*(log(*n*)). + #[unstable(feature = "binary_heap_pop_if", issue = "151828")] + pub fn pop_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option { + let first = self.peek()?; + if predicate(first) { self.pop() } else { None } + } + /// Pushes an item onto the binary heap. /// /// # Examples diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6cab5728a281..3889fca30bc8 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -854,7 +854,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::LinkedList; /// /// let mut dl = LinkedList::from([1, 2, 3]); @@ -863,7 +862,7 @@ impl LinkedList { /// *ptr += 4; /// assert_eq!(dl.front().unwrap(), &6); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `LinkedList::push_front` instead"] pub fn push_front_mut(&mut self, elt: T) -> &mut T { let mut node = @@ -926,7 +925,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::LinkedList; /// /// let mut dl = LinkedList::from([1, 2, 3]); @@ -935,7 +933,7 @@ impl LinkedList { /// *ptr += 4; /// assert_eq!(dl.back().unwrap(), &6); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `LinkedList::push_back` instead"] pub fn push_back_mut(&mut self, elt: T) -> &mut T { let mut node = diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c51317a1a68f..eda29db44257 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2168,7 +2168,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut d = VecDeque::from([1, 2, 3]); @@ -2176,7 +2175,7 @@ impl VecDeque { /// *x -= 1; /// assert_eq!(d.front(), Some(&7)); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::push_front` instead"] pub fn push_front_mut(&mut self, value: T) -> &mut T { if self.is_full() { @@ -2212,7 +2211,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut d = VecDeque::from([1, 2, 3]); @@ -2220,7 +2218,7 @@ impl VecDeque { /// *x += 1; /// assert_eq!(d.back(), Some(&10)); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::push_back` instead"] pub fn push_back_mut(&mut self, value: T) -> &mut T { if self.is_full() { @@ -2419,7 +2417,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut vec_deque = VecDeque::from([1, 2, 3]); @@ -2428,7 +2425,7 @@ impl VecDeque { /// *x += 7; /// assert_eq!(vec_deque, &[1, 12, 2, 3]); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::insert` instead"] pub fn insert_mut(&mut self, index: usize, value: T) -> &mut T { assert!(index <= self.len(), "index out of bounds"); diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index d6dcba7107a9..fba967c04895 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -103,6 +103,7 @@ use crate::vec::Vec; /// and other memory errors. #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[rustc_diagnostic_item = "cstring_type"] +#[rustc_insignificant_dtor] #[stable(feature = "alloc_c_string", since = "1.64.0")] pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. @@ -694,7 +695,6 @@ impl CString { // memory-unsafe code from working by accident. Inline // to prevent LLVM from optimizing it away in debug builds. #[stable(feature = "cstring_drop", since = "1.13.0")] -#[rustc_insignificant_dtor] impl Drop for CString { #[inline] fn drop(&mut self) { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f7167650635d..3d94554281d4 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -56,6 +56,7 @@ //! [`Rc`]: rc //! [`RefCell`]: core::cell +#![allow(unused_features)] #![allow(incomplete_features)] #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] @@ -85,14 +86,11 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))] #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(ascii_char)] -#![feature(assert_matches)] #![feature(async_fn_traits)] #![feature(async_iterator)] -#![feature(box_vec_non_null)] #![feature(bstr)] #![feature(bstr_internals)] #![feature(cast_maybe_uninit)] @@ -149,7 +147,6 @@ #![feature(slice_ptr_get)] #![feature(slice_range)] #![feature(std_internals)] -#![feature(str_internals)] #![feature(temporary_niche_types)] #![feature(transmutability)] #![feature(trivial_clone)] @@ -159,7 +156,6 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(try_trait_v2_residual)] -#![feature(try_with_capacity)] #![feature(tuple_trait)] #![feature(ub_checks)] #![feature(unicode_internals)] @@ -177,10 +173,8 @@ #![feature(const_trait_impl)] #![feature(coroutine_trait)] #![feature(decl_macro)] -#![feature(derive_const)] #![feature(dropck_eyepatch)] #![feature(fundamental)] -#![feature(hashmap_internals)] #![feature(intrinsics)] #![feature(lang_items)] #![feature(min_specialization)] diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index e772ac25a95c..8a3326c7d76a 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -411,9 +411,8 @@ impl str { fn map_uppercase_sigma(from: &str, i: usize) -> char { // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 // for the definition of `Final_Sigma`. - debug_assert!('Σ'.len_utf8() == 2); let is_word_final = case_ignorable_then_cased(from[..i].chars().rev()) - && !case_ignorable_then_cased(from[i + 2..].chars()); + && !case_ignorable_then_cased(from[i + const { 'Σ'.len_utf8() }..].chars()); if is_word_final { 'ς' } else { 'σ' } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 4100ee55a4c7..30e52f3e1be4 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2661,8 +2661,7 @@ impl<'b> Pattern for &'b String { macro_rules! impl_eq { ($lhs:ty, $rhs: ty) => { #[stable(feature = "rust1", since = "1.0.0")] - #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) @@ -2674,8 +2673,7 @@ macro_rules! impl_eq { } #[stable(feature = "rust1", since = "1.0.0")] - #[allow(unused_lifetimes)] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) @@ -2689,13 +2687,13 @@ macro_rules! impl_eq { } impl_eq! { String, str } -impl_eq! { String, &'a str } +impl_eq! { String, &str } #[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, str } +impl_eq! { Cow<'_, str>, str } #[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, &'b str } +impl_eq! { Cow<'_, str>, &'_ str } #[cfg(not(no_global_oom_handling))] -impl_eq! { Cow<'a, str>, String } +impl_eq! { Cow<'_, str>, String } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a5e4fab916ab..dc82357dd146 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3270,7 +3270,7 @@ impl Weak { // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner // value can be initialized after `Weak` references have already been created. In that case, we // expect to observe the fully initialized value. - if self.inner()?.strong.fetch_update(Acquire, Relaxed, checked_increment).is_ok() { + if self.inner()?.strong.try_update(Acquire, Relaxed, checked_increment).is_ok() { // SAFETY: pointer is not null, verified in checked_increment unsafe { Some(Arc::from_inner_in(self.ptr, self.alloc.clone())) } } else { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index aaf22e80ec60..11a498d09d3f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1003,9 +1003,6 @@ const impl Vec { /// # Examples /// /// ``` - /// #![feature(push_mut)] - /// - /// /// let mut vec = vec![1, 2]; /// let last = vec.push_mut(3); /// assert_eq!(*last, 3); @@ -1023,7 +1020,7 @@ const impl Vec { /// vector's elements to a larger allocation. This expensive operation is /// offset by the *capacity* *O*(1) insertions it allows. #[inline] - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `Vec::push` instead"] pub fn push_mut(&mut self, value: T) -> &mut T { // Inform codegen that the length does not change across grow_one(). @@ -1241,7 +1238,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -1268,7 +1265,7 @@ impl Vec { /// Using memory that was allocated elsewhere: /// /// ```rust - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::{AllocError, Allocator, Global, Layout}; /// @@ -1368,7 +1365,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -2196,7 +2193,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// let mut vec = vec![1, 3, 5, 9]; /// let x = vec.insert_mut(3, 6); /// *x += 1; @@ -2210,7 +2206,7 @@ impl Vec { /// the insertion index is 0. #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[track_caller] #[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"] pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T { @@ -2689,7 +2685,6 @@ impl Vec { /// Takes *O*(1) time. #[inline] #[unstable(feature = "vec_push_within_capacity", issue = "100486")] - // #[unstable(feature = "push_mut", issue = "135974")] pub fn push_within_capacity(&mut self, value: T) -> Result<&mut T, T> { if self.len == self.buf.capacity() { return Err(value); diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index fe14480102e3..e09d8495fdea 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -16,8 +16,6 @@ // tidy-alphabetical-start #![feature(allocator_api)] #![feature(array_into_iter_constructors)] -#![feature(assert_matches)] -#![feature(box_vec_non_null)] #![feature(char_internals)] #![feature(const_alloc_error)] #![feature(const_cmp)] @@ -56,16 +54,12 @@ // // Language features: // tidy-alphabetical-start -#![feature(cfg_sanitize)] #![feature(const_trait_impl)] #![feature(dropck_eyepatch)] -#![feature(lang_items)] #![feature(min_specialization)] -#![feature(negative_impls)] #![feature(never_type)] #![feature(optimize_attribute)] #![feature(prelude_import)] -#![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_attrs)] #![feature(staged_api)] #![feature(test)] diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index 95f4c3e614f5..e1484c32a4f8 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -136,6 +136,18 @@ fn test_peek_and_pop() { } } +#[test] +fn test_pop_if() { + let data = vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from(data); + while let Some(popped) = heap.pop_if(|x| *x > 2) { + assert_eq!(popped, sorted.pop().unwrap()); + } + assert_eq!(heap.into_sorted_vec(), vec![0, 1, 2]); +} + #[test] fn test_peek_mut() { let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 2926248edbf5..699a5010282b 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -1,9 +1,8 @@ #![feature(allocator_api)] +#![feature(binary_heap_pop_if)] #![feature(const_heap)] #![feature(deque_extend_front)] #![feature(iter_array_chunks)] -#![feature(assert_matches)] -#![feature(wtf8_internals)] #![feature(cow_is_borrowed)] #![feature(core_intrinsics)] #![feature(downcast_unchecked)] @@ -30,8 +29,6 @@ #![feature(string_remove_matches)] #![feature(const_btree_len)] #![feature(const_trait_impl)] -#![feature(panic_update_hook)] -#![feature(pointer_is_aligned_to)] #![feature(test)] #![feature(thin_box)] #![feature(drain_keep_rest)] diff --git a/library/alloctests/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs index d321f8df5189..09b76773d6b2 100644 --- a/library/alloctests/tests/sort/tests.rs +++ b/library/alloctests/tests/sort/tests.rs @@ -362,6 +362,13 @@ fn sort_vs_sort_by_impl() { assert_eq!(input_sort_by, expected); } +pub fn box_value_impl() { + for len in [3, 9, 35, 56, 132] { + test_is_sorted::, S>(len, Box::new, patterns::random); + test_is_sorted::, S>(len, Box::new, |len| patterns::random_sorted(len, 80.0)); + } +} + gen_sort_test_fns_with_default_patterns!( correct_i32, |len, pattern_fn| test_is_sorted::(len, |val| val, pattern_fn), @@ -967,6 +974,7 @@ define_instantiate_sort_tests!( [miri_yes, fixed_seed_rand_vec_prefix], [miri_yes, int_edge], [miri_yes, sort_vs_sort_by], + [miri_yes, box_value], [miri_yes, correct_i32_random], [miri_yes, correct_i32_random_z1], [miri_yes, correct_i32_random_d2], diff --git a/library/alloctests/tests/str.rs b/library/alloctests/tests/str.rs index fcc4aaaa1dcd..52cc8afeee90 100644 --- a/library/alloctests/tests/str.rs +++ b/library/alloctests/tests/str.rs @@ -612,14 +612,14 @@ mod slice_index { data: "abcdef"; good: data[4..4] == ""; bad: data[4..3]; - message: "begin <= end (4 <= 3)"; + message: "begin > end (4 > 3)"; } in mod rangeinclusive_neg_width { data: "abcdef"; good: data[4..=3] == ""; bad: data[4..=2]; - message: "begin <= end (4 <= 3)"; + message: "begin > end (4 > 3)"; } } @@ -630,13 +630,13 @@ mod slice_index { // note: using 0 specifically ensures that the result of overflowing is 0..0, // so that `get` doesn't simply return None for the wrong reason. bad: data[0..=usize::MAX]; - message: "maximum usize"; + message: "out of bounds"; } in mod rangetoinclusive { data: "hello"; bad: data[..=usize::MAX]; - message: "maximum usize"; + message: "out of bounds"; } } } @@ -659,49 +659,49 @@ mod slice_index { data: super::DATA; bad: data[super::BAD_START..super::GOOD_END]; message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; } in mod range_2 { data: super::DATA; bad: data[super::GOOD_START..super::BAD_END]; message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; } in mod rangefrom { data: super::DATA; bad: data[super::BAD_START..]; message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; } in mod rangeto { data: super::DATA; bad: data[..super::BAD_END]; message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; } in mod rangeinclusive_1 { data: super::DATA; bad: data[super::BAD_START..=super::GOOD_END_INCL]; message: - "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; } in mod rangeinclusive_2 { data: super::DATA; bad: data[super::GOOD_START..=super::BAD_END_INCL]; message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; } in mod rangetoinclusive { data: super::DATA; bad: data[..=super::BAD_END_INCL]; message: - "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; } } } @@ -716,7 +716,9 @@ mod slice_index { // check the panic includes the prefix of the sliced string #[test] - #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] + #[should_panic( + expected = "end byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet" + )] fn test_slice_fail_truncated_1() { let _ = &LOREM_PARAGRAPH[..1024]; } diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 699a9c417dde..3fed58f2a207 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -70,12 +70,14 @@ jobs: os: ubuntu-24.04 - target: powerpc64le-unknown-linux-gnu os: ubuntu-24.04 - - target: powerpc64le-unknown-linux-gnu - os: ubuntu-24.04-ppc64le + # - target: powerpc64le-unknown-linux-gnu + # os: ubuntu-24.04-ppc64le + # # FIXME(rust#151807): remove once PPC builds work again. + # channel: nightly-2026-01-23 - target: riscv64gc-unknown-linux-gnu os: ubuntu-24.04 - - target: s390x-unknown-linux-gnu - os: ubuntu-24.04-s390x + # - target: s390x-unknown-linux-gnu + # os: ubuntu-24.04-s390x - target: thumbv6m-none-eabi os: ubuntu-24.04 - target: thumbv7em-none-eabi @@ -228,7 +230,27 @@ jobs: # poorly with build scripts) cargo build -p compiler_builtins -p libm \ --target etc/thumbv7em-none-eabi-renamed.json \ - -Zbuild-std=core + -Zbuild-std=core \ + -Zjson-target-spec + + # FIXME: move this target to test job once https://github.com/rust-lang/rust/pull/150138 merged. + build-thumbv6k: + name: Build thumbv6k + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup component add rust-src + - uses: Swatinem/rust-cache@v2 + - run: | + cargo build -p compiler_builtins -p libm \ + --target etc/thumbv6-none-eabi.json \ + -Zbuild-std=core \ + -Zjson-target-spec benchmarks: name: Benchmarks @@ -354,6 +376,7 @@ jobs: needs: - benchmarks - build-custom + - build-thumbv6k - clippy - extensive - miri diff --git a/library/compiler-builtins/.github/workflows/rustc-pull.yml b/library/compiler-builtins/.github/workflows/rustc-pull.yml index 617db14f46ee..8e88213332de 100644 --- a/library/compiler-builtins/.github/workflows/rustc-pull.yml +++ b/library/compiler-builtins/.github/workflows/rustc-pull.yml @@ -7,6 +7,9 @@ on: # Run at 04:00 UTC every Monday and Thursday - cron: '0 4 * * 1,4' +env: + JOSH_SYNC_VERBOSE: true + jobs: pull: if: github.repository == 'rust-lang/compiler-builtins' diff --git a/library/compiler-builtins/Cargo.toml b/library/compiler-builtins/Cargo.toml index 8501f4e630b5..26f67e02fc52 100644 --- a/library/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/Cargo.toml @@ -31,6 +31,39 @@ exclude = [ "compiler-builtins", ] +[workspace.dependencies] +anyhow = "1.0.101" +assert_cmd = "2.1.2" +cc = "1.2.55" +compiler_builtins = { path = "builtins-shim", default-features = false } +criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } +getrandom = "0.3.4" +gmp-mpfr-sys = { version = "1.6.8", default-features = false } +gungraun = "0.17.0" +heck = "0.5.0" +indicatif = { version = "0.18.3", default-features = false } +libm = { path = "libm", default-features = false } +libm-macros = { path = "crates/libm-macros" } +libm-test = { path = "libm-test", default-features = false } +libtest-mimic = "0.8.1" +musl-math-sys = { path = "crates/musl-math-sys" } +no-panic = "0.1.35" +object = { version = "0.37.3", features = ["wasm"] } +panic-handler = { path = "crates/panic-handler" } +paste = "1.0.15" +proc-macro2 = "1.0.106" +quote = "1.0.44" +rand = "0.9.2" +rand_chacha = "0.9.0" +rand_xoshiro = "0.7" +rayon = "1.11.0" +regex = "1.12.3" +rug = { version = "1.28.1", default-features = false, features = ["float", "integer", "std"] } +rustc_apfloat = "0.2.3" +serde_json = "1.0.149" +syn = "2.0.114" +tempfile = "3.24.0" + [profile.release] panic = "abort" @@ -51,6 +84,7 @@ codegen-units = 1 lto = "fat" [profile.bench] +codegen-units = 1 # Required for gungraun debug = true strip = false diff --git a/library/compiler-builtins/builtins-shim/Cargo.toml b/library/compiler-builtins/builtins-shim/Cargo.toml index 746d5b21dc3f..37d3407e9f66 100644 --- a/library/compiler-builtins/builtins-shim/Cargo.toml +++ b/library/compiler-builtins/builtins-shim/Cargo.toml @@ -7,6 +7,9 @@ # manifest that is identical except for the `core` dependency and forwards # to the same sources, which acts as the `compiler-builtins` Cargo entrypoint # for out of tree testing +# +# Ideally we can eventually replace this with a patch in the workspace +# manifest . [package] name = "compiler_builtins" @@ -33,7 +36,7 @@ doctest = false test = false [build-dependencies] -cc = { optional = true, version = "1.2" } +cc = { version = "1.2", optional = true } [features] default = ["compiler-builtins"] diff --git a/library/compiler-builtins/builtins-test/Cargo.toml b/library/compiler-builtins/builtins-test/Cargo.toml index 550f736a76db..9395ab1a985e 100644 --- a/library/compiler-builtins/builtins-test/Cargo.toml +++ b/library/compiler-builtins/builtins-test/Cargo.toml @@ -6,23 +6,22 @@ publish = false license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" [dependencies] +compiler_builtins = { workspace = true, features = ["unstable-public-internals"] } + # For fuzzing tests we want a deterministic seedable RNG. We also eliminate potential # problems with system RNGs on the variety of platforms this crate is tested on. # `xoshiro128**` is used for its quality, size, and speed at generating `u32` shift amounts. -rand_xoshiro = "0.7" -# To compare float builtins against -rustc_apfloat = "0.2.3" -# Really a dev dependency, but dev dependencies can't be optional -gungraun = { version = "0.17.0", optional = true } +rand_xoshiro.workspace = true -[dependencies.compiler_builtins] -path = "../builtins-shim" -default-features = false -features = ["unstable-public-internals"] +# To compare float builtins against +rustc_apfloat.workspace = true + +# Really a dev dependency, but dev dependencies can't be optional +gungraun = { workspace = true, optional = true } [dev-dependencies] -criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } -paste = "1.0.15" +criterion.workspace = true +paste.workspace = true [target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies] test = { git = "https://github.com/japaric/utest" } diff --git a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 69b99f5b6b32..683bd07fd47e 100644 --- a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-aarch64-linux-gnu m4 make libc6-dev-arm64-cross \ - qemu-user-static + qemu-user ENV TOOLCHAIN_PREFIX=aarch64-linux-gnu- ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64-static \ + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64 \ AR_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile index 2fa6f8520520..781abd1b6e88 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user-static + gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabi- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabi \ diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile index 85f7335f5a85..36ea4827dc52 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ diff --git a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile index 42511479f36f..8b76693b2799 100644 --- a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ diff --git a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile index 35488c477493..9125038acbde 100644 --- a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile index 35488c477493..9125038acbde 100644 --- a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index e95a1b9163ff..a65223595877 100644 --- a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -1,13 +1,13 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-14-loongarch64-linux-gnu libc6-dev-loong64-cross ENV CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER=loongarch64-linux-gnu-gcc-14 \ - CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-loongarch64-static \ + CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-loongarch64 \ AR_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-ar \ CC_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-gcc-14 \ QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile index fd1877603100..0913f33c05ce 100644 --- a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-mips-linux-gnu libc6-dev-mips-cross \ - binfmt-support qemu-user-static qemu-system-mips + binfmt-support qemu-user qemu-system-mips ENV TOOLCHAIN_PREFIX=mips-linux-gnu- ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips-static \ + CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips \ AR_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile index 4e542ce6858c..d2f4e484b1aa 100644 --- a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ @@ -8,12 +8,12 @@ RUN apt-get update && \ gcc-mips64-linux-gnuabi64 \ libc6-dev \ libc6-dev-mips64-cross \ - qemu-user-static \ + qemu-user \ qemu-system-mips ENV TOOLCHAIN_PREFIX=mips64-linux-gnuabi64- ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64-static \ + CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64 \ AR_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 \ diff --git a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile index 528dfd8940d5..873754b2793e 100644 --- a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ @@ -8,11 +8,11 @@ RUN apt-get update && \ gcc-mips64el-linux-gnuabi64 \ libc6-dev \ libc6-dev-mips64el-cross \ - qemu-user-static + qemu-user ENV TOOLCHAIN_PREFIX=mips64el-linux-gnuabi64- ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el-static \ + CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el \ AR_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ diff --git a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile index 2572180238e2..5768b68d6c95 100644 --- a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ - binfmt-support qemu-user-static + binfmt-support qemu-user ENV TOOLCHAIN_PREFIX=mipsel-linux-gnu- ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel-static \ + CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel \ AR_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile index cac1f23610aa..c625a4bcd5d7 100644 --- a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc-linux-gnu- ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc-static \ + CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc \ AR_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile index 76127b7dbb8c..86a7a8cd46e4 100644 --- a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ - binfmt-support qemu-user-static qemu-system-ppc + binfmt-support qemu-user qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc64-linux-gnu- ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64-static \ + CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64 \ AR_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile index da1d56ca66f2..722b10b0a734 100644 --- a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc64le-linux-gnu- ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le-static \ + CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le \ AR_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile index 513efacd6d96..7a721ba05416 100644 --- a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-riscv64-linux-gnu libc6-dev-riscv64-cross \ qemu-system-riscv64 ENV TOOLCHAIN_PREFIX=riscv64-linux-gnu- ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64-static \ + CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64 \ AR_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/riscv64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile index 2813d318670e..b646a72bb37c 100644 --- a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile +++ b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:20.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index 2ef800129d67..927515f90f32 100644 --- a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/run-docker.sh b/library/compiler-builtins/ci/run-docker.sh index 4c1fe0fe2644..e65ada271904 100755 --- a/library/compiler-builtins/ci/run-docker.sh +++ b/library/compiler-builtins/ci/run-docker.sh @@ -97,7 +97,7 @@ if [ "${1:-}" = "--help" ] || [ "$#" -gt 1 ]; then usage: ./ci/run-docker.sh [target] you can also set DOCKER_BASE_IMAGE to use something other than the default - ubuntu:25.04 (or rustlang/rust:nightly). + ubuntu:25.10 (or rustlang/rust:nightly). " exit fi diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index 0c07b32c74b9..12b3f37889c9 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -13,11 +13,6 @@ if [ -z "$target" ]; then target="$host_target" fi -if [[ "$target" = *"wasm"* ]]; then - # Enable the random backend - export RUSTFLAGS="${RUSTFLAGS:-} --cfg getrandom_backend=\"wasm_js\"" -fi - if [ "${USING_CONTAINER_RUSTC:-}" = 1 ]; then # Install nonstandard components if we have control of the environment rustup target list --installed | @@ -51,8 +46,8 @@ fi # Ensure there are no duplicate symbols or references to `core` when # `compiler-builtins` is built with various features. Symcheck invokes Cargo to # build with the arguments we provide it, then validates the built artifacts. +SYMCHECK_TEST_TARGET="$target" cargo test -p symbol-check --release symcheck=(cargo run -p symbol-check --release) -[[ "$target" = "wasm"* ]] && symcheck+=(--features wasm) symcheck+=(-- build-and-check) "${symcheck[@]}" "$target" -- -p compiler_builtins @@ -157,7 +152,8 @@ if [ "${BUILD_ONLY:-}" = "1" ]; then echo "can't run tests on $target; skipping" else - mflags+=(--workspace --target "$target") + # symcheck tests need specific env setup, and is already tested above + mflags+=(--workspace --exclude symbol-check --target "$target") cmd=(cargo test "${mflags[@]}") profile_flag="--profile" diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml index 496dde2d4cf2..a8b8920421b3 100644 --- a/library/compiler-builtins/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/compiler-builtins/Cargo.toml @@ -31,7 +31,7 @@ doc = false core = { path = "../../core", optional = true } [build-dependencies] -cc = { optional = true, version = "1.2" } +cc = { version = "1.2", optional = true } [features] default = ["compiler-builtins"] diff --git a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s index 97d05eb1839e..6cd1f1b79f87 100644 --- a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s +++ b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s @@ -7,7 +7,7 @@ .p2align 5 __hexagon_fmadf4: __hexagon_fmadf5: -fma: +.Lfma: { p0 = dfclass(r1:0,#2) p0 = dfclass(r3:2,#2) @@ -400,7 +400,7 @@ fma: r3:2 = insert(r11:10,#63,#0) r1 -= asl(r28,#20) } - jump fma + jump .Lfma .Lfma_ab_tiny: r9:8 = combine(##0x00100000,#0) @@ -408,7 +408,7 @@ fma: r1:0 = insert(r9:8,#63,#0) r3:2 = insert(r9:8,#63,#0) } - jump fma + jump .Lfma .Lab_inf: { @@ -531,4 +531,3 @@ fma: r5 = insert(r28,#11,#20) jump .Lfma_abnormal_c_restart } -.size fma,.-fma diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index c993209699be..80395a4738eb 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -15,6 +15,7 @@ #![cfg_attr(f128_enabled, feature(f128))] #![no_builtins] #![no_std] +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable #![allow(unused_features)] #![allow(internal_features)] // `mem::swap` cannot be used because it may generate references to memcpy in unoptimized code. @@ -45,6 +46,7 @@ pub mod float; pub mod int; pub mod math; pub mod mem; +pub mod sync; // `libm` expects its `support` module to be available in the crate root. use math::libm_math::support; @@ -58,13 +60,6 @@ pub mod aarch64; #[cfg(all(target_arch = "aarch64", target_feature = "outline-atomics"))] pub mod aarch64_outline_atomics; -#[cfg(all( - kernel_user_helpers, - any(target_os = "linux", target_os = "android"), - target_arch = "arm" -))] -pub mod arm_linux; - #[cfg(target_arch = "avr")] pub mod avr; diff --git a/library/compiler-builtins/compiler-builtins/src/arm_linux.rs b/library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs similarity index 59% rename from library/compiler-builtins/compiler-builtins/src/arm_linux.rs rename to library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs index ab9f86807390..7edd76c0b8b7 100644 --- a/library/compiler-builtins/compiler-builtins/src/arm_linux.rs +++ b/library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs @@ -125,14 +125,16 @@ unsafe fn atomic_cmpxchg(ptr: *mut T, oldval: u32, newval: u32) -> u32 { let (shift, mask) = get_shift_mask(ptr); loop { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. let curval_aligned = unsafe { atomic_load_aligned::(aligned_ptr) }; let curval = extract_aligned(curval_aligned, shift, mask); if curval != oldval { return curval; } let newval_aligned = insert_aligned(curval_aligned, newval, shift, mask); - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. if unsafe { __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) } { return oldval; } @@ -143,7 +145,8 @@ macro_rules! atomic_rmw { ($name:ident, $ty:ty, $op:expr, $fetch:expr) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. unsafe { atomic_rmw( ptr, @@ -167,140 +170,15 @@ macro_rules! atomic_cmpxchg { ($name:ident, $ty:ty) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. unsafe { atomic_cmpxchg(ptr, oldval as u32, newval as u32) as $ty } } } }; } -atomic_rmw!(@old __sync_fetch_and_add_1, u8, |a: u8, b: u8| a.wrapping_add(b)); -atomic_rmw!(@old __sync_fetch_and_add_2, u16, |a: u16, b: u16| a - .wrapping_add(b)); -atomic_rmw!(@old __sync_fetch_and_add_4, u32, |a: u32, b: u32| a - .wrapping_add(b)); - -atomic_rmw!(@new __sync_add_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_add(b)); -atomic_rmw!(@new __sync_add_and_fetch_2, u16, |a: u16, b: u16| a - .wrapping_add(b)); -atomic_rmw!(@new __sync_add_and_fetch_4, u32, |a: u32, b: u32| a - .wrapping_add(b)); - -atomic_rmw!(@old __sync_fetch_and_sub_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); -atomic_rmw!(@old __sync_fetch_and_sub_2, u16, |a: u16, b: u16| a - .wrapping_sub(b)); -atomic_rmw!(@old __sync_fetch_and_sub_4, u32, |a: u32, b: u32| a - .wrapping_sub(b)); - -atomic_rmw!(@new __sync_sub_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); -atomic_rmw!(@new __sync_sub_and_fetch_2, u16, |a: u16, b: u16| a - .wrapping_sub(b)); -atomic_rmw!(@new __sync_sub_and_fetch_4, u32, |a: u32, b: u32| a - .wrapping_sub(b)); - -atomic_rmw!(@old __sync_fetch_and_and_1, u8, |a: u8, b: u8| a & b); -atomic_rmw!(@old __sync_fetch_and_and_2, u16, |a: u16, b: u16| a & b); -atomic_rmw!(@old __sync_fetch_and_and_4, u32, |a: u32, b: u32| a & b); - -atomic_rmw!(@new __sync_and_and_fetch_1, u8, |a: u8, b: u8| a & b); -atomic_rmw!(@new __sync_and_and_fetch_2, u16, |a: u16, b: u16| a & b); -atomic_rmw!(@new __sync_and_and_fetch_4, u32, |a: u32, b: u32| a & b); - -atomic_rmw!(@old __sync_fetch_and_or_1, u8, |a: u8, b: u8| a | b); -atomic_rmw!(@old __sync_fetch_and_or_2, u16, |a: u16, b: u16| a | b); -atomic_rmw!(@old __sync_fetch_and_or_4, u32, |a: u32, b: u32| a | b); - -atomic_rmw!(@new __sync_or_and_fetch_1, u8, |a: u8, b: u8| a | b); -atomic_rmw!(@new __sync_or_and_fetch_2, u16, |a: u16, b: u16| a | b); -atomic_rmw!(@new __sync_or_and_fetch_4, u32, |a: u32, b: u32| a | b); - -atomic_rmw!(@old __sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); -atomic_rmw!(@old __sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); -atomic_rmw!(@old __sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); - -atomic_rmw!(@new __sync_xor_and_fetch_1, u8, |a: u8, b: u8| a ^ b); -atomic_rmw!(@new __sync_xor_and_fetch_2, u16, |a: u16, b: u16| a ^ b); -atomic_rmw!(@new __sync_xor_and_fetch_4, u32, |a: u32, b: u32| a ^ b); - -atomic_rmw!(@old __sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); -atomic_rmw!(@old __sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); -atomic_rmw!(@old __sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); - -atomic_rmw!(@new __sync_nand_and_fetch_1, u8, |a: u8, b: u8| !(a & b)); -atomic_rmw!(@new __sync_nand_and_fetch_2, u16, |a: u16, b: u16| !(a & b)); -atomic_rmw!(@new __sync_nand_and_fetch_4, u32, |a: u32, b: u32| !(a & b)); - -atomic_rmw!(@old __sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_max_4, i32, |a: i32, b: i32| if a > b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_umax_1, u8, |a: u8, b: u8| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umax_2, u16, |a: u16, b: u16| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umax_4, u32, |a: u32, b: u32| if a > b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_min_1, i8, |a: i8, b: i8| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_min_2, i16, |a: i16, b: i16| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_min_4, i32, |a: i32, b: i32| if a < b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_umin_1, u8, |a: u8, b: u8| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umin_2, u16, |a: u16, b: u16| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umin_4, u32, |a: u32, b: u32| if a < b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_lock_test_and_set_1, u8, |_: u8, b: u8| b); -atomic_rmw!(@old __sync_lock_test_and_set_2, u16, |_: u16, b: u16| b); -atomic_rmw!(@old __sync_lock_test_and_set_4, u32, |_: u32, b: u32| b); - -atomic_cmpxchg!(__sync_val_compare_and_swap_1, u8); -atomic_cmpxchg!(__sync_val_compare_and_swap_2, u16); -atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32); +include!("arm_thumb_shared.rs"); intrinsics! { pub unsafe extern "C" fn __sync_synchronize() { diff --git a/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs b/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs new file mode 100644 index 000000000000..812989c7bc85 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs @@ -0,0 +1,134 @@ +// Used by both arm_linux.rs and thumbv6k.rs. + +// References: +// - https://llvm.org/docs/Atomics.html#libcalls-sync +// - https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html +// - https://refspecs.linuxfoundation.org/elf/IA64-SysV-psABI.pdf#page=58 + +atomic_rmw!(@old __sync_fetch_and_add_1, u8, |a: u8, b: u8| a.wrapping_add(b)); +atomic_rmw!(@old __sync_fetch_and_add_2, u16, |a: u16, b: u16| a + .wrapping_add(b)); +atomic_rmw!(@old __sync_fetch_and_add_4, u32, |a: u32, b: u32| a + .wrapping_add(b)); + +atomic_rmw!(@new __sync_add_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_add(b)); +atomic_rmw!(@new __sync_add_and_fetch_2, u16, |a: u16, b: u16| a + .wrapping_add(b)); +atomic_rmw!(@new __sync_add_and_fetch_4, u32, |a: u32, b: u32| a + .wrapping_add(b)); + +atomic_rmw!(@old __sync_fetch_and_sub_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); +atomic_rmw!(@old __sync_fetch_and_sub_2, u16, |a: u16, b: u16| a + .wrapping_sub(b)); +atomic_rmw!(@old __sync_fetch_and_sub_4, u32, |a: u32, b: u32| a + .wrapping_sub(b)); + +atomic_rmw!(@new __sync_sub_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); +atomic_rmw!(@new __sync_sub_and_fetch_2, u16, |a: u16, b: u16| a + .wrapping_sub(b)); +atomic_rmw!(@new __sync_sub_and_fetch_4, u32, |a: u32, b: u32| a + .wrapping_sub(b)); + +atomic_rmw!(@old __sync_fetch_and_and_1, u8, |a: u8, b: u8| a & b); +atomic_rmw!(@old __sync_fetch_and_and_2, u16, |a: u16, b: u16| a & b); +atomic_rmw!(@old __sync_fetch_and_and_4, u32, |a: u32, b: u32| a & b); + +atomic_rmw!(@new __sync_and_and_fetch_1, u8, |a: u8, b: u8| a & b); +atomic_rmw!(@new __sync_and_and_fetch_2, u16, |a: u16, b: u16| a & b); +atomic_rmw!(@new __sync_and_and_fetch_4, u32, |a: u32, b: u32| a & b); + +atomic_rmw!(@old __sync_fetch_and_or_1, u8, |a: u8, b: u8| a | b); +atomic_rmw!(@old __sync_fetch_and_or_2, u16, |a: u16, b: u16| a | b); +atomic_rmw!(@old __sync_fetch_and_or_4, u32, |a: u32, b: u32| a | b); + +atomic_rmw!(@new __sync_or_and_fetch_1, u8, |a: u8, b: u8| a | b); +atomic_rmw!(@new __sync_or_and_fetch_2, u16, |a: u16, b: u16| a | b); +atomic_rmw!(@new __sync_or_and_fetch_4, u32, |a: u32, b: u32| a | b); + +atomic_rmw!(@old __sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); +atomic_rmw!(@old __sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); +atomic_rmw!(@old __sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); + +atomic_rmw!(@new __sync_xor_and_fetch_1, u8, |a: u8, b: u8| a ^ b); +atomic_rmw!(@new __sync_xor_and_fetch_2, u16, |a: u16, b: u16| a ^ b); +atomic_rmw!(@new __sync_xor_and_fetch_4, u32, |a: u32, b: u32| a ^ b); + +atomic_rmw!(@old __sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); +atomic_rmw!(@old __sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); +atomic_rmw!(@old __sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); + +atomic_rmw!(@new __sync_nand_and_fetch_1, u8, |a: u8, b: u8| !(a & b)); +atomic_rmw!(@new __sync_nand_and_fetch_2, u16, |a: u16, b: u16| !(a & b)); +atomic_rmw!(@new __sync_nand_and_fetch_4, u32, |a: u32, b: u32| !(a & b)); + +atomic_rmw!(@old __sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_max_4, i32, |a: i32, b: i32| if a > b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_umax_1, u8, |a: u8, b: u8| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umax_2, u16, |a: u16, b: u16| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umax_4, u32, |a: u32, b: u32| if a > b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_min_1, i8, |a: i8, b: i8| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_min_2, i16, |a: i16, b: i16| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_min_4, i32, |a: i32, b: i32| if a < b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_umin_1, u8, |a: u8, b: u8| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umin_2, u16, |a: u16, b: u16| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umin_4, u32, |a: u32, b: u32| if a < b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_lock_test_and_set_1, u8, |_: u8, b: u8| b); +atomic_rmw!(@old __sync_lock_test_and_set_2, u16, |_: u16, b: u16| b); +atomic_rmw!(@old __sync_lock_test_and_set_4, u32, |_: u32, b: u32| b); + +atomic_cmpxchg!(__sync_val_compare_and_swap_1, u8); +atomic_cmpxchg!(__sync_val_compare_and_swap_2, u16); +atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32); diff --git a/library/compiler-builtins/compiler-builtins/src/sync/mod.rs b/library/compiler-builtins/compiler-builtins/src/sync/mod.rs new file mode 100644 index 000000000000..590db14bb23b --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/mod.rs @@ -0,0 +1,20 @@ +#[cfg(all( + kernel_user_helpers, + any(target_os = "linux", target_os = "android"), + target_arch = "arm" +))] +pub mod arm_linux; + +// Armv6k supports atomic instructions, but they are unavailable in Thumb mode +// unless Thumb-2 instructions available (v6t2). +// Using Thumb interworking allows us to use these instructions even from Thumb mode +// without Thumb-2 instructions, but LLVM does not implement that processing (as of LLVM 21), +// so we implement it here at this time. +// (`not(target_feature = "mclass")` is unneeded because v6k is not set on thumbv6m.) +#[cfg(all( + target_arch = "arm", + target_feature = "thumb-mode", + target_feature = "v6k", + not(target_feature = "v6t2"), +))] +pub mod thumbv6k; diff --git a/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs b/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs new file mode 100644 index 000000000000..c47b4c2ec6b0 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs @@ -0,0 +1,213 @@ +// Armv6k supports atomic instructions, but they are unavailable in Thumb mode +// unless Thumb-2 instructions available (v6t2). +// Using Thumb interworking allows us to use these instructions even from Thumb mode +// without Thumb-2 instructions, but LLVM does not implement that processing (as of LLVM 21), +// so we implement it here at this time. + +use core::arch::asm; +use core::mem; + +// Data Memory Barrier (DMB) operation. +// +// Armv6 does not support DMB instruction, so use use special instruction equivalent to it. +// +// Refs: https://developer.arm.com/documentation/ddi0360/f/control-coprocessor-cp15/register-descriptions/c7--cache-operations-register +macro_rules! cp15_barrier { + () => { + "mcr p15, #0, {zero}, c7, c10, #5" + }; +} + +#[instruction_set(arm::a32)] +unsafe fn fence() { + unsafe { + asm!( + cp15_barrier!(), + // cp15_barrier! calls `mcr p15, 0, {zero}, c7, c10, 5`, and + // the value in the {zero} register should be zero (SBZ). + zero = inout(reg) 0_u32 => _, + options(nostack, preserves_flags), + ); + } +} + +trait Atomic: Copy + Eq { + unsafe fn load_relaxed(src: *const Self) -> Self; + unsafe fn cmpxchg(dst: *mut Self, current: Self, new: Self) -> Self; +} + +macro_rules! atomic { + ($ty:ident, $suffix:tt) => { + impl Atomic for $ty { + // #[instruction_set(arm::a32)] is unneeded for ldr. + #[inline] + unsafe fn load_relaxed( + src: *const Self, + ) -> Self { + let out: Self; + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { + asm!( + concat!("ldr", $suffix, " {out}, [{src}]"), // atomic { out = *src } + src = in(reg) src, + out = lateout(reg) out, + options(nostack, preserves_flags), + ); + } + out + } + #[inline] + #[instruction_set(arm::a32)] + unsafe fn cmpxchg( + dst: *mut Self, + old: Self, + new: Self, + ) -> Self { + let mut out: Self; + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + // + // Instead of the common `fence; ll/sc loop; fence` form, we use the form used by + // LLVM, which omits the preceding fence if no write operation is performed. + unsafe { + asm!( + concat!("ldrex", $suffix, " {out}, [{dst}]"), // atomic { out = *dst; EXCLUSIVE = dst } + "cmp {out}, {old}", // if out == old { Z = 1 } else { Z = 0 } + "bne 3f", // if Z == 0 { jump 'cmp-fail } + cp15_barrier!(), // fence + "2:", // 'retry: + concat!("strex", $suffix, " {r}, {new}, [{dst}]"), // atomic { if EXCLUSIVE == dst { *dst = new; r = 0 } else { r = 1 }; EXCLUSIVE = None } + "cmp {r}, #0", // if r == 0 { Z = 1 } else { Z = 0 } + "beq 3f", // if Z == 1 { jump 'success } + concat!("ldrex", $suffix, " {out}, [{dst}]"), // atomic { out = *dst; EXCLUSIVE = dst } + "cmp {out}, {old}", // if out == old { Z = 1 } else { Z = 0 } + "beq 2b", // if Z == 1 { jump 'retry } + "3:", // 'cmp-fail | 'success: + cp15_barrier!(), // fence + dst = in(reg) dst, + // Note: this cast must be a zero-extend since loaded value + // which compared to it is zero-extended. + old = in(reg) u32::from(old), + new = in(reg) new, + out = out(reg) out, + r = out(reg) _, + // cp15_barrier! calls `mcr p15, 0, {zero}, c7, c10, 5`, and + // the value in the {zero} register should be zero (SBZ). + zero = inout(reg) 0_u32 => _, + // Do not use `preserves_flags` because CMP modifies the condition flags. + options(nostack), + ); + out + } + } + } + }; +} +atomic!(u8, "b"); +atomic!(u16, "h"); +atomic!(u32, ""); + +// To avoid the annoyance of sign extension, we implement signed CAS using +// unsigned CAS. (See note in cmpxchg impl in atomic! macro) +macro_rules! delegate_signed { + ($ty:ident, $base:ident) => { + const _: () = { + assert!(mem::size_of::<$ty>() == mem::size_of::<$base>()); + assert!(mem::align_of::<$ty>() == mem::align_of::<$base>()); + }; + impl Atomic for $ty { + #[inline] + unsafe fn load_relaxed(src: *const Self) -> Self { + // SAFETY: the caller must uphold the safety contract. + // casts are okay because $ty and $base implement the same layout. + unsafe { <$base as Atomic>::load_relaxed(src.cast::<$base>()).cast_signed() } + } + #[inline] + unsafe fn cmpxchg(dst: *mut Self, old: Self, new: Self) -> Self { + // SAFETY: the caller must uphold the safety contract. + // casts are okay because $ty and $base implement the same layout. + unsafe { + <$base as Atomic>::cmpxchg( + dst.cast::<$base>(), + old.cast_unsigned(), + new.cast_unsigned(), + ) + .cast_signed() + } + } + } + }; +} +delegate_signed!(i8, u8); +delegate_signed!(i16, u16); +delegate_signed!(i32, u32); + +// Generic atomic read-modify-write operation +// +// We could implement RMW more efficiently as an assembly LL/SC loop per operation, +// but we won't do that for now because it would make the implementation more complex. +// +// We also do not implement LL and SC as separate functions. This is because it +// is theoretically possible for the compiler to insert operations that might +// clear the reservation between LL and SC. See https://github.com/taiki-e/portable-atomic/blob/58ef7f27c9e20da4cc1ef0abf8b8ce9ac5219ec3/src/imp/atomic128/aarch64.rs#L44-L55 +// for more details. +unsafe fn atomic_rmw T, G: Fn(T, T) -> T>(ptr: *mut T, f: F, g: G) -> T { + loop { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + let curval = unsafe { T::load_relaxed(ptr) }; + let newval = f(curval); + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + if unsafe { T::cmpxchg(ptr, curval, newval) } == curval { + return g(curval, newval); + } + } +} + +macro_rules! atomic_rmw { + ($name:ident, $ty:ty, $op:expr, $fetch:expr) => { + intrinsics! { + pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { + atomic_rmw( + ptr, + |x| $op(x as $ty, val), + |old, new| $fetch(old, new) + ) as $ty + } + } + } + }; + + (@old $name:ident, $ty:ty, $op:expr) => { + atomic_rmw!($name, $ty, $op, |old, _| old); + }; + + (@new $name:ident, $ty:ty, $op:expr) => { + atomic_rmw!($name, $ty, $op, |_, new| new); + }; +} +macro_rules! atomic_cmpxchg { + ($name:ident, $ty:ty) => { + intrinsics! { + pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { <$ty as Atomic>::cmpxchg(ptr, oldval, newval) } + } + } + }; +} + +include!("arm_thumb_shared.rs"); + +intrinsics! { + pub unsafe extern "C" fn __sync_synchronize() { + // SAFETY: preconditions are the same as the calling function. + unsafe { fence() }; + } +} diff --git a/library/compiler-builtins/crates/libm-macros/Cargo.toml b/library/compiler-builtins/crates/libm-macros/Cargo.toml index 100a8d0ec30e..f99a92e21c70 100644 --- a/library/compiler-builtins/crates/libm-macros/Cargo.toml +++ b/library/compiler-builtins/crates/libm-macros/Cargo.toml @@ -9,10 +9,10 @@ license = "MIT OR Apache-2.0" proc-macro = true [dependencies] -heck = "0.5.0" -proc-macro2 = "1.0.95" -quote = "1.0.40" -syn = { version = "2.0.104", features = ["full", "extra-traits", "visit-mut"] } +heck.workspace = true +proc-macro2.workspace = true +quote.workspace = true +syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] } [lints.rust] # Values used during testing diff --git a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml index 39f6fa9065bd..eb97ffbc8669 100644 --- a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml +++ b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml @@ -5,10 +5,8 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" -[dependencies] - [dev-dependencies] -libm = { path = "../../libm" } +libm.workspace = true [build-dependencies] -cc = "1.2.29" +cc.workspace = true diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index e2218b491720..5bc13d337c27 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -5,8 +5,11 @@ edition = "2024" publish = false [dependencies] -object = "0.37.1" -serde_json = "1.0.140" +object.workspace = true +regex.workspace = true +serde_json.workspace = true -[features] -wasm = ["object/wasm"] +[dev-dependencies] +assert_cmd.workspace = true +cc.workspace = true +tempfile.workspace = true diff --git a/library/compiler-builtins/crates/symbol-check/build.rs b/library/compiler-builtins/crates/symbol-check/build.rs new file mode 100644 index 000000000000..b3e53c38b0bd --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/build.rs @@ -0,0 +1,6 @@ +use std::env; + +fn main() { + println!("cargo::rustc-env=HOST={}", env::var("HOST").unwrap()); + println!("cargo::rustc-env=TARGET={}", env::var("TARGET").unwrap()); +} diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs index 7d0b7e90addb..733d9f4e8bef 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symbol-check/src/main.rs @@ -1,17 +1,22 @@ //! Tool used by CI to inspect compiler-builtins archives and help ensure we won't run into any //! linking errors. +//! +//! Note that symcheck is a "hostprog", i.e. is built and run on the host target even when the +//! actual target is cross compiled. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fs; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::sync::LazyLock; use object::read::archive::ArchiveFile; use object::{ File as ObjFile, Object, ObjectSection, ObjectSymbol, Result as ObjResult, Symbol, SymbolKind, SymbolScope, }; +use regex::Regex; use serde_json::Value; const CHECK_LIBRARIES: &[&str] = &["compiler_builtins", "builtins_test_intrinsics"]; @@ -42,8 +47,7 @@ fn main() { run_build_and_check(target, args); } ["build-and-check", "--", args @ ..] if !args.is_empty() => { - let target = &host_target(); - run_build_and_check(target, args); + run_build_and_check(env!("HOST"), args); } ["check", paths @ ..] if !paths.is_empty() => { check_paths(paths); @@ -80,20 +84,6 @@ fn check_paths>(paths: &[P]) { } } -fn host_target() -> String { - let out = Command::new("rustc") - .arg("--version") - .arg("--verbose") - .output() - .unwrap(); - assert!(out.status.success()); - let out = String::from_utf8(out.stdout).unwrap(); - out.lines() - .find_map(|s| s.strip_prefix("host: ")) - .unwrap() - .to_owned() -} - /// Run `cargo build` with the provided additional arguments, collecting the list of created /// libraries. fn exec_cargo_with_args(target: &str, args: &[&str]) -> Vec { @@ -257,8 +247,9 @@ fn verify_no_duplicates(archive: &BinFile) { assert!(found_any, "no symbols found"); if !dups.is_empty() { + let count = dups.iter().map(|x| &x.name).collect::>().len(); dups.sort_unstable_by(|a, b| a.name.cmp(&b.name)); - panic!("found duplicate symbols: {dups:#?}"); + panic!("found {count} duplicate symbols: {dups:#?}"); } println!(" success: no duplicate symbols found"); @@ -266,6 +257,14 @@ fn verify_no_duplicates(archive: &BinFile) { /// Ensure that there are no references to symbols from `core` that aren't also (somehow) defined. fn verify_core_symbols(archive: &BinFile) { + // Match both mangling styles: + // + // * `_ZN4core3str8converts9from_utf817hd4454ac14cbbb790E` (old) + // * `_RNvNtNtCscK9O3IwVk7N_4core3str8converts9from_utf8` (v0) + // + // Also account for the Apple leading `_`. + static RE: LazyLock = LazyLock::new(|| Regex::new(r"^_?_[RZ].*4core").unwrap()); + let mut defined = BTreeSet::new(); let mut undefined = Vec::new(); let mut has_symbols = false; @@ -274,7 +273,7 @@ fn verify_core_symbols(archive: &BinFile) { has_symbols = true; // Find only symbols from `core` - if !symbol.name().unwrap().contains("_ZN4core") { + if !RE.is_match(symbol.name().unwrap()) { return; } @@ -293,7 +292,10 @@ fn verify_core_symbols(archive: &BinFile) { if !undefined.is_empty() { undefined.sort_unstable_by(|a, b| a.name.cmp(&b.name)); - panic!("found undefined symbols from core: {undefined:#?}"); + panic!( + "found {} undefined symbols from core: {undefined:#?}", + undefined.len() + ); } println!(" success: no undefined references to core found"); diff --git a/library/compiler-builtins/crates/symbol-check/tests/all.rs b/library/compiler-builtins/crates/symbol-check/tests/all.rs new file mode 100644 index 000000000000..400469a49e2a --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/all.rs @@ -0,0 +1,126 @@ +use std::env; +use std::ffi::OsString; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::sync::LazyLock; + +use assert_cmd::assert::Assert; +use assert_cmd::cargo::cargo_bin_cmd; +use tempfile::tempdir; + +trait AssertExt { + fn stderr_contains(self, s: &str) -> Self; +} + +impl AssertExt for Assert { + fn stderr_contains(self, s: &str) -> Self { + let out = String::from_utf8_lossy(&self.get_output().stderr); + assert!(out.contains(s), "looking for: `{s}`\nout:\n```\n{out}\n```"); + self + } +} + +#[test] +fn test_duplicates() { + let dir = tempdir().unwrap(); + let dup_out = dir.path().join("dup.o"); + let lib_out = dir.path().join("libfoo.rlib"); + + // For the "bad" file, we need duplicate symbols from different object files in the archive. Do + // this reliably by building an archive and a separate object file then merging them. + rustc_build(&input_dir().join("duplicates.rs"), &lib_out, |cmd| cmd); + rustc_build(&input_dir().join("duplicates.rs"), &dup_out, |cmd| { + cmd.arg("--emit=obj") + }); + + let mut ar = cc_build().get_archiver(); + + if ar.get_program().to_string_lossy().contains("lib.exe") { + let mut out_arg = OsString::from("-out:"); + out_arg.push(&lib_out); + ar.arg(&out_arg); + // Repeating the same file as the first arg makes lib.exe append (taken from the + // `cc` implementation). + ar.arg(&lib_out); + } else { + ar.arg("rs") + // Eat an `libfoo.rlib(lib.rmeta) has no symbols` info message on MacOS + .stderr(Stdio::null()) + .arg(&lib_out); + } + let status = ar.arg(&dup_out).status().unwrap(); + assert!(status.success()); + + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + assert + .failure() + .stderr_contains("duplicate symbols") + .stderr_contains("FDUP") + .stderr_contains("IDUP") + .stderr_contains("fndup"); +} + +#[test] +fn test_core_symbols() { + let dir = tempdir().unwrap(); + let lib_out = dir.path().join("libfoo.rlib"); + rustc_build(&input_dir().join("core_symbols.rs"), &lib_out, |cmd| cmd); + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + assert + .failure() + .stderr_contains("found 1 undefined symbols from core") + .stderr_contains("from_utf8"); +} + +#[test] +fn test_good() { + let dir = tempdir().unwrap(); + let lib_out = dir.path().join("libfoo.rlib"); + rustc_build(&input_dir().join("good.rs"), &lib_out, |cmd| cmd); + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + assert.success(); +} + +/// Build i -> o with optional additional configuration. +fn rustc_build(i: &Path, o: &Path, mut f: impl FnMut(&mut Command) -> &mut Command) { + let mut cmd = Command::new("rustc"); + cmd.arg(i) + .arg("--target") + .arg(target()) + .arg("--crate-type=lib") + .arg("-o") + .arg(o); + f(&mut cmd); + let status = cmd.status().unwrap(); + assert!(status.success()); +} + +/// Configure `cc` with the host and target. +fn cc_build() -> cc::Build { + let mut b = cc::Build::new(); + b.host(env!("HOST")).target(&target()); + b +} + +/// Symcheck runs on the host but we want to verify that we find issues on all targets, so +/// the cross target may be specified. +fn target() -> String { + static TARGET: LazyLock = LazyLock::new(|| { + let target = match env::var("SYMCHECK_TEST_TARGET") { + Ok(t) => t, + // Require on CI so we don't accidentally always test the native target + _ if env::var("CI").is_ok() => panic!("SYMCHECK_TEST_TARGET must be set in CI"), + // Fall back to native for local convenience. + Err(_) => env!("HOST").to_string(), + }; + + println!("using target {target}"); + target + }); + + TARGET.clone() +} + +fn input_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/input") +} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs b/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs new file mode 100644 index 000000000000..cf74f9779661 --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs @@ -0,0 +1,11 @@ +//! Ensure we catch calls to `core`. + +#![no_std] + +#[unsafe(no_mangle)] +pub fn call_from_core(s: &[u8]) -> &str { + match core::str::from_utf8(&s) { + Ok(s) => s, + Err(_) => "", + } +} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs b/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs new file mode 100644 index 000000000000..92623a0b2e1a --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs @@ -0,0 +1,12 @@ +//! Ensure we catch duplicate symbols (the duplicates are in the aux file). Gets built twice +//! as separate object files. + +#![no_std] + +#[unsafe(no_mangle)] +static IDUP: i32 = 0; +#[unsafe(no_mangle)] +static FDUP: f32 = 0.0; + +#[unsafe(no_mangle)] +pub fn fndup() {} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/good.rs b/library/compiler-builtins/crates/symbol-check/tests/input/good.rs new file mode 100644 index 000000000000..6679ee1dd30c --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/good.rs @@ -0,0 +1,4 @@ +#![no_std] + +#[unsafe(no_mangle)] +pub fn good() {} diff --git a/library/compiler-builtins/crates/util/Cargo.toml b/library/compiler-builtins/crates/util/Cargo.toml index 614c54bd8355..c56e2cc12ea5 100644 --- a/library/compiler-builtins/crates/util/Cargo.toml +++ b/library/compiler-builtins/crates/util/Cargo.toml @@ -5,15 +5,15 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" +[dependencies] +libm.workspace = true +libm-macros.workspace = true +libm-test.workspace = true +musl-math-sys = { workspace = true, optional = true } +rug = { workspace = true, optional = true } + [features] default = ["build-musl", "build-mpfr", "unstable-float"] build-musl = ["libm-test/build-musl", "dep:musl-math-sys"] build-mpfr = ["libm-test/build-mpfr", "dep:rug"] unstable-float = ["libm/unstable-float", "libm-test/unstable-float", "rug?/nightly-float"] - -[dependencies] -libm = { path = "../../libm", default-features = false } -libm-macros = { path = "../libm-macros" } -libm-test = { path = "../../libm-test", default-features = false } -musl-math-sys = { path = "../musl-math-sys", optional = true } -rug = { version = "1.27.0", optional = true, default-features = false, features = ["float", "std"] } diff --git a/library/compiler-builtins/etc/thumbv6-none-eabi.json b/library/compiler-builtins/etc/thumbv6-none-eabi.json new file mode 100644 index 000000000000..4c1f760ac3e0 --- /dev/null +++ b/library/compiler-builtins/etc/thumbv6-none-eabi.json @@ -0,0 +1,20 @@ +{ + "abi": "eabi", + "arch": "arm", + "asm-args": ["-mthumb-interwork", "-march=armv6", "-mlittle-endian"], + "c-enum-min-bits": 8, + "crt-objects-fallback": "false", + "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + "emit-debug-gdb-scripts": false, + "features": "+soft-float,+strict-align,+v6k", + "frame-pointer": "always", + "has-thumb-interworking": true, + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-floatabi": "soft", + "llvm-target": "thumbv6-none-eabi", + "max-atomic-width": 32, + "panic-strategy": "abort", + "relocation-model": "static", + "target-pointer-width": 32 +} diff --git a/library/compiler-builtins/libm-test/Cargo.toml b/library/compiler-builtins/libm-test/Cargo.toml index adecfc1af6b8..4f65504bd584 100644 --- a/library/compiler-builtins/libm-test/Cargo.toml +++ b/library/compiler-builtins/libm-test/Cargo.toml @@ -5,6 +5,31 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" +[dependencies] +anyhow.workspace = true +# This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`. +gmp-mpfr-sys = { workspace = true, optional = true } +gungraun = { workspace = true, optional = true } +indicatif.workspace = true +libm = { workspace = true, default-features = true, features = ["unstable-public-internals"] } +libm-macros.workspace = true +musl-math-sys = { workspace = true, optional = true } +paste.workspace = true +rand.workspace = true +rand_chacha.workspace = true +rayon.workspace = true +rug = { workspace = true, optional = true } + +[target.'cfg(target_family = "wasm")'.dependencies] +getrandom = { workspace = true, features = ["wasm_js"] } + +[build-dependencies] +rand = { workspace = true, optional = true } + +[dev-dependencies] +criterion.workspace = true +libtest-mimic.workspace = true + [features] default = ["build-mpfr", "unstable-float"] @@ -27,31 +52,6 @@ icount = ["dep:gungraun"] # Run with a reduced set of benchmarks, such as for CI short-benchmarks = [] -[dependencies] -anyhow = "1.0.98" -# This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`. -gmp-mpfr-sys = { version = "1.6.5", optional = true, default-features = false } -gungraun = { version = "0.17.0", optional = true } -indicatif = { version = "0.18.0", default-features = false } -libm = { path = "../libm", features = ["unstable-public-internals"] } -libm-macros = { path = "../crates/libm-macros" } -musl-math-sys = { path = "../crates/musl-math-sys", optional = true } -paste = "1.0.15" -rand = "0.9.1" -rand_chacha = "0.9.0" -rayon = "1.10.0" -rug = { version = "1.27.0", optional = true, default-features = false, features = ["float", "integer", "std"] } - -[target.'cfg(target_family = "wasm")'.dependencies] -getrandom = { version = "0.3.3", features = ["wasm_js"] } - -[build-dependencies] -rand = { version = "0.9.1", optional = true } - -[dev-dependencies] -criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } -libtest-mimic = "0.8.1" - [[bench]] name = "icount" harness = false diff --git a/library/compiler-builtins/libm-test/src/domain.rs b/library/compiler-builtins/libm-test/src/domain.rs index 94641be9b548..eb009bfa093f 100644 --- a/library/compiler-builtins/libm-test/src/domain.rs +++ b/library/compiler-builtins/libm-test/src/domain.rs @@ -207,7 +207,7 @@ impl EitherPrim, Domain> { .into_prim_float()]; /// Domain for `loggamma` - const LGAMMA: [Self; 1] = Self::STRICTLY_POSITIVE; + const LGAMMA: [Self; 1] = Self::UNBOUNDED1; /// Domain for `jn` and `yn`. // FIXME: the domain should provide some sort of "reasonable range" so we don't actually test diff --git a/library/compiler-builtins/libm-test/src/lib.rs b/library/compiler-builtins/libm-test/src/lib.rs index accb39654d15..60d96ae9bcee 100644 --- a/library/compiler-builtins/libm-test/src/lib.rs +++ b/library/compiler-builtins/libm-test/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] #![allow(clippy::unusual_byte_groupings)] // sometimes we group by sign_exp_sig +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable pub mod domain; mod f8_impl; diff --git a/library/compiler-builtins/libm-test/src/mpfloat.rs b/library/compiler-builtins/libm-test/src/mpfloat.rs index 9b51dc6051d0..85f0a4da4a6e 100644 --- a/library/compiler-builtins/libm-test/src/mpfloat.rs +++ b/library/compiler-builtins/libm-test/src/mpfloat.rs @@ -170,7 +170,9 @@ libm_macros::for_each_function! { ldexpf, ldexpf128, ldexpf16, + lgamma, lgamma_r, + lgammaf, lgammaf_r, modf, modff, @@ -213,7 +215,6 @@ libm_macros::for_each_function! { fmaximum_num | fmaximum_numf | fmaximum_numf16 | fmaximum_numf128 => max, fmin | fminf | fminf16 | fminf128 | fminimum_num | fminimum_numf | fminimum_numf16 | fminimum_numf128 => min, - lgamma | lgammaf => ln_gamma, log | logf => ln, log1p | log1pf => ln_1p, tgamma | tgammaf => gamma, @@ -576,6 +577,30 @@ impl MpOp for crate::op::lgammaf_r::Routine { } } +impl MpOp for crate::op::lgamma::Routine { + type MpTy = MpFloat; + + fn new_mp() -> Self::MpTy { + new_mpfloat::() + } + + fn run(this: &mut Self::MpTy, input: Self::RustArgs) -> Self::RustRet { + ::run(this, input).0 + } +} + +impl MpOp for crate::op::lgammaf::Routine { + type MpTy = MpFloat; + + fn new_mp() -> Self::MpTy { + new_mpfloat::() + } + + fn run(this: &mut Self::MpTy, input: Self::RustArgs) -> Self::RustRet { + ::run(this, input).0 + } +} + /* stub implementations so we don't need to special case them */ impl MpOp for crate::op::nextafter::Routine { diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index 7887c032394b..5d52da168fe7 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -67,7 +67,7 @@ pub fn default_ulp(ctx: &CheckCtx) -> u32 { Bn::Exp2 => 1, Bn::Expm1 => 1, Bn::Hypot => 1, - Bn::Lgamma | Bn::LgammaR => 16, + Bn::Lgamma | Bn::LgammaR => 4, Bn::Log => 1, Bn::Log10 => 1, Bn::Log1p => 1, @@ -102,7 +102,6 @@ pub fn default_ulp(ctx: &CheckCtx) -> u32 { match ctx.base_name { Bn::Cosh => ulp = 2, Bn::Exp10 if usize::BITS < 64 => ulp = 4, - Bn::Lgamma | Bn::LgammaR => ulp = 400, Bn::Tanh => ulp = 4, _ => (), } @@ -218,17 +217,17 @@ impl MaybeOverride<(f16,)> for SpecialCase {} impl MaybeOverride<(f32,)> for SpecialCase { fn check_float(input: (f32,), actual: F, expected: F, ctx: &CheckCtx) -> CheckAction { - if (ctx.base_name == BaseName::Lgamma || ctx.base_name == BaseName::LgammaR) - && input.0 > 4e36 - && expected.is_infinite() - && !actual.is_infinite() - { - // This result should saturate but we return a finite value. + if ctx.base_name == BaseName::J0 && input.0 < -1e34 { + // Errors get huge close to -inf return XFAIL_NOCHECK; } - if ctx.base_name == BaseName::J0 && input.0 < -1e34 { - // Errors get huge close to -inf + // FIXME(correctness): lgammaf has high relative inaccuracy near its zeroes + if matches!(ctx.base_name, BaseName::Lgamma | BaseName::LgammaR) + && input.0 > -13.0625 + && input.0 < -2.0 + && (expected.abs() < F::ONE || (input.0 - input.0.round()).abs() < 0.02) + { return XFAIL_NOCHECK; } @@ -266,6 +265,24 @@ impl MaybeOverride<(f64,)> for SpecialCase { return XFAIL_NOCHECK; } + if ctx.base_name == BaseName::Acosh + && input.0 < 1.0 + && actual.is_nan() + && ctx.basis == CheckBasis::Musl + { + // Musl sometimes evaluates acosh(negative) to a numeric value + return XFAIL_NOCHECK; + } + + // FIXME(correctness): lgamma has high relative inaccuracy near its zeroes + if matches!(ctx.base_name, BaseName::Lgamma | BaseName::LgammaR) + && input.0 > -32.0 + && input.0 < -2.0 + && (expected.abs() < F::ONE || (input.0 - input.0.round()).abs() < 0.02) + { + return XFAIL_NOCHECK; + } + // maybe_check_nan_bits(actual, expected, ctx) unop_common(input, actual, expected, ctx) } @@ -295,27 +312,6 @@ fn unop_common( expected: F2, ctx: &CheckCtx, ) -> CheckAction { - if ctx.base_name == BaseName::Acosh - && input.0 < F1::NEG_ONE - && !(expected.is_nan() && actual.is_nan()) - { - // acoshf is undefined for x <= 1.0, but we return a random result at lower values. - - if ctx.basis == CheckBasis::Musl { - return XFAIL_NOCHECK; - } - - return XFAIL("acoshf undefined"); - } - - if (ctx.base_name == BaseName::Lgamma || ctx.base_name == BaseName::LgammaR) - && input.0 < F1::ZERO - && !input.0.is_infinite() - { - // loggamma should not be defined for x < 0, yet we both return results - return XFAIL_NOCHECK; - } - // fabs and copysign must leave NaNs untouched. if ctx.base_name == BaseName::Fabs && input.0.is_nan() { // LLVM currently uses x87 instructions which quieten signalling NaNs to handle the i686 @@ -401,14 +397,6 @@ fn binop_common( return SKIP; } - // FIXME(#939): this should not be skipped, there is a bug in our implementationi. - if ctx.base_name == BaseName::FmaximumNum - && ctx.basis == CheckBasis::Mpfr - && ((input.0.is_nan() && actual.is_nan() && expected.is_nan()) || input.1.is_nan()) - { - return XFAIL_NOCHECK; - } - /* FIXME(#439): our fmin and fmax do not compare signed zeros */ if ctx.base_name == BaseName::Fmin @@ -510,7 +498,7 @@ fn int_float_common( if input.0 > 4000 { return XFAIL_NOCHECK; } else if input.0 > 100 { - return CheckAction::AssertWithUlp(1_000_000); + return CheckAction::AssertWithUlp(2_000_000); } } DEFAULT diff --git a/library/compiler-builtins/libm/CHANGELOG.md b/library/compiler-builtins/libm/CHANGELOG.md index 33fec06aa237..037f79ef3ef1 100644 --- a/library/compiler-builtins/libm/CHANGELOG.md +++ b/library/compiler-builtins/libm/CHANGELOG.md @@ -8,6 +8,22 @@ and this project adheres to ## [Unreleased] +## [0.2.16](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.15...libm-v0.2.16) - 2025-12-07 + +### Fixed + +- Fix an incorrect result for `fminimum` and `fmaximum` with the input (-0, NaN) +- Fix a typo in `libm::Libm::roundeven` +- Fix the `expm1f` overflow threshold +- Change `CmpResult` to use a pointer-sized return type +- Compare against `CARGO_CFG_TARGET_FAMILY` in a multi-valued fashion +- Implement `exp` and its variants for i586 with inline assembly +- Implement `floor` and `ceil` in assembly on `i586` + +### Other + +- Significantly optimize `fmod` worst case performance ([#1002](https://github.com/rust-lang/compiler-builtins/pull/1002)) + ## [0.2.15](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15) - 2025-05-06 ### Other diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index 5b5ca34fd2c9..98202d1977dc 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libm" -version = "0.2.15" +version = "0.2.16" authors = [ "Alex Crichton ", "Amanieu d'Antras ", @@ -13,7 +13,11 @@ keywords = ["libm", "math"] repository = "https://github.com/rust-lang/compiler-builtins" license = "MIT" edition = "2021" -rust-version = "1.63" +rust-version = "1.67" + +[dev-dependencies] +# FIXME(msrv): switch to `no-panic.workspace` when possible +no-panic = "0.1.35" [features] default = ["arch"] @@ -42,9 +46,6 @@ unstable-float = [] # hard float operations. force-soft-floats = [] -[dev-dependencies] -no-panic = "0.1.35" - [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ # compiler-builtins sets this feature, but we use it in `libm` diff --git a/library/compiler-builtins/libm/src/lib.rs b/library/compiler-builtins/libm/src/lib.rs index 31b12235314c..85ed5e2c9fc6 100644 --- a/library/compiler-builtins/libm/src/lib.rs +++ b/library/compiler-builtins/libm/src/lib.rs @@ -8,6 +8,7 @@ )] #![cfg_attr(f128_enabled, feature(f128))] #![cfg_attr(f16_enabled, feature(f16))] +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable #![allow(clippy::assign_op_pattern)] #![allow(clippy::deprecated_cfg_attr)] #![allow(clippy::eq_op)] diff --git a/library/compiler-builtins/libm/src/math/acosh.rs b/library/compiler-builtins/libm/src/math/acosh.rs index 8737bad012c8..2904fc0ed520 100644 --- a/library/compiler-builtins/libm/src/math/acosh.rs +++ b/library/compiler-builtins/libm/src/math/acosh.rs @@ -1,4 +1,4 @@ -use super::{log, log1p, sqrt}; +use super::{Float, log, log1p, sqrt}; const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa39ef*/ @@ -9,19 +9,19 @@ const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa3 /// `x` must be a number greater than or equal to 1. #[cfg_attr(assert_no_panic, no_panic::no_panic)] pub fn acosh(x: f64) -> f64 { - let u = x.to_bits(); - let e = ((u >> 52) as usize) & 0x7ff; + let ux = x.to_bits(); /* x < 1 domain error is handled in the called functions */ - - if e < 0x3ff + 1 { - /* |x| < 2, up to 2ulp error in [1,1.125] */ - return log1p(x - 1.0 + sqrt((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + if (ux & !f64::SIGN_MASK) < 2_f64.to_bits() { + /* |x| < 2, invalid if x < 1 */ + /* up to 2ulp error in [1,1.125] */ + let x_1 = x - 1.0; + log1p(x_1 + sqrt(x_1 * x_1 + 2.0 * x_1)) + } else if ux < ((1 << 26) as f64).to_bits() { + /* 2 <= x < 0x1p26 */ + log(2.0 * x - 1.0 / (x + sqrt(x * x - 1.0))) + } else { + /* x >= 0x1p26 or x <= -2 or nan */ + log(x) + LN2 } - if e < 0x3ff + 26 { - /* |x| < 0x1p26 */ - return log(2.0 * x - 1.0 / (x + sqrt(x * x - 1.0))); - } - /* |x| >= 0x1p26 or nan */ - return log(x) + LN2; } diff --git a/library/compiler-builtins/libm/src/math/acoshf.rs b/library/compiler-builtins/libm/src/math/acoshf.rs index 432fa03f1163..d9aafaabdef4 100644 --- a/library/compiler-builtins/libm/src/math/acoshf.rs +++ b/library/compiler-builtins/libm/src/math/acoshf.rs @@ -1,4 +1,4 @@ -use super::{log1pf, logf, sqrtf}; +use super::{Float, log1pf, logf, sqrtf}; const LN2: f32 = 0.693147180559945309417232121458176568; @@ -9,18 +9,19 @@ const LN2: f32 = 0.693147180559945309417232121458176568; /// `x` must be a number greater than or equal to 1. #[cfg_attr(assert_no_panic, no_panic::no_panic)] pub fn acoshf(x: f32) -> f32 { - let u = x.to_bits(); - let a = u & 0x7fffffff; + let ux = x.to_bits(); - if a < 0x3f800000 + (1 << 23) { - /* |x| < 2, invalid if x < 1 or nan */ + /* x < 1 domain error is handled in the called functions */ + if (ux & !f32::SIGN_MASK) < 2_f32.to_bits() { + /* |x| < 2, invalid if x < 1 */ /* up to 2ulp error in [1,1.125] */ - return log1pf(x - 1.0 + sqrtf((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + let x_1 = x - 1.0; + log1pf(x_1 + sqrtf(x_1 * x_1 + 2.0 * x_1)) + } else if ux < ((1 << 12) as f32).to_bits() { + /* 2 <= x < 0x1p12 */ + logf(2.0 * x - 1.0 / (x + sqrtf(x * x - 1.0))) + } else { + /* x >= 0x1p12 or x <= -2 or nan */ + logf(x) + LN2 } - if a < 0x3f800000 + (12 << 23) { - /* |x| < 0x1p12 */ - return logf(2.0 * x - 1.0 / (x + sqrtf(x * x - 1.0))); - } - /* x >= 0x1p12 */ - return logf(x) + LN2; } diff --git a/library/compiler-builtins/libm/src/math/generic/sqrt.rs b/library/compiler-builtins/libm/src/math/generic/sqrt.rs index 9481c4cdb7bb..e97a43d34956 100644 --- a/library/compiler-builtins/libm/src/math/generic/sqrt.rs +++ b/library/compiler-builtins/libm/src/math/generic/sqrt.rs @@ -419,9 +419,7 @@ mod tests { fn conformance_tests_f16() { let cases = [ (f16::PI, 0x3f17_u16), - // 10_000.0, using a hex literal for MSRV hack (Rust < 1.67 checks literal widths as - // part of the AST, so the `cfg` is irrelevant here). - (f16::from_bits(0x70e2), 0x5640_u16), + (10000.0_f16, 0x5640_u16), (f16::from_bits(0x0000000f), 0x13bf_u16), (f16::INFINITY, f16::INFINITY.to_bits()), ]; diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index 4e5011f62e0f..60c8bfca5165 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -1,5 +1,3 @@ -#![allow(unknown_lints)] // FIXME(msrv) we shouldn't need this - use core::{fmt, mem, ops}; use super::int_traits::{CastFrom, Int, MinInt}; @@ -289,10 +287,7 @@ macro_rules! float_impl { cfg_if! { // fma is not yet available in `core` if #[cfg(intrinsics_enabled)] { - // FIXME(msrv,bench): once our benchmark rustc version is above the - // 2022-09-23 nightly, this can be removed. - #[allow(unused_unsafe)] - unsafe { core::intrinsics::$fma_intrinsic(self, y, z) } + core::intrinsics::$fma_intrinsic(self, y, z) } else { super::super::$fma_fn(self, y, z) } diff --git a/library/compiler-builtins/libm/src/math/support/hex_float.rs b/library/compiler-builtins/libm/src/math/support/hex_float.rs index c8558b90053d..2f9369e50441 100644 --- a/library/compiler-builtins/libm/src/math/support/hex_float.rs +++ b/library/compiler-builtins/libm/src/math/support/hex_float.rs @@ -121,7 +121,7 @@ const fn parse_finite( Ok(Parsed { sig, exp }) => (sig, exp), }; - let mut round_bits = u128_ilog2(sig) as i32 - sig_bits as i32; + let mut round_bits = sig.ilog2() as i32 - sig_bits as i32; // Round at least up to min_lsb if exp < min_lsb - round_bits { @@ -299,29 +299,11 @@ const fn parse_hex(mut b: &[u8]) -> Result { )); }; - { - let e; - if negate_exp { - e = (exp as i64) - (pexp as i64); - } else { - e = (exp as i64) + (pexp as i64); - }; - - exp = if e < i32::MIN as i64 { - i32::MIN - } else if e > i32::MAX as i64 { - i32::MAX - } else { - e as i32 - }; - } - /* FIXME(msrv): once MSRV >= 1.66, replace the above workaround block with: if negate_exp { exp = exp.saturating_sub_unsigned(pexp); } else { exp = exp.saturating_add_unsigned(pexp); }; - */ Ok(Parsed { sig, exp }) } @@ -342,14 +324,6 @@ const fn hex_digit(c: u8) -> Option { } } -/* FIXME(msrv): vendor some things that are not const stable at our MSRV */ - -/// `u128::ilog2` -const fn u128_ilog2(v: u128) -> u32 { - assert!(v != 0); - u128::BITS - 1 - v.leading_zeros() -} - #[cfg(any(test, feature = "unstable-public-internals"))] mod hex_fmt { use core::fmt; diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index 6a2835bc2d9e..aa3876b14a22 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -23d01cd2412583491621ab1ca4f1b01e37d11e39 +db3e99bbab28c6ca778b13222becdea54533d908 diff --git a/library/compiler-builtins/triagebot.toml b/library/compiler-builtins/triagebot.toml index b210a5fb5256..d0cdb497edba 100644 --- a/library/compiler-builtins/triagebot.toml +++ b/library/compiler-builtins/triagebot.toml @@ -10,7 +10,7 @@ exclude_titles = ["Rustc pull update"] # when commits are included in subtrees, as well as warning links in commits. # Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html [issue-links] -check-commits = false +check-commits = "uncanonicalized" # Enable issue transfers within the org # Documentation at: https://forge.rust-lang.org/triagebot/transfer.html diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 9b80e3b70fa2..bf3d3e0a5aca 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -57,7 +57,7 @@ use crate::{cmp, ptr}; /// let mut allocated = 0; /// if self /// .remaining -/// .fetch_update(Relaxed, Relaxed, |mut remaining| { +/// .try_update(Relaxed, Relaxed, |mut remaining| { /// if size > remaining { /// return None; /// } @@ -284,9 +284,10 @@ pub unsafe trait GlobalAlloc { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: the caller must ensure that the `new_size` does not overflow. - // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. - let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + let alignment = layout.alignment(); + // SAFETY: the caller must ensure that the `new_size` does not overflow + // when rounded up to the next multiple of `alignment`. + let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) }; // SAFETY: the caller must ensure that `new_layout` is greater than zero. let new_ptr = unsafe { self.alloc(new_layout) }; if !new_ptr.is_null() { diff --git a/library/core/src/array/drain.rs b/library/core/src/array/drain.rs index 1c6137191324..17792dca583d 100644 --- a/library/core/src/array/drain.rs +++ b/library/core/src/array/drain.rs @@ -31,7 +31,6 @@ impl<'l, 'f, T, U, const N: usize, F: FnMut(T) -> U> Drain<'l, 'f, T, N, F> { } /// See [`Drain::new`]; this is our fake iterator. -#[rustc_const_unstable(feature = "array_try_map", issue = "79711")] #[unstable(feature = "array_try_map", issue = "79711")] pub(super) struct Drain<'l, 'f, T, const N: usize, F> { // FIXME(const-hack): This is essentially a slice::IterMut<'static>, replace when possible. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 6cca2e6358b6..4a2cf1527744 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -516,20 +516,47 @@ impl [T; N] { /// /// # Note on performance and stack usage /// - /// Unfortunately, usages of this method are currently not always optimized - /// as well as they could be. This mainly concerns large arrays, as mapping - /// over small arrays seem to be optimized just fine. Also note that in - /// debug mode (i.e. without any optimizations), this method can use a lot - /// of stack space (a few times the size of the array or more). + /// Note that this method is *eager*. It evaluates `f` all `N` times before + /// returning the new array. /// - /// Therefore, in performance-critical code, try to avoid using this method - /// on large arrays or check the emitted code. Also try to avoid chained - /// maps (e.g. `arr.map(...).map(...)`). + /// That means that `arr.map(f).map(g)` is, in general, *not* equivalent to + /// `array.map(|x| g(f(x)))`, as the former calls `f` 4 times then `g` 4 times, + /// whereas the latter interleaves the calls (`fgfgfgfg`). /// - /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()` - /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you - /// really need a new array of the same size as the result. Rust's lazy - /// iterators tend to get optimized very well. + /// A consequence of this is that it can have fairly-high stack usage, especially + /// in debug mode or for long arrays. The backend may be able to optimize it + /// away, but especially for complicated mappings it might not be able to. + /// + /// If you're doing a one-step `map` and really want an array as the result, + /// then absolutely use this method. Its implementation uses a bunch of tricks + /// to help the optimizer handle it well. Particularly for simple arrays, + /// like `[u8; 3]` or `[f32; 4]`, there's nothing to be concerned about. + /// + /// However, if you don't actually need an *array* of the results specifically, + /// just to process them, then you likely want [`Iterator::map`] instead. + /// + /// For example, rather than doing an array-to-array map of all the elements + /// in the array up-front and only iterating after that completes, + /// + /// ``` + /// # let my_array = [1, 2, 3]; + /// # let f = |x: i32| x + 1; + /// for x in my_array.map(f) { + /// // ... + /// } + /// ``` + /// + /// It's often better to use an iterator along the lines of + /// + /// ``` + /// # let my_array = [1, 2, 3]; + /// # let f = |x: i32| x + 1; + /// for x in my_array.into_iter().map(f) { + /// // ... + /// } + /// ``` + /// + /// as that's more likely to avoid large temporaries. /// /// /// # Examples diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index d77fafed2039..ec3e551056fe 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -878,7 +878,7 @@ impl AsciiChar { /// # Examples /// /// ``` - /// #![feature(ascii_char, ascii_char_variants, is_ascii_octdigit)] + /// #![feature(ascii_char, ascii_char_variants)] /// /// use std::ascii; /// diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index ff46bb13ba4e..7da6c5f13cce 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -45,8 +45,7 @@ impl hash::Hash for ByteStr { #[unstable(feature = "bstr_internals", issue = "none")] macro_rules! impl_partial_eq { ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { let other: &[u8] = other.as_ref(); @@ -54,8 +53,7 @@ macro_rules! impl_partial_eq { } } - #[allow(unused_lifetimes)] - impl<'a> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { let this: &[u8] = self.as_ref(); @@ -76,9 +74,8 @@ macro_rules! impl_partial_eq_ord { ($lhs:ty, $rhs:ty) => { $crate::bstr::impl_partial_eq!($lhs, $rhs); - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$rhs> for $lhs { + impl PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { let other: &[u8] = other.as_ref(); @@ -86,9 +83,8 @@ macro_rules! impl_partial_eq_ord { } } - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] - impl<'a> PartialOrd<$lhs> for $rhs { + impl PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { let this: &[u8] = self.as_ref(); @@ -107,7 +103,6 @@ pub use impl_partial_eq_ord; #[unstable(feature = "bstr_internals", issue = "none")] macro_rules! impl_partial_eq_n { ($lhs:ty, $rhs:ty) => { - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl PartialEq<$rhs> for $lhs { #[inline] @@ -117,7 +112,6 @@ macro_rules! impl_partial_eq_n { } } - #[allow(unused_lifetimes)] #[unstable(feature = "bstr", issue = "134915")] impl PartialEq<$lhs> for $rhs { #[inline] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 661ea4ab6a27..28c3db698536 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -689,6 +689,30 @@ impl, U> CoerceUnsized> for Cell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for Cell {} +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell; N]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell; N] { + self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + &*self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + self.as_slice_of_cells() + } +} + impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// @@ -750,7 +774,6 @@ impl Cell<[T; N]> { /// following is unsound: /// /// ```rust -/// #![feature(cell_get_cloned)] /// # use std::cell::Cell; /// /// #[derive(Copy, Debug)] diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index c69026c5c9f3..03650615e25a 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -39,62 +39,51 @@ impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i12 impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -// Conversion traits for primitive integer and float types -// Conversions T -> T are covered by a blanket impl and therefore excluded -// Some conversions from and to usize/isize are not implemented due to portability concerns -macro_rules! impl_from { - (bool => $Int:ty $(,)?) => { - impl_from!( - bool => $Int, - #[stable(feature = "from_bool", since = "1.28.0")], - concat!( - "Converts a [`bool`] to [`", stringify!($Int), "`] losslessly.\n", - "The resulting value is `0` for `false` and `1` for `true` values.\n", - "\n", - "# Examples\n", - "\n", - "```\n", - "assert_eq!(", stringify!($Int), "::from(true), 1);\n", - "assert_eq!(", stringify!($Int), "::from(false), 0);\n", - "```\n", - ), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta] $(,)?) => { - impl_from!( - $Small => $Large, - #[$attr], - concat!("Converts [`", stringify!($Small), "`] to [`", stringify!($Large), "`] losslessly."), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta], $doc:expr $(,)?) => { - #[$attr] +/// Implement `From` for integers +macro_rules! impl_from_bool { + ($($int:ty)*) => {$( + #[stable(feature = "from_bool", since = "1.28.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - impl const From<$Small> for $Large { - // Rustdocs on the impl block show a "[+] show undocumented items" toggle. - // Rustdocs on functions do not. - #[doc = $doc] + impl const From for $int { + /// Converts from [`bool`] to + #[doc = concat!("[`", stringify!($int), "`]")] + /// , by turning `false` into `0` and `true` into `1`. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($int), "::from(false), 0);")] + /// + #[doc = concat!("assert_eq!(", stringify!($int), "::from(true), 1);")] + /// ``` #[inline(always)] - fn from(small: $Small) -> Self { - small as Self + fn from(b: bool) -> Self { + b as Self } } - }; + )*} } // boolean -> integer -impl_from!(bool => u8); -impl_from!(bool => u16); -impl_from!(bool => u32); -impl_from!(bool => u64); -impl_from!(bool => u128); -impl_from!(bool => usize); -impl_from!(bool => i8); -impl_from!(bool => i16); -impl_from!(bool => i32); -impl_from!(bool => i64); -impl_from!(bool => i128); -impl_from!(bool => isize); +impl_from_bool!(u8 u16 u32 u64 u128 usize); +impl_from_bool!(i8 i16 i32 i64 i128 isize); + +/// Implement `From<$small>` for `$large` +macro_rules! impl_from { + ($small:ty => $large:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + impl const From<$small> for $large { + #[doc = concat!("Converts from [`", stringify!($small), "`] to [`", stringify!($large), "`] losslessly.")] + #[inline(always)] + fn from(small: $small) -> Self { + debug_assert!(<$large>::MIN as i128 <= <$small>::MIN as i128); + debug_assert!(<$small>::MAX as u128 <= <$large>::MAX as u128); + small as Self + } + } + } +} // unsigned integer -> unsigned integer impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); @@ -230,6 +219,7 @@ impl_float_from_bool!( f16; doctest_prefix: // rustdoc doesn't remove the conventional space after the `///` + ///# #![allow(unused_features)] ///#![feature(f16)] ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// @@ -241,6 +231,7 @@ impl_float_from_bool!(f64); impl_float_from_bool!( f128; doctest_prefix: + ///# #![allow(unused_features)] ///#![feature(f128)] ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { /// @@ -338,12 +329,48 @@ macro_rules! impl_try_from_both_bounded { )*} } +/// Implement `TryFrom` for `bool` +macro_rules! impl_try_from_integer_for_bool { + ($($int:ty)+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + impl const TryFrom<$int> for bool { + type Error = TryFromIntError; + + /// Tries to create a bool from an integer type. + /// Returns an error if the integer is not 0 or 1. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(0_", stringify!($int), ".try_into(), Ok(false));")] + /// + #[doc = concat!("assert_eq!(1_", stringify!($int), ".try_into(), Ok(true));")] + /// + #[doc = concat!("assert!(<", stringify!($int), " as TryInto>::try_into(2).is_err());")] + /// ``` + #[inline] + fn try_from(i: $int) -> Result { + match i { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(TryFromIntError(())), + } + } + } + )*} +} + macro_rules! rev { ($mac:ident, $source:ty => $($target:ty),+) => {$( $mac!($target => $source); )*} } +// integer -> bool +impl_try_from_integer_for_bool!(u128 u64 u32 u16 u8); +impl_try_from_integer_for_bool!(i128 i64 i32 i16 i8); + // unsigned integer -> unsigned integer impl_try_from_upper_bounded!(u16 => u8); impl_try_from_upper_bounded!(u32 => u8, u16); diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 197cddd3fa9d..7550dac45cd0 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1227,8 +1227,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// assert_eq!(format!("{:?}", wrapped), "'a'"); /// ``` #[stable(feature = "fmt_from_fn", since = "1.93.0")] +#[rustc_const_stable(feature = "const_fmt_from_fn", since = "CURRENT_RUSTC_VERSION")] #[must_use = "returns a type implementing Debug and Display, which do not have any effects unless they are used"] -pub fn from_fn) -> fmt::Result>(f: F) -> FromFn { +pub const fn from_fn) -> fmt::Result>(f: F) -> FromFn { FromFn(f) } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index dccac26e07e6..3692420be8fc 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -724,7 +724,6 @@ pub const fn unlikely(b: bool) -> bool { /// # Examples /// /// ``` -/// #![feature(cold_path)] /// use core::hint::cold_path; /// /// fn foo(x: &[i32]) { @@ -750,7 +749,6 @@ pub const fn unlikely(b: bool) -> bool { /// than the branch: /// /// ``` -/// #![feature(cold_path)] /// use core::hint::cold_path; /// /// #[inline(always)] @@ -777,7 +775,8 @@ pub const fn unlikely(b: bool) -> bool { /// } /// } /// ``` -#[unstable(feature = "cold_path", issue = "136873")] +#[stable(feature = "cold_path", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "cold_path", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] pub const fn cold_path() { crate::intrinsics::cold_path() diff --git a/library/core/src/index.rs b/library/core/src/index.rs index 3baefdf10cec..70372163c6e1 100644 --- a/library/core/src/index.rs +++ b/library/core/src/index.rs @@ -315,7 +315,7 @@ unsafe impl SliceIndex<[T]> for Clamp> { } #[unstable(feature = "sliceindex_wrappers", issue = "146179")] -unsafe impl SliceIndex<[T]> for Clamp> { +unsafe impl SliceIndex<[T]> for Clamp> { type Output = [T]; fn get(self, slice: &[T]) -> Option<&Self::Output> { @@ -408,7 +408,7 @@ unsafe impl SliceIndex<[T]> for Clamp> { } #[unstable(feature = "sliceindex_wrappers", issue = "146179")] -unsafe impl SliceIndex<[T]> for Clamp { +unsafe impl SliceIndex<[T]> for Clamp { type Output = [T]; fn get(self, slice: &[T]) -> Option<&Self::Output> { diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs index 932537f2581f..aa9033ee3d26 100644 --- a/library/core/src/intrinsics/fallback.rs +++ b/library/core/src/intrinsics/fallback.rs @@ -218,3 +218,38 @@ macro_rules! impl_funnel_shifts { impl_funnel_shifts! { u8, u16, u32, u64, u128, usize } + +#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] +pub const trait CarrylessMul: Copy + 'static { + /// See [`super::carryless_mul`]; we just need the trait indirection to handle + /// different types since calling intrinsics with generics doesn't work. + fn carryless_mul(self, rhs: Self) -> Self; +} + +macro_rules! impl_carryless_mul{ + ($($type:ident),*) => {$( + #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] + impl const CarrylessMul for $type { + #[inline] + fn carryless_mul(self, rhs: Self) -> Self { + let mut result = 0; + let mut i = 0; + + while i < $type::BITS { + // If the i-th bit in rhs is set. + if (rhs >> i) & 1 != 0 { + // Then xor the result with `self` shifted to the left by i positions. + result ^= self << i; + } + i += 1; + } + + result + } + } + )*}; +} + +impl_carryless_mul! { + u8, u16, u32, u64, u128, usize +} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 051dda731881..7fded188ddbf 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -409,8 +409,7 @@ pub const unsafe fn assume(b: bool) { /// Therefore, implementations must not require the user to uphold /// any safety invariants. /// -/// This intrinsic does not have a stable counterpart. -#[unstable(feature = "core_intrinsics", issue = "none")] +/// The stabilized version of this intrinsic is [`core::hint::cold_path`]. #[rustc_intrinsic] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] @@ -2179,6 +2178,19 @@ pub const unsafe fn unchecked_funnel_shr( unsafe { a.unchecked_funnel_shr(b, shift) } } +/// Carryless multiply. +/// +/// Safe versions of this intrinsic are available on the integer primitives +/// via the `carryless_mul` method. For example, [`u32::carryless_mul`]. +#[rustc_intrinsic] +#[rustc_nounwind] +#[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")] +#[unstable(feature = "uint_carryless_mul", issue = "152080")] +#[miri::intrinsic_fallback_is_spec] +pub const fn carryless_mul(a: T, b: T) -> T { + a.carryless_mul(b) +} + /// This is an implementation detail of [`crate::ptr::read`] and should /// not be used anywhere else. See its comments for why this exists. /// @@ -2887,7 +2899,7 @@ pub const fn type_name() -> &'static str; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn type_id() -> crate::any::TypeId; +pub const fn type_id() -> crate::any::TypeId; /// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the /// same type. This is necessary because at const-eval time the actual discriminating diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index f70262c38ae5..5fb2102c319e 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -162,6 +162,18 @@ pub const unsafe fn simd_funnel_shl(a: T, b: T, shift: T) -> T; #[rustc_nounwind] pub const unsafe fn simd_funnel_shr(a: T, b: T, shift: T) -> T; +/// Compute the carry-less product. +/// +/// This is similar to long multiplication except that the carry is discarded. +/// +/// This operation can be used to model multiplication in `GF(2)[X]`, the polynomial +/// ring over `GF(2)`. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn simd_carryless_mul(a: T, b: T) -> T; + /// "And"s vectors elementwise. /// /// `T` must be a vector of integers. diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index c3b9a0f0b7a4..9c3edfd4192d 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -279,7 +279,8 @@ pub trait FromIterator: Sized { )] #[rustc_skip_during_method_dispatch(array, boxed_slice)] #[stable(feature = "rust1", since = "1.0.0")] -pub trait IntoIterator { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const trait IntoIterator { /// The type of the elements being iterated over. #[rustc_diagnostic_item = "IntoIteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] @@ -312,7 +313,8 @@ pub trait IntoIterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for I { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for I { type Item = I::Item; type IntoIter = I; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index dc484e2a27f6..d919230d094d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -37,7 +37,8 @@ fn _assert_is_dyn_compatible(_: &dyn Iterator) {} #[lang = "iterator"] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub trait Iterator { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const trait Iterator { /// The type of the elements being iterated over. #[rustc_diagnostic_item = "IteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] @@ -107,6 +108,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_next_chunk", issue = "98326")] + #[rustc_non_const_trait_method] fn next_chunk( &mut self, ) -> Result<[Self::Item; N], array::IntoIter> @@ -219,6 +221,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn count(self) -> usize where Self: Sized, @@ -251,6 +254,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn last(self) -> Option where Self: Sized, @@ -298,6 +302,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_advance_by", issue = "77404")] + #[rustc_non_const_trait_method] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { /// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators. trait SpecAdvanceBy { @@ -375,6 +380,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn nth(&mut self, n: usize) -> Option { self.advance_by(n).ok()?; self.next() @@ -425,6 +431,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_step_by", since = "1.28.0")] + #[rustc_non_const_trait_method] fn step_by(self, step: usize) -> StepBy where Self: Sized, @@ -496,6 +503,7 @@ pub trait Iterator { /// [`OsStr`]: ../../std/ffi/struct.OsStr.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn chain(self, other: U) -> Chain where Self: Sized, @@ -614,6 +622,7 @@ pub trait Iterator { /// [`zip`]: crate::iter::zip #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn zip(self, other: U) -> Zip where Self: Sized, @@ -657,6 +666,7 @@ pub trait Iterator { /// [`intersperse_with`]: Iterator::intersperse_with #[inline] #[unstable(feature = "iter_intersperse", issue = "79524")] + #[rustc_non_const_trait_method] fn intersperse(self, separator: Self::Item) -> Intersperse where Self: Sized, @@ -715,6 +725,7 @@ pub trait Iterator { /// [`intersperse`]: Iterator::intersperse #[inline] #[unstable(feature = "iter_intersperse", issue = "79524")] + #[rustc_non_const_trait_method] fn intersperse_with(self, separator: G) -> IntersperseWith where Self: Sized, @@ -774,6 +785,7 @@ pub trait Iterator { #[rustc_diagnostic_item = "IteratorMap"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn map(self, f: F) -> Map where Self: Sized, @@ -819,6 +831,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] + #[rustc_non_const_trait_method] fn for_each(self, f: F) where Self: Sized, @@ -894,6 +907,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "iter_filter"] + #[rustc_non_const_trait_method] fn filter

(self, predicate: P) -> Filter where Self: Sized, @@ -939,6 +953,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn filter_map(self, f: F) -> FilterMap where Self: Sized, @@ -986,6 +1001,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "enumerate_method"] + #[rustc_non_const_trait_method] fn enumerate(self) -> Enumerate where Self: Sized, @@ -1057,6 +1073,7 @@ pub trait Iterator { /// [`next`]: Iterator::next #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn peekable(self) -> Peekable where Self: Sized, @@ -1122,6 +1139,7 @@ pub trait Iterator { #[inline] #[doc(alias = "drop_while")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn skip_while

(self, predicate: P) -> SkipWhile where Self: Sized, @@ -1200,6 +1218,7 @@ pub trait Iterator { /// the iteration should stop, but wasn't placed back into the iterator. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn take_while

(self, predicate: P) -> TakeWhile where Self: Sized, @@ -1288,6 +1307,7 @@ pub trait Iterator { /// [`fuse`]: Iterator::fuse #[inline] #[stable(feature = "iter_map_while", since = "1.57.0")] + #[rustc_non_const_trait_method] fn map_while(self, predicate: P) -> MapWhile where Self: Sized, @@ -1317,6 +1337,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn skip(self, n: usize) -> Skip where Self: Sized, @@ -1389,6 +1410,7 @@ pub trait Iterator { #[doc(alias = "limit")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn take(self, n: usize) -> Take where Self: Sized, @@ -1436,6 +1458,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn scan(self, initial_state: St, f: F) -> Scan where Self: Sized, @@ -1474,6 +1497,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn flat_map(self, f: F) -> FlatMap where Self: Sized, @@ -1558,6 +1582,7 @@ pub trait Iterator { /// [`flat_map()`]: Iterator::flat_map #[inline] #[stable(feature = "iterator_flatten", since = "1.29.0")] + #[rustc_non_const_trait_method] fn flatten(self) -> Flatten where Self: Sized, @@ -1714,6 +1739,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_map_windows", issue = "87155")] + #[rustc_non_const_trait_method] fn map_windows(self, f: F) -> MapWindows where Self: Sized, @@ -1776,6 +1802,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn fuse(self) -> Fuse where Self: Sized, @@ -1860,6 +1887,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn inspect(self, f: F) -> Inspect where Self: Sized, @@ -2019,6 +2047,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] #[rustc_diagnostic_item = "iterator_collect_fn"] + #[rustc_non_const_trait_method] fn collect>(self) -> B where Self: Sized, @@ -2106,6 +2135,7 @@ pub trait Iterator { /// [`collect`]: Iterator::collect #[inline] #[unstable(feature = "iterator_try_collect", issue = "94047")] + #[rustc_non_const_trait_method] fn try_collect(&mut self) -> ChangeOutputType where Self: Sized, @@ -2178,6 +2208,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_collect_into", issue = "94780")] + #[rustc_non_const_trait_method] fn collect_into>(self, collection: &mut E) -> &mut E where Self: Sized, @@ -2210,6 +2241,7 @@ pub trait Iterator { /// assert_eq!(odd, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn partition(self, f: F) -> (B, B) where Self: Sized, @@ -2272,6 +2304,7 @@ pub trait Iterator { /// assert!(a[i..].iter().all(|n| n % 2 == 1)); // odds /// ``` #[unstable(feature = "iter_partition_in_place", issue = "62543")] + #[rustc_non_const_trait_method] fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize where Self: Sized + DoubleEndedIterator, @@ -2329,6 +2362,7 @@ pub trait Iterator { /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase)); /// ``` #[unstable(feature = "iter_is_partitioned", issue = "62544")] + #[rustc_non_const_trait_method] fn is_partitioned

(mut self, mut predicate: P) -> bool where Self: Sized, @@ -2423,6 +2457,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_non_const_trait_method] fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -2481,6 +2516,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_non_const_trait_method] fn try_for_each(&mut self, f: F) -> R where Self: Sized, @@ -2600,6 +2636,7 @@ pub trait Iterator { #[doc(alias = "inject", alias = "foldl")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, @@ -2637,6 +2674,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_fold_self", since = "1.51.0")] + #[rustc_non_const_trait_method] fn reduce(mut self, f: F) -> Option where Self: Sized, @@ -2708,6 +2746,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iterator_try_reduce", issue = "87053")] + #[rustc_non_const_trait_method] fn try_reduce( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, @@ -2766,6 +2805,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn all(&mut self, f: F) -> bool where Self: Sized, @@ -2819,6 +2859,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn any(&mut self, f: F) -> bool where Self: Sized, @@ -2892,6 +2933,7 @@ pub trait Iterator { /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn find

(&mut self, predicate: P) -> Option where Self: Sized, @@ -2923,6 +2965,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] + #[rustc_non_const_trait_method] fn find_map(&mut self, f: F) -> Option where Self: Sized, @@ -2981,6 +3024,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", issue = "63178")] + #[rustc_non_const_trait_method] fn try_find( &mut self, f: impl FnMut(&Self::Item) -> R, @@ -3064,6 +3108,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn position

(&mut self, predicate: P) -> Option where Self: Sized, @@ -3129,6 +3174,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn rposition

(&mut self, predicate: P) -> Option where P: FnMut(Self::Item) -> bool, @@ -3178,6 +3224,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn max(self) -> Option where Self: Sized, @@ -3214,6 +3261,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn min(self) -> Option where Self: Sized, @@ -3236,6 +3284,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_non_const_trait_method] fn max_by_key(self, f: F) -> Option where Self: Sized, @@ -3269,6 +3318,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] + #[rustc_non_const_trait_method] fn max_by(self, compare: F) -> Option where Self: Sized, @@ -3296,6 +3346,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_non_const_trait_method] fn min_by_key(self, f: F) -> Option where Self: Sized, @@ -3329,6 +3380,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] + #[rustc_non_const_trait_method] fn min_by(self, compare: F) -> Option where Self: Sized, @@ -3366,6 +3418,7 @@ pub trait Iterator { #[inline] #[doc(alias = "reverse")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn rev(self) -> Rev where Self: Sized + DoubleEndedIterator, @@ -3402,6 +3455,7 @@ pub trait Iterator { /// assert_eq!(z, [3, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn unzip(self) -> (FromA, FromB) where FromA: Default + Extend, @@ -3433,6 +3487,7 @@ pub trait Iterator { /// ``` #[stable(feature = "iter_copied", since = "1.36.0")] #[rustc_diagnostic_item = "iter_copied"] + #[rustc_non_const_trait_method] fn copied<'a, T>(self) -> Copied where T: Copy + 'a, @@ -3481,6 +3536,7 @@ pub trait Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "iter_cloned"] + #[rustc_non_const_trait_method] fn cloned<'a, T>(self) -> Cloned where T: Clone + 'a, @@ -3512,6 +3568,7 @@ pub trait Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_non_const_trait_method] fn cycle(self) -> Cycle where Self: Sized + Clone, @@ -3555,6 +3612,7 @@ pub trait Iterator { /// ``` #[track_caller] #[unstable(feature = "iter_array_chunks", issue = "100450")] + #[rustc_non_const_trait_method] fn array_chunks(self) -> ArrayChunks where Self: Sized, @@ -3591,6 +3649,7 @@ pub trait Iterator { /// assert_eq!(sum, -0.0_f32); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_non_const_trait_method] fn sum(self) -> S where Self: Sized, @@ -3623,6 +3682,7 @@ pub trait Iterator { /// assert_eq!(factorial(5), 120); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_non_const_trait_method] fn product

(self) -> P where Self: Sized, @@ -3644,6 +3704,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn cmp(self, other: I) -> Ordering where I: IntoIterator, @@ -3671,6 +3732,7 @@ pub trait Iterator { /// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn cmp_by(self, other: I, cmp: F) -> Ordering where Self: Sized, @@ -3727,6 +3789,7 @@ pub trait Iterator { /// ``` /// #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn partial_cmp(self, other: I) -> Option where I: IntoIterator, @@ -3763,6 +3826,7 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option where Self: Sized, @@ -3796,6 +3860,7 @@ pub trait Iterator { /// assert_eq!([1].iter().eq([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn eq(self, other: I) -> bool where I: IntoIterator, @@ -3819,6 +3884,7 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(ys, |x, y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn eq_by(self, other: I, eq: F) -> bool where Self: Sized, @@ -3848,6 +3914,7 @@ pub trait Iterator { /// assert_eq!([1].iter().ne([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn ne(self, other: I) -> bool where I: IntoIterator, @@ -3869,6 +3936,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().lt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn lt(self, other: I) -> bool where I: IntoIterator, @@ -3890,6 +3958,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().le([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn le(self, other: I) -> bool where I: IntoIterator, @@ -3911,6 +3980,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().gt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn gt(self, other: I) -> bool where I: IntoIterator, @@ -3932,6 +4002,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().ge([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn ge(self, other: I) -> bool where I: IntoIterator, @@ -3961,6 +4032,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted(self) -> bool where Self: Sized, @@ -3987,6 +4059,7 @@ pub trait Iterator { /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); /// ``` #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted_by(mut self, compare: F) -> bool where Self: Sized, @@ -4031,6 +4104,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted_by_key(self, f: F) -> bool where Self: Sized, @@ -4046,6 +4120,7 @@ pub trait Iterator { #[inline] #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] + #[rustc_non_const_trait_method] unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item where Self: TrustedRandomAccessNoCoerce, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e8c9d26fb3b5..d650239a44c6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -87,6 +87,7 @@ #![allow(incomplete_features)] #![warn(multiple_supertrait_upcastable)] #![allow(internal_features)] +#![allow(unused_features)] #![deny(ffi_unwind_calls)] #![warn(unreachable_pub)] // Do not check link redundancy on bootstrapping phase @@ -95,10 +96,7 @@ // // Library features: // tidy-alphabetical-start -#![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(bigint_helper_methods)] -#![feature(bstr)] #![feature(bstr_internals)] #![feature(cfg_select)] #![feature(cfg_target_has_reliable_f16_f128)] @@ -111,24 +109,11 @@ #![feature(coverage_attribute)] #![feature(disjoint_bitor)] #![feature(internal_impls_macro)] -#![feature(ip)] -#![feature(is_ascii_octdigit)] #![feature(link_cfg)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(pattern_type_macro)] -#![feature(ptr_alignment_type)] -#![feature(ptr_metadata)] -#![feature(set_ptr_value)] -#![feature(slice_ptr_get)] -#![feature(str_internals)] -#![feature(str_split_inclusive_remainder)] -#![feature(str_split_remainder)] -#![feature(type_info)] #![feature(ub_checks)] -#![feature(unsafe_pinned)] -#![feature(utf16_extra)] -#![feature(variant_count)] // tidy-alphabetical-end // // Language features: @@ -173,7 +158,6 @@ #![feature(optimize_attribute)] #![feature(pattern_types)] #![feature(prelude_import)] -#![feature(reborrow)] #![feature(repr_simd)] #![feature(rustc_allow_const_fn_unstable)] #![feature(rustc_attrs)] @@ -186,6 +170,7 @@ #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] +#![feature(uint_carryless_mul)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] @@ -223,7 +208,7 @@ use prelude::rust_2024::*; #[macro_use] mod macros; -#[unstable(feature = "assert_matches", issue = "82775")] +#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")] pub use crate::macros::{assert_matches, debug_assert_matches}; #[unstable(feature = "derive_from", issue = "144889")] @@ -322,7 +307,7 @@ pub mod pat; pub mod pin; #[unstable(feature = "random", issue = "130703")] pub mod random; -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub mod range; pub mod result; pub mod sync; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3176f3c06709..d900b4a21b36 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -147,8 +147,6 @@ macro_rules! assert_ne { /// # Examples /// /// ``` -/// #![feature(assert_matches)] -/// /// use std::assert_matches; /// /// let a = Some(345); @@ -166,7 +164,7 @@ macro_rules! assert_ne { /// assert_matches!(a, Some(x) if x > 100); /// // assert_matches!(a, Some(x) if x < 100); // panics /// ``` -#[unstable(feature = "assert_matches", issue = "82775")] +#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(panic_internals)] #[rustc_macro_transparency = "semiopaque"] pub macro assert_matches { @@ -380,8 +378,6 @@ macro_rules! debug_assert_ne { /// # Examples /// /// ``` -/// #![feature(assert_matches)] -/// /// use std::debug_assert_matches; /// /// let a = Some(345); @@ -399,7 +395,7 @@ macro_rules! debug_assert_ne { /// debug_assert_matches!(a, Some(x) if x > 100); /// // debug_assert_matches!(a, Some(x) if x < 100); // panics /// ``` -#[unstable(feature = "assert_matches", issue = "82775")] +#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(assert_matches)] #[rustc_macro_transparency = "semiopaque"] pub macro debug_assert_matches($($arg:tt)*) { @@ -611,6 +607,9 @@ macro_rules! write { ($dst:expr, $($arg:tt)*) => { $dst.write_fmt($crate::format_args!($($arg)*)) }; + ($($arg:tt)*) => { + compile_error!("requires a destination and format arguments, like `write!(dest, \"format string\", args...)`") + }; } /// Writes formatted data into a buffer, with a newline appended. @@ -649,6 +648,9 @@ macro_rules! writeln { ($dst:expr, $($arg:tt)*) => { $dst.write_fmt($crate::format_args_nl!($($arg)*)) }; + ($($arg:tt)*) => { + compile_error!("requires a destination and format arguments, like `writeln!(dest, \"format string\", args...)`") + }; } /// Indicates unreachable code. @@ -1781,7 +1783,7 @@ pub(crate) mod builtin { /// /// See also [`std::alloc::GlobalAlloc`](../../../std/alloc/trait.GlobalAlloc.html). #[stable(feature = "global_allocator", since = "1.28.0")] - #[allow_internal_unstable(rustc_attrs)] + #[allow_internal_unstable(rustc_attrs, ptr_alignment_type)] #[rustc_builtin_macro] pub macro global_allocator($item:item) { /* compiler built-in */ diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 57416455e9de..7187c71799b9 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -927,14 +927,20 @@ marker_impls! { /// This is part of [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html), and is /// tracked by [#125735](https://github.com/rust-lang/rust/issues/125735). #[lang = "unsafe_unpin"] -pub(crate) unsafe auto trait UnsafeUnpin {} +#[unstable(feature = "unsafe_unpin", issue = "125735")] +pub unsafe auto trait UnsafeUnpin {} +#[unstable(feature = "unsafe_unpin", issue = "125735")] impl !UnsafeUnpin for UnsafePinned {} -unsafe impl UnsafeUnpin for PhantomData {} -unsafe impl UnsafeUnpin for *const T {} -unsafe impl UnsafeUnpin for *mut T {} -unsafe impl UnsafeUnpin for &T {} -unsafe impl UnsafeUnpin for &mut T {} +marker_impls! { +#[unstable(feature = "unsafe_unpin", issue = "125735")] + unsafe UnsafeUnpin for + {T: ?Sized} PhantomData, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} /// Types that do not require any pinning guarantees. /// @@ -1027,6 +1033,7 @@ impl !Unpin for PhantomPinned {} // continue working. Ideally PhantomPinned could just wrap an `UnsafePinned<()>` to get the same // effect, but we can't add a new field to an already stable unit struct -- that would be a breaking // change. +#[unstable(feature = "unsafe_unpin", issue = "125735")] impl !UnsafeUnpin for PhantomPinned {} marker_impls! { diff --git a/library/core/src/mem/maybe_dangling.rs b/library/core/src/mem/maybe_dangling.rs index 3c5437757e97..a5f77e667f97 100644 --- a/library/core/src/mem/maybe_dangling.rs +++ b/library/core/src/mem/maybe_dangling.rs @@ -29,7 +29,7 @@ use crate::{mem, ptr}; /// mem::forget(boxed); // <-- this is UB! /// ``` /// -/// Even though the `Box`e's destructor is not run (and thus we don't have a double free bug), this +/// Even though the `Box`'s destructor is not run (and thus we don't have a double free bug), this /// code is still UB. This is because when moving `boxed` into `forget`, its validity invariants /// are asserted, causing UB since the `Box` is dangling. The safety comment is as such wrong, as /// moving the `boxed` variable as part of the `forget` call *is* a use. diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 320eb97f83a4..594147720193 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1532,6 +1532,56 @@ impl MaybeUninit<[T; N]> { } } +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn from(arr: [MaybeUninit; N]) -> Self { + arr.transpose() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &*ptr::from_ref(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit] { + &*AsRef::<[MaybeUninit; N]>::as_ref(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &mut *ptr::from_mut(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit] { + &mut *AsMut::<[MaybeUninit; N]>::as_mut(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From> for [MaybeUninit; N] { + #[inline] + fn from(arr: MaybeUninit<[T; N]>) -> Self { + arr.transpose() + } +} + impl [MaybeUninit; N] { /// Transposes a `[MaybeUninit; N]` into a `MaybeUninit<[T; N]>`. /// diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7c486875a826..eb6f8f975721 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1260,7 +1260,10 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "ptr_alignment_type", issue = "102070")] - const ALIGNMENT: Alignment = Alignment::of::(); + const ALIGNMENT: Alignment = { + // This can't panic since type alignment is always a power of two. + Alignment::new(Self::ALIGN).unwrap() + }; /// `true` if this type requires no storage. /// `false` if its [size](size_of) is greater than zero. diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b30803c97c9..f8c2a259ba7e 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -2,7 +2,7 @@ //! runtime or const-eval processable way. use crate::any::TypeId; -use crate::intrinsics::type_of; +use crate::intrinsics::{type_id, type_of}; /// Compile-time type information. #[derive(Debug)] @@ -28,11 +28,17 @@ impl TypeId { impl Type { /// Returns the type information of the generic type parameter. + /// + /// Note: Unlike `TypeId`s obtained via `TypeId::of`, the `Type` + /// struct and its fields contain `TypeId`s that are not necessarily + /// derived from types that outlive `'static`. This means that using + /// the `TypeId`s (transitively) obtained from this function will + /// be able to break invariants that other `TypeId` consuming crates + /// may have assumed to hold. #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - // FIXME(reflection): don't require the 'static bound - pub const fn of() -> Self { - const { TypeId::of::().info() } + pub const fn of() -> Self { + const { type_id::().info() } } } @@ -49,6 +55,12 @@ pub enum TypeKind { Slice(Slice), /// Dynamic Traits. DynTrait(DynTrait), + /// Structs. + Struct(Struct), + /// Enums. + Enum(Enum), + /// Unions. + Union(Union), /// Primitive boolean type. Bool(Bool), /// Primitive character type. @@ -81,6 +93,8 @@ pub struct Tuple { #[non_exhaustive] #[unstable(feature = "type_info", issue = "146922")] pub struct Field { + /// The name of the field. + pub name: &'static str, /// The field's type. pub ty: TypeId, /// Offset in bytes from the parent type @@ -137,6 +151,95 @@ pub struct Trait { pub is_auto: bool, } +/// Compile-time type information about arrays. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Struct { + /// Instantiated generics of the struct. + pub generics: &'static [Generic], + /// All fields of the struct. + pub fields: &'static [Field], + /// Whether the struct field list is non-exhaustive. + pub non_exhaustive: bool, +} + +/// Compile-time type information about unions. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Union { + /// Instantiated generics of the union. + pub generics: &'static [Generic], + /// All fields of the union. + pub fields: &'static [Field], +} + +/// Compile-time type information about enums. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Enum { + /// Instantiated generics of the enum. + pub generics: &'static [Generic], + /// All variants of the enum. + pub variants: &'static [Variant], + /// Whether the enum variant list is non-exhaustive. + pub non_exhaustive: bool, +} + +/// Compile-time type information about variants of enums. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Variant { + /// The name of the variant. + pub name: &'static str, + /// All fields of the variant. + pub fields: &'static [Field], + /// Whether the enum variant fields is non-exhaustive. + pub non_exhaustive: bool, +} + +/// Compile-time type information about instantiated generics of structs, enum and union variants. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub enum Generic { + /// Lifetimes. + Lifetime(Lifetime), + /// Types. + Type(GenericType), + /// Const parameters. + Const(Const), +} + +/// Compile-time type information about generic lifetimes. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Lifetime { + // No additional information to provide for now. +} + +/// Compile-time type information about instantiated generic types. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct GenericType { + /// The type itself. + pub ty: TypeId, +} + +/// Compile-time type information about generic const parameters. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Const { + /// The const's type. + pub ty: TypeId, +} + /// Compile-time type information about `bool`. #[derive(Debug)] #[non_exhaustive] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index cc142fab8e82..d114b821655b 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -108,6 +108,17 @@ pub mod consts { pub const FRAC_1_SQRT_3: f128 = 0.577350269189625764509148780501957455647601751270126876018602_f128; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f128", issue = "116909")] + pub const SQRT_5: f128 = 2.23606797749978969640917366873127623544061835961152572427089_f128; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_1_SQRT_5: f128 = + 0.447213595499957939281834733746255247088123671922305144854179_f128; + /// Euler's number (e) #[unstable(feature = "f128", issue = "116909")] pub const E: f128 = 2.71828182845904523536028747135266249775724709369995957496697_f128; @@ -137,12 +148,20 @@ pub mod consts { pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128; } -#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))] +#[doc(test(attr( + feature(cfg_target_has_reliable_f16_f128), + allow(internal_features, unused_features) +)))] impl f128 { /// The radix or base of the internal representation of `f128`. #[unstable(feature = "f128", issue = "116909")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + // #[unstable(feature = "f128", issue = "116909")] + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 128; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one @@ -1454,7 +1473,11 @@ impl f128 { // Functions in this module fall into `core_float_math` // #[unstable(feature = "core_float_math", issue = "137578")] #[cfg(not(test))] -#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))] +#[doc(test(attr( + feature(cfg_target_has_reliable_f16_f128), + expect(internal_features), + allow(unused_features) +)))] impl f128 { /// Returns the largest integer less than or equal to `self`. /// diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index e97a44e991f6..373225c5806c 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -103,6 +103,16 @@ pub mod consts { // Also, #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f16", issue = "116909")] + pub const SQRT_5: f16 = 2.23606797749978969640917366873127623_f16; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_1_SQRT_5: f16 = 0.44721359549995793928183473374625524_f16; + /// Euler's number (e) #[unstable(feature = "f16", issue = "116909")] pub const E: f16 = 2.71828182845904523536028747135266250_f16; @@ -132,12 +142,20 @@ pub mod consts { pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16; } -#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))] +#[doc(test(attr( + feature(cfg_target_has_reliable_f16_f128), + allow(internal_features, unused_features) +)))] impl f16 { /// The radix or base of the internal representation of `f16`. #[unstable(feature = "f16", issue = "116909")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + // #[unstable(feature = "f16", issue = "116909")] + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 16; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 3d8249631037..f3c7961931a1 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -356,6 +356,14 @@ pub mod consts { #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const SQRT_5: f32 = 2.23606797749978969640917366873127623_f32; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const FRAC_1_SQRT_5: f32 = 0.44721359549995793928183473374625524_f32; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; @@ -390,6 +398,10 @@ impl f32 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 32; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one @@ -1809,6 +1821,7 @@ pub mod math { /// # Examples /// /// ``` + /// # #![allow(unused_features)] /// #![feature(core_float_math)] /// /// # // FIXME(#140515): mingw has an incorrect fma diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 566a6a7ec947..a6fd3b1cb5d0 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -356,6 +356,14 @@ pub mod consts { #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const SQRT_5: f64 = 2.23606797749978969640917366873127623_f64; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const FRAC_1_SQRT_5: f64 = 0.44721359549995793928183473374625524_f64; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; @@ -390,6 +398,10 @@ impl f64 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 64; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one @@ -1807,6 +1819,7 @@ pub mod math { /// # Examples /// /// ``` + /// # #![allow(unused_features)] /// #![feature(core_float_math)] /// /// # // FIXME(#140515): mingw has an incorrect fma diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9a27f8a0b5e6..b21865a9ae54 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2522,7 +2522,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] @@ -2544,7 +2544,7 @@ macro_rules! int_impl { /// /// assert_eq!((sum1, sum0), (6, 8)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2625,7 +2625,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")] @@ -2647,7 +2647,7 @@ macro_rules! int_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2717,12 +2717,12 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5i32.widening_mul(-2), (4294967286, -1)); /// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2747,7 +2747,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul(-2, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul(-2, 10), (0, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul(-10, 0), (2884901888, -3)); @@ -2757,8 +2757,8 @@ macro_rules! int_impl { "(", stringify!($SelfT), "::MAX.unsigned_abs() + 1, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2784,7 +2784,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul_add(-2, 0, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul_add(-2, 10, 10), (10, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul_add(-10, 0, 0), (2884901888, -3)); @@ -2794,8 +2794,8 @@ macro_rules! int_impl { "(", stringify!($UnsignedT), "::MAX, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 558426c94e5d..839a6fbdc9b7 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -244,6 +244,104 @@ macro_rules! midpoint_impl { }; } +macro_rules! widening_carryless_mul_impl { + ($SelfT:ty, $WideT:ty) => { + /// Performs a widening carry-less multiplication. + /// + /// # Examples + /// + /// ``` + /// #![feature(uint_carryless_mul)] + /// + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_carryless_mul(", + stringify!($SelfT), "::MAX), ", stringify!($WideT), "::MAX / 3);")] + /// ``` + #[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")] + #[doc(alias = "clmul")] + #[unstable(feature = "uint_carryless_mul", issue = "152080")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn widening_carryless_mul(self, rhs: $SelfT) -> $WideT { + (self as $WideT).carryless_mul(rhs as $WideT) + } + } +} + +macro_rules! carrying_carryless_mul_impl { + (u128, u256) => { + carrying_carryless_mul_impl! { @internal u128 => + pub const fn carrying_carryless_mul(self, rhs: Self, carry: Self) -> (Self, Self) { + let x0 = self as u64; + let x1 = (self >> 64) as u64; + let y0 = rhs as u64; + let y1 = (rhs >> 64) as u64; + + let z0 = u64::widening_carryless_mul(x0, y0); + let z2 = u64::widening_carryless_mul(x1, y1); + + // The grade school algorithm would compute: + // z1 = x0y1 ^ x1y0 + + // Instead, Karatsuba first computes: + let z3 = u64::widening_carryless_mul(x0 ^ x1, y0 ^ y1); + // Since it distributes over XOR, + // z3 == x0y0 ^ x0y1 ^ x1y0 ^ x1y1 + // |--| |---------| |--| + // == z0 ^ z1 ^ z2 + // so we can compute z1 as + let z1 = z3 ^ z0 ^ z2; + + let lo = z0 ^ (z1 << 64); + let hi = z2 ^ (z1 >> 64); + + (lo ^ carry, hi) + } + } + }; + ($SelfT:ty, $WideT:ty) => { + carrying_carryless_mul_impl! { @internal $SelfT => + pub const fn carrying_carryless_mul(self, rhs: Self, carry: Self) -> (Self, Self) { + // Can't use widening_carryless_mul because it's not implemented for usize. + let p = (self as $WideT).carryless_mul(rhs as $WideT); + + let lo = (p as $SelfT); + let hi = (p >> Self::BITS) as $SelfT; + + (lo ^ carry, hi) + } + } + }; + (@internal $SelfT:ty => $($fn:tt)*) => { + /// Calculates the "full carryless multiplication" without the possibility to overflow. + /// + /// This returns the low-order (wrapping) bits and the high-order (overflow) bits + /// of the result as two separate values, in that order. + /// + /// # Examples + /// + /// Please note that this example is shared among integer types, which is why `u8` is used. + /// + /// ``` + /// #![feature(uint_carryless_mul)] + /// + /// assert_eq!(0b1000_0000u8.carrying_carryless_mul(0b1000_0000, 0b0000), (0, 0b0100_0000)); + /// assert_eq!(0b1000_0000u8.carrying_carryless_mul(0b1000_0000, 0b1111), (0b1111, 0b0100_0000)); + #[doc = concat!("assert_eq!(", + stringify!($SelfT), "::MAX.carrying_carryless_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ", + "(!(", stringify!($SelfT), "::MAX / 3), ", stringify!($SelfT), "::MAX / 3));" + )] + /// ``` + #[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")] + #[doc(alias = "clmul")] + #[unstable(feature = "uint_carryless_mul", issue = "152080")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + $($fn)* + } +} + impl i8 { int_impl! { Self = i8, @@ -458,6 +556,9 @@ impl u8 { fsh_op = "0x36", fshl_result = "0x8", fshr_result = "0x8d", + clmul_lhs = "0x12", + clmul_rhs = "0x34", + clmul_result = "0x28", swap_op = "0x12", swapped = "0x12", reversed = "0x48", @@ -468,6 +569,8 @@ impl u8 { bound_condition = "", } midpoint_impl! { u8, u16, unsigned } + widening_carryless_mul_impl! { u8, u16 } + carrying_carryless_mul_impl! { u8, u16 } /// Checks if the value is within the ASCII range. /// @@ -1095,6 +1198,9 @@ impl u16 { fsh_op = "0x2de", fshl_result = "0x30", fshr_result = "0x302d", + clmul_lhs = "0x9012", + clmul_rhs = "0xcd34", + clmul_result = "0x928", swap_op = "0x1234", swapped = "0x3412", reversed = "0x2c48", @@ -1105,6 +1211,8 @@ impl u16 { bound_condition = "", } midpoint_impl! { u16, u32, unsigned } + widening_carryless_mul_impl! { u16, u32 } + carrying_carryless_mul_impl! { u16, u32 } /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`]. /// @@ -1145,6 +1253,9 @@ impl u32 { fsh_op = "0x2fe78e45", fshl_result = "0xb32f", fshr_result = "0xb32fe78e", + clmul_lhs = "0x56789012", + clmul_rhs = "0xf52ecd34", + clmul_result = "0x9b980928", swap_op = "0x12345678", swapped = "0x78563412", reversed = "0x1e6a2c48", @@ -1155,6 +1266,8 @@ impl u32 { bound_condition = "", } midpoint_impl! { u32, u64, unsigned } + widening_carryless_mul_impl! { u32, u64 } + carrying_carryless_mul_impl! { u32, u64 } } impl u64 { @@ -1171,6 +1284,9 @@ impl u64 { fsh_op = "0x2fe78e45983acd98", fshl_result = "0x6e12fe", fshr_result = "0x6e12fe78e45983ac", + clmul_lhs = "0x7890123456789012", + clmul_rhs = "0xdd358416f52ecd34", + clmul_result = "0xa6299579b980928", swap_op = "0x1234567890123456", swapped = "0x5634129078563412", reversed = "0x6a2c48091e6a2c48", @@ -1181,6 +1297,8 @@ impl u64 { bound_condition = "", } midpoint_impl! { u64, u128, unsigned } + widening_carryless_mul_impl! { u64, u128 } + carrying_carryless_mul_impl! { u64, u128 } } impl u128 { @@ -1197,6 +1315,9 @@ impl u128 { fsh_op = "0x2fe78e45983acd98039000008736273", fshl_result = "0x4f7602fe", fshr_result = "0x4f7602fe78e45983acd9803900000873", + clmul_lhs = "0x12345678901234567890123456789012", + clmul_rhs = "0x4317e40ab4ddcf05dd358416f52ecd34", + clmul_result = "0xb9cf660de35d0c170a6299579b980928", swap_op = "0x12345678901234567890123456789012", swapped = "0x12907856341290785634129078563412", reversed = "0x48091e6a2c48091e6a2c48091e6a2c48", @@ -1209,6 +1330,7 @@ impl u128 { bound_condition = "", } midpoint_impl! { u128, unsigned } + carrying_carryless_mul_impl! { u128, u256 } } #[cfg(target_pointer_width = "16")] @@ -1223,9 +1345,12 @@ impl usize { rot = 4, rot_op = "0xa003", rot_result = "0x3a", - fsh_op = "0x2fe78e45983acd98039000008736273", - fshl_result = "0x4f7602fe", - fshr_result = "0x4f7602fe78e45983acd9803900000873", + fsh_op = "0x2de", + fshl_result = "0x30", + fshr_result = "0x302d", + clmul_lhs = "0x9012", + clmul_rhs = "0xcd34", + clmul_result = "0x928", swap_op = "0x1234", swapped = "0x3412", reversed = "0x2c48", @@ -1236,6 +1361,7 @@ impl usize { bound_condition = " on 16-bit targets", } midpoint_impl! { usize, u32, unsigned } + carrying_carryless_mul_impl! { usize, u32 } } #[cfg(target_pointer_width = "32")] @@ -1253,6 +1379,9 @@ impl usize { fsh_op = "0x2fe78e45", fshl_result = "0xb32f", fshr_result = "0xb32fe78e", + clmul_lhs = "0x56789012", + clmul_rhs = "0xf52ecd34", + clmul_result = "0x9b980928", swap_op = "0x12345678", swapped = "0x78563412", reversed = "0x1e6a2c48", @@ -1263,6 +1392,7 @@ impl usize { bound_condition = " on 32-bit targets", } midpoint_impl! { usize, u64, unsigned } + carrying_carryless_mul_impl! { usize, u64 } } #[cfg(target_pointer_width = "64")] @@ -1280,6 +1410,9 @@ impl usize { fsh_op = "0x2fe78e45983acd98", fshl_result = "0x6e12fe", fshr_result = "0x6e12fe78e45983ac", + clmul_lhs = "0x7890123456789012", + clmul_rhs = "0xdd358416f52ecd34", + clmul_result = "0xa6299579b980928", swap_op = "0x1234567890123456", swapped = "0x5634129078563412", reversed = "0x6a2c48091e6a2c48", @@ -1290,6 +1423,7 @@ impl usize { bound_condition = " on 64-bit targets", } midpoint_impl! { usize, u128, unsigned } + carrying_carryless_mul_impl! { usize, u128 } } impl usize { diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index 9ac0eb72bdcb..33b2a6741abd 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -5,45 +5,33 @@ )] use crate::cmp::Ordering; -use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::marker::StructuralPartialEq; +use crate::{fmt, pattern_type}; macro_rules! define_valid_range_type { ($( $(#[$m:meta])* - $vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal); + $vis:vis struct $name:ident($int:ident is $pat:pat); )+) => {$( - #[derive(Clone, Copy, Eq)] + #[derive(Clone, Copy)] #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start($low)] - #[rustc_layout_scalar_valid_range_end($high)] $(#[$m])* - $vis struct $name($int); - - const _: () = { - // With the `valid_range` attributes, it's always specified as unsigned - assert!(<$uint>::MIN == 0); - let ulow: $uint = $low; - let uhigh: $uint = $high; - assert!(ulow <= uhigh); - - assert!(size_of::<$int>() == size_of::<$uint>()); - }; - + $vis struct $name(pattern_type!($int is $pat)); impl $name { #[inline] pub const fn new(val: $int) -> Option { - if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) { - // SAFETY: just checked the inclusive range - Some(unsafe { $name(val) }) + #[allow(non_contiguous_range_endpoints)] + if let $pat = val { + // SAFETY: just checked that the value matches the pattern + Some(unsafe { $name(crate::mem::transmute(val)) }) } else { None } } /// Constructs an instance of this type from the underlying integer - /// primitive without checking whether its zero. + /// primitive without checking whether its valid. /// /// # Safety /// Immediate language UB if `val` is not within the valid range for this @@ -51,13 +39,13 @@ macro_rules! define_valid_range_type { #[inline] pub const unsafe fn new_unchecked(val: $int) -> Self { // SAFETY: Caller promised that `val` is within the valid range. - unsafe { $name(val) } + unsafe { crate::mem::transmute(val) } } #[inline] pub const fn as_inner(self) -> $int { - // SAFETY: This is a transparent wrapper, so unwrapping it is sound - // (Not using `.0` due to MCP#807.) + // SAFETY: pattern types are always legal values of their base type + // (Not using `.0` because that has perf regressions.) unsafe { crate::mem::transmute(self) } } } @@ -67,6 +55,8 @@ macro_rules! define_valid_range_type { // by . impl StructuralPartialEq for $name {} + impl Eq for $name {} + impl PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { @@ -104,7 +94,7 @@ macro_rules! define_valid_range_type { } define_valid_range_type! { - pub struct Nanoseconds(u32 as u32 in 0..=999_999_999); + pub struct Nanoseconds(u32 is 0..=999_999_999); } impl Nanoseconds { @@ -120,47 +110,32 @@ impl const Default for Nanoseconds { } } -define_valid_range_type! { - pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff); - pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff); - pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); - - pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff); - pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff); - pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); - - pub struct NonZeroCharInner(char as u32 in 1..=0x10ffff); -} - -#[cfg(target_pointer_width = "16")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff); -} -#[cfg(target_pointer_width = "32")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff); -} -#[cfg(target_pointer_width = "64")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff); -} +const HALF_USIZE: usize = usize::MAX >> 1; define_valid_range_type! { - pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe); - pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe); + pub struct NonZeroU8Inner(u8 is 1..); + pub struct NonZeroU16Inner(u16 is 1..); + pub struct NonZeroU32Inner(u32 is 1..); + pub struct NonZeroU64Inner(u64 is 1..); + pub struct NonZeroU128Inner(u128 is 1..); - pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe); - pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe); + pub struct NonZeroI8Inner(i8 is ..0 | 1..); + pub struct NonZeroI16Inner(i16 is ..0 | 1..); + pub struct NonZeroI32Inner(i32 is ..0 | 1..); + pub struct NonZeroI64Inner(i64 is ..0 | 1..); + pub struct NonZeroI128Inner(i128 is ..0 | 1..); + + pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE); + pub struct NonZeroUsizeInner(usize is 1..); + pub struct NonZeroIsizeInner(isize is ..0 | 1..); + + pub struct U32NotAllOnes(u32 is 0..u32::MAX); + pub struct I32NotAllOnes(i32 is ..-1 | 0..); + + pub struct U64NotAllOnes(u64 is 0..u64::MAX); + pub struct I64NotAllOnes(i64 is ..-1 | 0..); + + pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}'); } pub trait NotAllOnesHelper { @@ -181,7 +156,7 @@ impl NotAllOnesHelper for i64 { } define_valid_range_type! { - pub struct CodePointInner(u32 as u32 in 0..=0x10ffff); + pub struct CodePointInner(u32 is 0..=0x10ffff); } impl CodePointInner { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 2b5279efb7f7..f52438e4e62e 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -31,7 +31,7 @@ use crate::{fmt, intrinsics, ptr, ub_checks}; issue = "none" )] pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed { - #[doc(hidden)] + /// A type like `Self` but with a niche that includes zero. type NonZeroInner: Sized + Copy; } @@ -1240,16 +1240,176 @@ macro_rules! nonzero_integer { // So the result cannot be zero. unsafe { Self::new_unchecked(self.get().saturating_pow(other)) } } + + /// Parses a non-zero integer from an ASCII-byte slice with decimal digits. + /// + /// The characters are expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in Rust literals) + /// also represent an error. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_ascii(b\"+10\"), Ok(NonZero::new(10)?));")] + /// # Some(()) + /// # } + /// ``` + /// + /// Trailing space returns error: + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_ascii(b\"1 \").is_err());")] + /// ``` + #[unstable(feature = "int_from_ascii", issue = "134821")] + #[inline] + pub const fn from_ascii(src: &[u8]) -> Result { + Self::from_ascii_radix(src, 10) + } + + /// Parses a non-zero integer from an ASCII-byte slice with digits in a given base. + /// + /// The characters are expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in Rust literals) + /// also represent an error. + /// + /// Digits are a subset of these characters, depending on `radix`: + /// + /// - `0-9` + /// - `a-z` + /// - `A-Z` + /// + /// # Panics + /// + /// This method panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_ascii_radix(b\"A\", 16), Ok(NonZero::new(10)?));")] + /// # Some(()) + /// # } + /// ``` + /// + /// Trailing space returns error: + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_ascii_radix(b\"1 \", 10).is_err());")] + /// ``` + #[unstable(feature = "int_from_ascii", issue = "134821")] + #[inline] + pub const fn from_ascii_radix(src: &[u8], radix: u32) -> Result { + let n = match <$Int>::from_ascii_radix(src, radix) { + Ok(n) => n, + Err(err) => return Err(err), + }; + if let Some(n) = Self::new(n) { + Ok(n) + } else { + Err(ParseIntError { kind: IntErrorKind::Zero }) + } + } + + /// Parses a non-zero integer from a string slice with digits in a given base. + /// + /// The string is expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in Rust literals) + /// also represent an error. + /// + /// Digits are a subset of these characters, depending on `radix`: + /// + /// - `0-9` + /// - `a-z` + /// - `A-Z` + /// + /// # Panics + /// + /// This method panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_from_str_radix)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_str_radix(\"A\", 16), Ok(NonZero::new(10)?));")] + /// # Some(()) + /// # } + /// ``` + /// + /// Trailing space returns error: + /// + /// ``` + /// #![feature(nonzero_from_str_radix)] + /// + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_str_radix(\"1 \", 10).is_err());")] + /// ``` + #[unstable(feature = "nonzero_from_str_radix", issue = "152193")] + #[inline] + pub const fn from_str_radix(src: &str, radix: u32) -> Result { + Self::from_ascii_radix(src.as_bytes(), radix) + } } #[stable(feature = "nonzero_parse", since = "1.35.0")] impl FromStr for NonZero<$Int> { type Err = ParseIntError; fn from_str(src: &str) -> Result { - Self::new(<$Int>::from_str_radix(src, 10)?) - .ok_or(ParseIntError { - kind: IntErrorKind::Zero - }) + Self::from_str_radix(src, 10) } } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c48320c0eab3..cf79635dcd87 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -17,6 +17,9 @@ macro_rules! uint_impl { fsh_op = $fsh_op:literal, fshl_result = $fshl_result:literal, fshr_result = $fshr_result:literal, + clmul_lhs = $clmul_rhs:literal, + clmul_rhs = $clmul_lhs:literal, + clmul_result = $clmul_result:literal, swap_op = $swap_op:literal, swapped = $swapped:literal, reversed = $reversed:literal, @@ -482,6 +485,62 @@ macro_rules! uint_impl { unsafe { intrinsics::unchecked_funnel_shr(self, rhs, n) } } + /// Performs a carry-less multiplication, returning the lower bits. + /// + /// This operation is similar to long multiplication, except that exclusive or is used + /// instead of addition. The implementation is equivalent to: + /// + /// ```no_run + #[doc = concat!("pub fn carryless_mul(lhs: ", stringify!($SelfT), ", rhs: ", stringify!($SelfT), ") -> ", stringify!($SelfT), "{")] + /// let mut retval = 0; + #[doc = concat!(" for i in 0..", stringify!($SelfT), "::BITS {")] + /// if (rhs >> i) & 1 != 0 { + /// // long multiplication would use += + /// retval ^= lhs << i; + /// } + /// } + /// retval + /// } + /// ``` + /// + /// The actual implementation is more efficient, and on some platforms lowers directly to a + /// dedicated instruction. + /// + /// # Uses + /// + /// Carryless multiplication can be used to turn a bitmask of quote characters into a + /// bit mask of characters surrounded by quotes: + /// + /// ```no_run + /// r#"abc xxx "foobar" zzz "a"!"#; // input string + /// 0b0000000010000001000001010; // quote_mask + /// 0b0000000001111110000000100; // quote_mask.carryless_mul(!0) & !quote_mask + /// ``` + /// + /// Another use is in cryptography, where carryless multiplication allows for efficient + /// implementations of polynomial multiplication in `GF(2)[X]`, the polynomial ring + /// over `GF(2)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(uint_carryless_mul)] + /// + #[doc = concat!("let a = ", $clmul_lhs, stringify!($SelfT), ";")] + #[doc = concat!("let b = ", $clmul_rhs, stringify!($SelfT), ";")] + /// + #[doc = concat!("assert_eq!(a.carryless_mul(b), ", $clmul_result, ");")] + /// ``` + #[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")] + #[doc(alias = "clmul")] + #[unstable(feature = "uint_carryless_mul", issue = "152080")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn carryless_mul(self, rhs: Self) -> Self { + intrinsics::carryless_mul(self, rhs) + } + /// Reverses the byte order of the integer. /// /// # Examples @@ -2807,7 +2866,7 @@ macro_rules! uint_impl { /// assert_eq!((sum1, sum0), (9, 6)); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2899,7 +2958,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3011,14 +3070,14 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")] /// ``` /// /// Compared to other `*_mul` methods: /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")] @@ -3028,12 +3087,12 @@ macro_rules! uint_impl { /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5u32.widening_mul(2), (10, 0)); /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3072,7 +3131,6 @@ macro_rules! uint_impl { /// implementing it for wider-than-native types. /// /// ``` - /// #![feature(bigint_helper_methods)] /// fn scalar_mul_eq(little_endian_digits: &mut Vec, multiplicand: u16) { /// let mut carry = 0; /// for d in little_endian_digits.iter_mut() { @@ -3097,7 +3155,8 @@ macro_rules! uint_impl { /// except that it gives the value of the overflow instead of just whether one happened: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// # #![allow(unused_features)] + /// #![feature(const_unsigned_bigint_helpers)] /// let r = u8::carrying_mul(7, 13, 0); /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); /// let r = u8::carrying_mul(13, 42, 0); @@ -3109,14 +3168,15 @@ macro_rules! uint_impl { /// [`wrapping_add`](Self::wrapping_add) methods: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// # #![allow(unused_features)] + /// #![feature(const_unsigned_bigint_helpers)] /// assert_eq!( /// 789_u16.carrying_mul(456, 123).0, /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3182,7 +3242,7 @@ macro_rules! uint_impl { /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 3cc184f0ab75..84fc98cf73f1 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -151,7 +151,7 @@ impl ControlFlow { /// ``` #[inline] #[stable(feature = "control_flow_enum_is", since = "1.59.0")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_stable(feature = "min_const_control_flow", since = "CURRENT_RUSTC_VERSION")] pub const fn is_break(&self) -> bool { matches!(*self, ControlFlow::Break(_)) } @@ -168,7 +168,7 @@ impl ControlFlow { /// ``` #[inline] #[stable(feature = "control_flow_enum_is", since = "1.59.0")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_stable(feature = "min_const_control_flow", since = "CURRENT_RUSTC_VERSION")] pub const fn is_continue(&self) -> bool { matches!(*self, ControlFlow::Continue(_)) } @@ -264,7 +264,7 @@ impl ControlFlow { /// ``` #[inline] #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] pub const fn break_ok(self) -> Result { match self { ControlFlow::Continue(c) => Err(c), @@ -377,7 +377,7 @@ impl ControlFlow { /// ``` #[inline] #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] pub const fn continue_ok(self) -> Result { match self { ControlFlow::Continue(c) => Ok(c), diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index a0b74ff383ea..c15c8f20c16b 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -773,7 +773,7 @@ impl Bound<&T> { /// ``` #[unstable(feature = "bound_copied", issue = "145966")] #[must_use] - pub fn copied(self) -> Bound { + pub const fn copied(self) -> Bound { match self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(*x), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index eb4f978b7c19..3dc53941977c 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -584,7 +584,7 @@ use crate::clone::TrivialClone; use crate::iter::{self, FusedIterator, TrustedLen}; use crate::marker::Destruct; -use crate::ops::{self, ControlFlow, Deref, DerefMut}; +use crate::ops::{self, ControlFlow, Deref, DerefMut, Residual, Try}; use crate::panicking::{panic, panic_display}; use crate::pin::Pin; use crate::{cmp, convert, hint, mem, slice}; @@ -1816,6 +1816,49 @@ impl Option { unsafe { self.as_mut().unwrap_unchecked() } } + /// If the option is `None`, calls the closure and inserts its output if successful. + /// + /// If the closure returns a residual value such as `Err` or `None`, + /// that residual value is returned and nothing is inserted. + /// + /// If the option is `Some`, nothing is inserted. + /// + /// Unless a residual is returned, a mutable reference to the value + /// of the option will be output. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_get_or_try_insert_with)] + /// let mut o1: Option = None; + /// let mut o2: Option = None; + /// + /// let number = "12345"; + /// + /// assert_eq!(o1.get_or_try_insert_with(|| number.parse()).copied(), Ok(12345)); + /// assert!(o2.get_or_try_insert_with(|| number.parse()).is_err()); + /// assert_eq!(o1, Some(12345)); + /// assert_eq!(o2, None); + /// ``` + #[inline] + #[unstable(feature = "option_get_or_try_insert_with", issue = "143648")] + pub fn get_or_try_insert_with<'a, R, F>( + &'a mut self, + f: F, + ) -> >::TryType + where + F: FnOnce() -> R, + R: Try>, + { + if let None = self { + *self = Some(f()?); + } + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. + + Try::from_output(unsafe { self.as_mut().unwrap_unchecked() }) + } + ///////////////////////////////////////////////////////////////////////// // Misc ///////////////////////////////////////////////////////////////////////// @@ -2257,7 +2300,8 @@ impl const Default for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Option { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for Option { type Item = T; type IntoIter = IntoIter; @@ -2429,7 +2473,8 @@ struct Item { opt: Option, } -impl Iterator for Item { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for Item { type Item = A; #[inline] @@ -2439,7 +2484,7 @@ impl Iterator for Item { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.len(); + let len = self.opt.len(); (len, Some(len)) } } @@ -2563,7 +2608,8 @@ pub struct IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for IntoIter { type Item = A; #[inline] diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 42c95e6c9cd2..b106314f14d1 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -13,7 +13,12 @@ use crate::{cmp, fmt, hash, mem, num}; #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] -pub struct Alignment(AlignmentEnum); +pub struct Alignment { + // This field is never used directly (nor is the enum), + // as it's just there to convey the validity invariant. + // (Hopefully it'll eventually be a pattern type instead.) + _inner_repr_trick: AlignmentEnum, +} // Alignment is `repr(usize)`, but via extra steps. const _: () = assert!(size_of::() == size_of::()); @@ -37,7 +42,7 @@ impl Alignment { /// assert_eq!(Alignment::MIN.as_usize(), 1); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0); + pub const MIN: Self = Self::new(1).unwrap(); /// Returns the alignment for a type. /// @@ -47,8 +52,7 @@ impl Alignment { #[inline] #[must_use] pub const fn of() -> Self { - // This can't actually panic since type alignment is always a power of two. - const { Alignment::new(align_of::()).unwrap() } + ::ALIGNMENT } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. @@ -108,7 +112,6 @@ impl Alignment { /// /// ``` /// #![feature(ptr_alignment_type)] - /// #![feature(layout_for_ptr)] /// use std::ptr::Alignment; /// /// assert_eq!(unsafe { Alignment::of_val_raw(&5i32) }.as_usize(), 4); @@ -166,7 +169,10 @@ impl Alignment { #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn as_usize(self) -> usize { - self.0 as usize + // Going through `as_nonzero` helps this be more clearly the inverse of + // `new_unchecked`, letting MIR optimizations fold it away. + + self.as_nonzero().get() } /// Returns the alignment as a [NonZero]<[usize]>. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 00b71f9a997c..75777144dfb8 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -239,7 +239,7 @@ impl *const T { /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// assert_eq!(val_back, &10); /// } /// ``` @@ -259,6 +259,7 @@ impl *const T { /// /// [`is_null`]: #method.is_null /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_ref_unchecked`]: #method.as_ref_unchecked #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] @@ -283,15 +284,14 @@ impl *const T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { /// assert_eq!(ptr.as_ref_unchecked(), &10); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -1386,6 +1386,43 @@ impl *const T { pub const fn cast_uninit(self) -> *const MaybeUninit { self as _ } + + /// Forms a raw slice from a pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// This function is safe, but actually using the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. + /// + /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// // create a slice pointer when starting out with a pointer to the first element + /// let x = [5, 6, 7]; + /// let raw_pointer = x.as_ptr(); + /// let slice = raw_pointer.cast_slice(3); + /// assert_eq!(unsafe { &*slice }[2], 7); + /// ``` + /// + /// You must ensure that the pointer is valid and not null before dereferencing + /// the raw slice. A slice reference must never have a null pointer, even if it's empty. + /// + /// ```rust,should_panic + /// #![feature(ptr_cast_slice)] + /// use std::ptr; + /// let danger: *const [u8] = ptr::null::().cast_slice(0); + /// unsafe { + /// danger.as_ref().expect("references must not be null"); + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> *const [T] { + slice_from_raw_parts(self, len) + } } impl *const MaybeUninit { /// Casts from a maybe-uninitialized type to its initialized version. diff --git a/library/core/src/ptr/docs/as_ref.md b/library/core/src/ptr/docs/as_ref.md index 0c0d2768c748..2c7d6e149b76 100644 --- a/library/core/src/ptr/docs/as_ref.md +++ b/library/core/src/ptr/docs/as_ref.md @@ -1,6 +1,7 @@ Returns `None` if the pointer is null, or else returns a shared reference to the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] -must be used instead. +must be used instead. If the value is known to be non-null, [`as_ref_unchecked`] +can be used instead. # Safety @@ -14,6 +15,5 @@ determined to be null or not. See [`is_null`] for more information. # Null-unchecked version -If you are sure the pointer can never be null and are looking for some kind of -`as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can -dereference the pointer directly. +If you are sure the pointer can never be null, you can use `as_ref_unchecked` which returns +`&mut T` instead of `Option<&mut T>`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 11e0a83bd7ec..f19a5d02b98d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -230,7 +230,7 @@ impl *mut T { /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// println!("We got back the value: {val_back}!"); /// } /// ``` @@ -252,7 +252,8 @@ impl *mut T { /// For the mutable counterpart see [`as_mut`]. /// /// [`is_null`]: #method.is_null-1 - /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_ref_unchecked`]: #method.as_ref_unchecked-1 /// [`as_mut`]: #method.as_mut #[stable(feature = "ptr_as_ref", since = "1.9.0")] @@ -281,15 +282,14 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -531,11 +531,13 @@ impl *mut T { /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] - /// must be used instead. + /// must be used instead. If the value is known to be non-null, [`as_mut_unchecked`] + /// can be used instead. /// /// For the shared counterpart see [`as_ref`]. /// /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_mut_unchecked`]: #method.as_mut_unchecked /// [`as_ref`]: pointer#method.as_ref-1 /// /// # Safety @@ -564,14 +566,13 @@ impl *mut T { /// /// # Null-unchecked version /// - /// If you are sure the pointer can never be null and are looking for some kind of - /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that - /// you can dereference the pointer directly. + /// If you are sure the pointer can never be null, you can use `as_mut_unchecked` which returns + /// `&mut T` instead of `Option<&mut T>`. /// /// ``` /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); - /// let first_value = unsafe { &mut *ptr }; + /// let first_value = unsafe { ptr.as_mut_unchecked() }; /// *first_value = 4; /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". @@ -603,7 +604,6 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); /// let first_value = unsafe { ptr.as_mut_unchecked() }; @@ -611,8 +611,8 @@ impl *mut T { /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` - // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { @@ -1655,6 +1655,51 @@ impl *mut T { pub const fn cast_uninit(self) -> *mut MaybeUninit { self as _ } + + /// Forms a raw mutable slice from a pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// Performs the same functionality as [`cast_slice`] on a `*const T`, except that a + /// raw mutable slice is returned, as opposed to a raw immutable slice. + /// + /// This function is safe, but actually using the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements. + /// + /// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut + /// [`cast_slice`]: pointer::cast_slice + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// + /// let x = &mut [5, 6, 7]; + /// let slice = x.as_mut_ptr().cast_slice(3); + /// + /// unsafe { + /// (*slice)[2] = 99; // assign a value at an index in the slice + /// }; + /// + /// assert_eq!(unsafe { &*slice }[2], 99); + /// ``` + /// + /// You must ensure that the pointer is valid and not null before dereferencing + /// the raw slice. A slice reference must never have a null pointer, even if it's empty. + /// + /// ```rust,should_panic + /// #![feature(ptr_cast_slice)] + /// use std::ptr; + /// let danger: *mut [u8] = ptr::null_mut::().cast_slice(0); + /// unsafe { + /// danger.as_mut().expect("references must not be null"); + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> *mut [T] { + slice_from_raw_parts_mut(self, len) + } } impl *mut MaybeUninit { /// Casts from a maybe-uninitialized type to its initialized version. @@ -1755,7 +1800,6 @@ impl *mut [T] { /// /// ``` /// #![feature(raw_slice_split)] - /// #![feature(slice_ptr_get)] /// /// let mut v = [1, 0, 3, 0, 5, 6]; /// let ptr = &mut v as *mut [_]; diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index cb43d095f5d1..7b9e638289bf 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1377,6 +1377,35 @@ impl NonNull { pub const fn cast_uninit(self) -> NonNull> { self.cast() } + + /// Creates a non-null raw slice from a thin pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// This function is safe, but dereferencing the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// use std::ptr::NonNull; + /// + /// // create a slice pointer when starting out with a pointer to the first element + /// let mut x = [5, 6, 7]; + /// let nonnull_pointer = NonNull::new(x.as_mut_ptr()).unwrap(); + /// let slice = nonnull_pointer.cast_slice(3); + /// assert_eq!(unsafe { slice.as_ref()[2] }, 7); + /// ``` + /// + /// (Note that this example artificially demonstrates a use of this method, + /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) + #[inline] + #[must_use] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> NonNull<[T]> { + NonNull::slice_from_raw_parts(self, len) + } } impl NonNull> { /// Casts from a maybe-uninitialized type to its initialized version. diff --git a/library/core/src/random.rs b/library/core/src/random.rs index 8a51fb289d8f..06f4f30efe2b 100644 --- a/library/core/src/random.rs +++ b/library/core/src/random.rs @@ -1,6 +1,6 @@ //! Random value generation. -use crate::range::RangeFull; +use crate::ops::RangeFull; /// A source of randomness. #[unstable(feature = "random", issue = "130703")] diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 4b87d426bda7..0ef0d192a868 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -24,14 +24,26 @@ mod iter; #[unstable(feature = "new_range_api", issue = "125687")] pub mod legacy; -use Bound::{Excluded, Included, Unbounded}; #[doc(inline)] -pub use iter::{RangeFromIter, RangeInclusiveIter, RangeIter}; +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] +pub use iter::RangeInclusiveIter; +#[doc(inline)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub use iter::{RangeFromIter, RangeIter}; -#[doc(inline)] -pub use crate::iter::Step; -#[doc(inline)] -pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; +// FIXME(#125687): re-exports temporarily removed +// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo) +// can't be made unstable. +// +// #[doc(inline)] +// #[unstable(feature = "new_range_api", issue = "125687")] +// pub use crate::iter::Step; +// #[doc(inline)] +// #[unstable(feature = "new_range_api", issue = "125687")] +// pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; +use crate::iter::Step; +use crate::ops::Bound::{self, Excluded, Included, Unbounded}; +use crate::ops::{IntoBounds, RangeBounds}; /// A (half-open) range bounded inclusively below and exclusively above /// (`start..end` in a future edition). @@ -226,7 +238,6 @@ impl const From> for Range { /// The `start..=last` syntax is a `RangeInclusive`: /// /// ``` -/// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 }); @@ -234,17 +245,17 @@ impl const From> for Range { /// ``` #[lang = "RangeInclusiveCopy"] #[derive(Clone, Copy, PartialEq, Eq, Hash)] -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub last: Idx, } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; @@ -260,7 +271,6 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).contains(&2)); @@ -278,7 +288,7 @@ impl> RangeInclusive { /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0)); /// ``` #[inline] - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn contains(&self, item: &U) -> bool where @@ -293,7 +303,6 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).is_empty()); @@ -304,14 +313,13 @@ impl> RangeInclusive { /// The range is empty if either side is incomparable: /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty()); /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty()); /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty()); /// ``` - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn is_empty(&self) -> bool @@ -330,7 +338,6 @@ impl RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n); @@ -338,23 +345,14 @@ impl RangeInclusive { /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn iter(&self) -> RangeInclusiveIter { self.clone().into_iter() } } -impl RangeInclusive { - /// Converts to an exclusive `Range` for `SliceIndex` implementations. - /// The caller is responsible for dealing with `last == usize::MAX`. - #[inline] - pub(crate) const fn into_slice_range(self) -> Range { - Range { start: self.start, end: self.last + 1 } - } -} - -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { @@ -371,7 +369,7 @@ impl const RangeBounds for RangeInclusive { /// If you need to use this implementation where `T` is unsized, /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { @@ -382,8 +380,8 @@ impl const RangeBounds for RangeInclusive<&T> { } } -// #[unstable(feature = "range_into_bounds", issue = "136903")] -#[unstable(feature = "new_range_api", issue = "125687")] +// #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] +#[unstable(feature = "range_into_bounds", issue = "136903")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const IntoBounds for RangeInclusive { fn into_bounds(self) -> (Bound, Bound) { @@ -391,7 +389,7 @@ impl const IntoBounds for RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for legacy::RangeInclusive { #[inline] @@ -399,7 +397,7 @@ impl const From> for legacy::RangeInclusive { Self::new(value.start, value.last) } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for RangeInclusive { #[inline] @@ -650,12 +648,13 @@ impl> RangeToInclusive { } } +#[unstable(feature = "new_range_api", issue = "125687")] impl From> for RangeToInclusive { fn from(value: legacy::RangeToInclusive) -> Self { Self { last: value.end } } } - +#[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeToInclusive { fn from(value: RangeToInclusive) -> Self { Self { end: value.last } diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index 6fe5d9b34361..e722b9fa33c5 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -11,6 +11,7 @@ use crate::{intrinsics, mem}; pub struct RangeIter(legacy::Range); impl RangeIter { + #[unstable(feature = "new_range_api", issue = "125687")] /// Returns the remainder of the range being iterated over. pub fn remainder(self) -> Range { Range { start: self.0.start, end: self.0.end } @@ -152,7 +153,7 @@ impl IntoIterator for Range { } /// By-value [`RangeInclusive`] iterator. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug, Clone)] pub struct RangeInclusiveIter(legacy::RangeInclusive); @@ -160,6 +161,7 @@ impl RangeInclusiveIter { /// Returns the remainder of the range being iterated over. /// /// If the iterator is exhausted or empty, returns `None`. + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub fn remainder(self) -> Option> { if self.0.is_empty() { return None; @@ -169,7 +171,7 @@ impl RangeInclusiveIter { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl Iterator for RangeInclusiveIter { type Item = A; @@ -225,7 +227,7 @@ impl Iterator for RangeInclusiveIter { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl DoubleEndedIterator for RangeInclusiveIter { #[inline] fn next_back(&mut self) -> Option { @@ -246,10 +248,10 @@ impl DoubleEndedIterator for RangeInclusiveIter { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RangeInclusiveIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for RangeInclusiveIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl IntoIterator for RangeInclusive { type Item = A; type IntoIter = RangeInclusiveIter; @@ -276,7 +278,7 @@ macro_rules! range_exact_iter_impl { macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl ExactSizeIterator for RangeInclusiveIter<$t> { } )*) } @@ -305,6 +307,7 @@ impl RangeFromIter { /// Returns the remainder of the range being iterated over. #[inline] #[rustc_inherit_overflow_checks] + #[unstable(feature = "new_range_api", issue = "125687")] pub fn remainder(self) -> RangeFrom { if intrinsics::overflow_checks() { if !self.first { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 52f3d43dfd6d..5f438d72ac13 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -690,7 +690,7 @@ impl Result { /// Converts from `Result` to [`Option`]. /// /// Converts `self` into an [`Option`], consuming `self`, - /// and discarding the error, if any. + /// and converting the error to `None`, if any. /// /// # Examples /// diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index d8ed521f4435..3a76c098bb53 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -127,7 +127,7 @@ mod private_slice_index { #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::Range {} - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl Sealed for range::RangeInclusive {} #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::RangeToInclusive {} @@ -663,7 +663,6 @@ unsafe impl const SliceIndex<[T]> for ops::RangeFull { } /// The methods `index` and `index_mut` panic if: -/// - the end of the range is `usize::MAX` or /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] @@ -673,12 +672,12 @@ unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { #[inline] fn get(self, slice: &[T]) -> Option<&[T]> { - if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } + if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) } } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { - if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) } } #[inline] @@ -724,7 +723,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex<[T]> for range::RangeInclusive { type Output = [T]; @@ -910,29 +909,7 @@ where R: [const] ops::RangeBounds + [const] Destruct, { let len = bounds.end; - - let end = match range.end_bound() { - ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len), - // Cannot overflow because `end < len` implies `end < usize::MAX`. - ops::Bound::Included(&end) => end + 1, - - ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len), - ops::Bound::Excluded(&end) => end, - ops::Bound::Unbounded => len, - }; - - let start = match range.start_bound() { - ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len), - // Cannot overflow because `start < end` implies `start < usize::MAX`. - ops::Bound::Excluded(&start) => start + 1, - - ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len), - ops::Bound::Included(&start) => start, - - ops::Bound::Unbounded => 0, - }; - - ops::Range { start, end } + into_slice_range(len, (range.start_bound().copied(), range.end_bound().copied())) } /// Performs bounds checking of a range without panicking. @@ -972,20 +949,7 @@ where R: ops::RangeBounds, { let len = bounds.end; - - let start = match range.start_bound() { - ops::Bound::Included(&start) => start, - ops::Bound::Excluded(start) => start.checked_add(1)?, - ops::Bound::Unbounded => 0, - }; - - let end = match range.end_bound() { - ops::Bound::Included(end) => end.checked_add(1)?, - ops::Bound::Excluded(&end) => end, - ops::Bound::Unbounded => len, - }; - - if start > end || end > len { None } else { Some(ops::Range { start, end }) } + try_into_slice_range(len, (range.start_bound().copied(), range.end_bound().copied())) } /// Converts a pair of `ops::Bound`s into `ops::Range` without performing any @@ -1011,32 +975,40 @@ pub(crate) const fn into_range_unchecked( /// Converts pair of `ops::Bound`s into `ops::Range`. /// Returns `None` on overflowing indices. #[rustc_const_unstable(feature = "const_range", issue = "none")] -pub(crate) const fn into_range( +#[inline] +pub(crate) const fn try_into_slice_range( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> Option> { - use ops::Bound; - let start = match start { - Bound::Included(start) => start, - Bound::Excluded(start) => start.checked_add(1)?, - Bound::Unbounded => 0, - }; - let end = match end { - Bound::Included(end) => end.checked_add(1)?, - Bound::Excluded(end) => end, - Bound::Unbounded => len, + ops::Bound::Included(end) if end >= len => return None, + // Cannot overflow because `end < len` implies `end < usize::MAX`. + ops::Bound::Included(end) => end + 1, + + ops::Bound::Excluded(end) if end > len => return None, + ops::Bound::Excluded(end) => end, + + ops::Bound::Unbounded => len, }; - // Don't bother with checking `start < end` and `end <= len` - // since these checks are handled by `Range` impls + let start = match start { + ops::Bound::Excluded(start) if start >= end => return None, + // Cannot overflow because `start < end` implies `start < usize::MAX`. + ops::Bound::Excluded(start) => start + 1, + + ops::Bound::Included(start) if start > end => return None, + ops::Bound::Included(start) => start, + + ops::Bound::Unbounded => 0, + }; Some(start..end) } /// Converts pair of `ops::Bound`s into `ops::Range`. /// Panics on overflowing indices. -pub(crate) fn into_slice_range( +#[inline] +pub(crate) const fn into_slice_range( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> ops::Range { @@ -1071,12 +1043,12 @@ unsafe impl SliceIndex<[T]> for (ops::Bound, ops::Bound) { #[inline] fn get(self, slice: &[T]) -> Option<&Self::Output> { - into_range(slice.len(), self)?.get(slice) + try_into_slice_range(slice.len(), self)?.get(slice) } #[inline] fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { - into_range(slice.len(), self)?.get_mut(slice) + try_into_slice_range(slice.len(), self)?.get_mut(slice) } #[inline] diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a289b0d6df40..ac096afb38af 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2175,7 +2175,7 @@ unsafe impl Sync for ChunksExactMut<'_, T> where T: Sync {} /// /// [`array_windows`]: slice::array_windows /// [slices]: slice -#[derive(Debug, Clone, Copy)] +#[derive(Debug)] #[stable(feature = "array_windows", since = "1.94.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { @@ -2189,6 +2189,14 @@ impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "array_windows", since = "1.94.0")] +impl Clone for ArrayWindows<'_, T, N> { + fn clone(&self) -> Self { + Self { v: self.v } + } +} + #[stable(feature = "array_windows", since = "1.94.0")] impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { type Item = &'a [T; N]; @@ -2224,6 +2232,14 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { fn last(self) -> Option { self.v.last_chunk() } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: since the caller guarantees that `idx` is in bounds, + // which means that `idx` cannot overflow an `isize`, and the + // "slice" created by `cast_array` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { &*self.v.as_ptr().add(idx).cast_array() } + } } #[stable(feature = "array_windows", since = "1.94.0")] @@ -2252,6 +2268,22 @@ impl ExactSizeIterator for ArrayWindows<'_, T, N> { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayWindows<'_, T, N> {} + +#[stable(feature = "array_windows", since = "1.94.0")] +impl FusedIterator for ArrayWindows<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for ArrayWindows<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for ArrayWindows<'_, T, N> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 139d2a4b4272..36dd4d6782ac 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3939,6 +3939,219 @@ impl [T] { } } + /// Moves the elements of this slice `N` places to the left, returning the ones + /// that "fall off" the front, and putting `inserted` at the end. + /// + /// Equivalently, you can think of concatenating `self` and `inserted` into one + /// long sequence, then returning the left-most `N` items and the rest into `self`: + /// + /// ```text + /// self (before) inserted + /// vvvvvvvvvvvvvvv vvv + /// [1, 2, 3, 4, 5] [9] + /// ↙ ↙ ↙ ↙ ↙ ↙ + /// [1] [2, 3, 4, 5, 9] + /// ^^^ ^^^^^^^^^^^^^^^ + /// returned self (after) + /// ``` + /// + /// See also [`Self::shift_right`] and compare [`Self::rotate_left`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_shift)] + /// + /// // Same as the diagram above + /// let mut a = [1, 2, 3, 4, 5]; + /// let inserted = [9]; + /// let returned = a.shift_left(inserted); + /// assert_eq!(returned, [1]); + /// assert_eq!(a, [2, 3, 4, 5, 9]); + /// + /// // You can shift multiple items at a time + /// let mut a = *b"Hello world"; + /// assert_eq!(a.shift_left(*b" peace"), *b"Hello "); + /// assert_eq!(a, *b"world peace"); + /// + /// // The name comes from this operation's similarity to bitshifts + /// let mut a: u8 = 0b10010110; + /// a <<= 3; + /// assert_eq!(a, 0b10110000_u8); + /// let mut a: [_; 8] = [1, 0, 0, 1, 0, 1, 1, 0]; + /// a.shift_left([0; 3]); + /// assert_eq!(a, [1, 0, 1, 1, 0, 0, 0, 0]); + /// + /// // Remember you can sub-slice to affect less that the whole slice. + /// // For example, this is similar to `.remove(1)` + `.insert(4, 'Z')` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// assert_eq!(a[1..=4].shift_left(['Z']), ['b']); + /// assert_eq!(a, ['a', 'c', 'd', 'e', 'Z', 'f']); + /// + /// // If the size matches it's equivalent to `mem::replace` + /// let mut a = [1, 2, 3]; + /// assert_eq!(a.shift_left([7, 8, 9]), [1, 2, 3]); + /// assert_eq!(a, [7, 8, 9]); + /// + /// // Some of the "inserted" elements end up returned if the slice is too short + /// let mut a = []; + /// assert_eq!(a.shift_left([1, 2, 3]), [1, 2, 3]); + /// let mut a = [9]; + /// assert_eq!(a.shift_left([1, 2, 3]), [9, 1, 2]); + /// assert_eq!(a, [3]); + /// ``` + #[unstable(feature = "slice_shift", issue = "151772")] + pub const fn shift_left(&mut self, inserted: [T; N]) -> [T; N] { + if let Some(shift) = self.len().checked_sub(N) { + // SAFETY: Having just checked that the inserted/returned arrays are + // shorter than (or the same length as) the slice: + // 1. The read for the items to return is in-bounds + // 2. We can `memmove` the slice over to cover the items we're returning + // to ensure those aren't double-dropped + // 3. Then we write (in-bounds for the same reason as the read) the + // inserted items atop the items of the slice that we just duplicated + // + // And none of this can panic, so there's no risk of intermediate unwinds. + unsafe { + let ptr = self.as_mut_ptr(); + let returned = ptr.cast_array::().read(); + ptr.copy_from(ptr.add(N), shift); + ptr.add(shift).cast_array::().write(inserted); + returned + } + } else { + // SAFETY: Having checked that the slice is strictly shorter than the + // inserted/returned arrays, it means we'll be copying the whole slice + // into the returned array, but that's not enough on its own. We also + // need to copy some of the inserted array into the returned array, + // with the rest going into the slice. Because `&mut` is exclusive + // and we own both `inserted` and `returned`, they're all disjoint + // allocations from each other as we can use `nonoverlapping` copies. + // + // We avoid double-frees by `ManuallyDrop`ing the inserted items, + // since we always copy them to other locations that will drop them + // instead. Plus nothing in here can panic -- it's just memcpy three + // times -- so there's no intermediate unwinds to worry about. + unsafe { + let len = self.len(); + let slice = self.as_mut_ptr(); + let inserted = mem::ManuallyDrop::new(inserted); + let inserted = (&raw const inserted).cast::(); + + let mut returned = MaybeUninit::<[T; N]>::uninit(); + let ptr = returned.as_mut_ptr().cast::(); + ptr.copy_from_nonoverlapping(slice, len); + ptr.add(len).copy_from_nonoverlapping(inserted, N - len); + slice.copy_from_nonoverlapping(inserted.add(N - len), len); + returned.assume_init() + } + } + } + + /// Moves the elements of this slice `N` places to the right, returning the ones + /// that "fall off" the back, and putting `inserted` at the beginning. + /// + /// Equivalently, you can think of concatenating `inserted` and `self` into one + /// long sequence, then returning the right-most `N` items and the rest into `self`: + /// + /// ```text + /// inserted self (before) + /// vvv vvvvvvvvvvvvvvv + /// [0] [5, 6, 7, 8, 9] + /// ↘ ↘ ↘ ↘ ↘ ↘ + /// [0, 5, 6, 7, 8] [9] + /// ^^^^^^^^^^^^^^^ ^^^ + /// self (after) returned + /// ``` + /// + /// See also [`Self::shift_left`] and compare [`Self::rotate_right`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_shift)] + /// + /// // Same as the diagram above + /// let mut a = [5, 6, 7, 8, 9]; + /// let inserted = [0]; + /// let returned = a.shift_right(inserted); + /// assert_eq!(returned, [9]); + /// assert_eq!(a, [0, 5, 6, 7, 8]); + /// + /// // The name comes from this operation's similarity to bitshifts + /// let mut a: u8 = 0b10010110; + /// a >>= 3; + /// assert_eq!(a, 0b00010010_u8); + /// let mut a: [_; 8] = [1, 0, 0, 1, 0, 1, 1, 0]; + /// a.shift_right([0; 3]); + /// assert_eq!(a, [0, 0, 0, 1, 0, 0, 1, 0]); + /// + /// // Remember you can sub-slice to affect less that the whole slice. + /// // For example, this is similar to `.remove(4)` + `.insert(1, 'Z')` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// assert_eq!(a[1..=4].shift_right(['Z']), ['e']); + /// assert_eq!(a, ['a', 'Z', 'b', 'c', 'd', 'f']); + /// + /// // If the size matches it's equivalent to `mem::replace` + /// let mut a = [1, 2, 3]; + /// assert_eq!(a.shift_right([7, 8, 9]), [1, 2, 3]); + /// assert_eq!(a, [7, 8, 9]); + /// + /// // Some of the "inserted" elements end up returned if the slice is too short + /// let mut a = []; + /// assert_eq!(a.shift_right([1, 2, 3]), [1, 2, 3]); + /// let mut a = [9]; + /// assert_eq!(a.shift_right([1, 2, 3]), [2, 3, 9]); + /// assert_eq!(a, [1]); + /// ``` + #[unstable(feature = "slice_shift", issue = "151772")] + pub const fn shift_right(&mut self, inserted: [T; N]) -> [T; N] { + if let Some(shift) = self.len().checked_sub(N) { + // SAFETY: Having just checked that the inserted/returned arrays are + // shorter than (or the same length as) the slice: + // 1. The read for the items to return is in-bounds + // 2. We can `memmove` the slice over to cover the items we're returning + // to ensure those aren't double-dropped + // 3. Then we write (in-bounds for the same reason as the read) the + // inserted items atop the items of the slice that we just duplicated + // + // And none of this can panic, so there's no risk of intermediate unwinds. + unsafe { + let ptr = self.as_mut_ptr(); + let returned = ptr.add(shift).cast_array::().read(); + ptr.add(N).copy_from(ptr, shift); + ptr.cast_array::().write(inserted); + returned + } + } else { + // SAFETY: Having checked that the slice is strictly shorter than the + // inserted/returned arrays, it means we'll be copying the whole slice + // into the returned array, but that's not enough on its own. We also + // need to copy some of the inserted array into the returned array, + // with the rest going into the slice. Because `&mut` is exclusive + // and we own both `inserted` and `returned`, they're all disjoint + // allocations from each other as we can use `nonoverlapping` copies. + // + // We avoid double-frees by `ManuallyDrop`ing the inserted items, + // since we always copy them to other locations that will drop them + // instead. Plus nothing in here can panic -- it's just memcpy three + // times -- so there's no intermediate unwinds to worry about. + unsafe { + let len = self.len(); + let slice = self.as_mut_ptr(); + let inserted = mem::ManuallyDrop::new(inserted); + let inserted = (&raw const inserted).cast::(); + + let mut returned = MaybeUninit::<[T; N]>::uninit(); + let ptr = returned.as_mut_ptr().cast::(); + ptr.add(N - len).copy_from_nonoverlapping(slice, len); + ptr.copy_from_nonoverlapping(inserted.add(len), N - len); + slice.copy_from_nonoverlapping(inserted, len); + returned.assume_init() + } + } + } + /// Fills `self` with elements by cloning `value`. /// /// # Examples @@ -4443,7 +4656,6 @@ impl [T] { where Simd: AsRef<[T; LANES]>, T: simd::SimdElement, - simd::LaneCount: simd::SupportedLaneCount, { // These are expected to always match, as vector types are laid out like // arrays per , but we @@ -4479,7 +4691,6 @@ impl [T] { where Simd: AsMut<[T; LANES]>, T: simd::SimdElement, - simd::LaneCount: simd::SupportedLaneCount, { // These are expected to always match, as vector types are laid out like // arrays per , but we diff --git a/library/core/src/slice/sort/stable/quicksort.rs b/library/core/src/slice/sort/stable/quicksort.rs index 734a495ce225..acc8a5e838e1 100644 --- a/library/core/src/slice/sort/stable/quicksort.rs +++ b/library/core/src/slice/sort/stable/quicksort.rs @@ -1,6 +1,6 @@ //! This module contains a stable quicksort and partition implementation. -use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::mem::MaybeUninit; use crate::slice::sort::shared::FreezeMarker; use crate::slice::sort::shared::pivot::choose_pivot; use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl; @@ -41,8 +41,11 @@ pub fn quicksort bool>( // SAFETY: We only access the temporary copy for Freeze types, otherwise // self-modifications via `is_less` would not be observed and this would // be unsound. Our temporary copy does not escape this scope. - let pivot_copy = unsafe { ManuallyDrop::new(ptr::read(&v[pivot_pos])) }; - let pivot_ref = (!has_direct_interior_mutability::()).then_some(&*pivot_copy); + // We use `MaybeUninit` to avoid re-tag issues. FIXME: use `MaybeDangling`. + let pivot_copy = unsafe { ptr::read((&raw const v[pivot_pos]).cast::>()) }; + let pivot_ref = + // SAFETY: We created the value in an init state. + (!has_direct_interior_mutability::()).then_some(unsafe { &*pivot_copy.as_ptr() }); // We choose a pivot, and check if this pivot is equal to our left // ancestor. If true, we do a partition putting equal elements on the diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ab7389a1300c..98354643aa40 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -85,34 +85,50 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH); let s_trunc = &s[..trunc_len]; let ellipsis = if trunc_len < s.len() { "[...]" } else { "" }; + let len = s.len(); - // 1. out of bounds - if begin > s.len() || end > s.len() { - let oob_index = if begin > s.len() { begin } else { end }; - panic!("byte index {oob_index} is out of bounds of `{s_trunc}`{ellipsis}"); + // 1. begin is OOB. + if begin > len { + panic!("start byte index {begin} is out of bounds of `{s_trunc}`{ellipsis}"); } - // 2. begin <= end - assert!( - begin <= end, - "begin <= end ({} <= {}) when slicing `{}`{}", - begin, - end, - s_trunc, - ellipsis - ); + // 2. end is OOB. + if end > len { + panic!("end byte index {end} is out of bounds of `{s_trunc}`{ellipsis}"); + } - // 3. character boundary - let index = if !s.is_char_boundary(begin) { begin } else { end }; - // find the character - let char_start = s.floor_char_boundary(index); - // `char_start` must be less than len and a char boundary - let ch = s[char_start..].chars().next().unwrap(); - let char_range = char_start..char_start + ch.len_utf8(); - panic!( - "byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}", - index, ch, char_range, s_trunc, ellipsis - ); + // 3. range is backwards. + if begin > end { + panic!("begin > end ({begin} > {end}) when slicing `{s_trunc}`{ellipsis}") + } + + // 4. begin is inside a character. + if !s.is_char_boundary(begin) { + let floor = s.floor_char_boundary(begin); + let ceil = s.ceil_char_boundary(begin); + let range = floor..ceil; + let ch = s[floor..ceil].chars().next().unwrap(); + panic!( + "start byte index {begin} is not a char boundary; it is inside {ch:?} (bytes {range:?}) of `{s_trunc}`{ellipsis}" + ) + } + + // 5. end is inside a character. + if !s.is_char_boundary(end) { + let floor = s.floor_char_boundary(end); + let ceil = s.ceil_char_boundary(end); + let range = floor..ceil; + let ch = s[floor..ceil].chars().next().unwrap(); + panic!( + "end byte index {end} is not a char boundary; it is inside {ch:?} (bytes {range:?}) of `{s_trunc}`{ellipsis}" + ) + } + + // 6. end is OOB and range is inclusive (end == len). + // This test cannot be combined with 2. above because for cases like + // `"abcαβγ"[4..9]` the error is that 4 is inside 'α', not that 9 is OOB. + debug_assert_eq!(end, len); + panic!("end byte index {end} is out of bounds of `{s_trunc}`{ellipsis}"); } impl str { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index a7cc943994c5..edf07c0c16f4 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -76,13 +76,6 @@ where } } -#[inline(never)] -#[cold] -#[track_caller] -const fn str_index_overflow_fail() -> ! { - panic!("attempted to index str up to maximum usize"); -} - /// Implements substring slicing with syntax `&self[..]` or `&mut self[..]`. /// /// Returns a slice of the whole string, i.e., returns `&self` or `&mut @@ -389,12 +382,12 @@ unsafe impl SliceIndex for (ops::Bound, ops::Bound) { #[inline] fn get(self, slice: &str) -> Option<&str> { - crate::slice::index::into_range(slice.len(), self)?.get(slice) + crate::slice::index::try_into_slice_range(slice.len(), self)?.get(slice) } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut str> { - crate::slice::index::into_range(slice.len(), self)?.get_mut(slice) + crate::slice::index::try_into_slice_range(slice.len(), self)?.get_mut(slice) } #[inline] @@ -640,11 +633,11 @@ unsafe impl const SliceIndex for ops::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } + if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) } } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { @@ -658,55 +651,69 @@ unsafe impl const SliceIndex for ops::RangeInclusive { } #[inline] fn index(self, slice: &str) -> &Self::Output { - if *self.end() == usize::MAX { - str_index_overflow_fail(); + let Self { mut start, mut end, exhausted } = self; + let len = slice.len(); + if end < len { + end = end + 1; + start = if exhausted { end } else { start }; + if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + // We also checked char boundaries, so this is valid UTF-8. + unsafe { return &*(start..end).get_unchecked(slice) } + } } - self.into_slice_range().index(slice) + + super::slice_error_fail(slice, start, end) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - if *self.end() == usize::MAX { - str_index_overflow_fail(); + let Self { mut start, mut end, exhausted } = self; + let len = slice.len(); + if end < len { + end = end + 1; + start = if exhausted { end } else { start }; + if start <= end && slice.is_char_boundary(start) && slice.is_char_boundary(end) { + // SAFETY: just checked that `start` and `end` are on a char boundary, + // and we are passing in a safe reference, so the return value will also be one. + // We also checked char boundaries, so this is valid UTF-8. + unsafe { return &mut *(start..end).get_unchecked_mut(slice) } + } } - self.into_slice_range().index_mut(slice) + + super::slice_error_fail(slice, start, end) } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex for range::RangeInclusive { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) } + ops::RangeInclusive::from(self).get(slice) } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } + ops::RangeInclusive::from(self).get_mut(slice) } #[inline] unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`. - unsafe { self.into_slice_range().get_unchecked(slice) } + unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) } } #[inline] unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. - unsafe { self.into_slice_range().get_unchecked_mut(slice) } + unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) } } #[inline] fn index(self, slice: &str) -> &Self::Output { - if self.last == usize::MAX { - str_index_overflow_fail(); - } - self.into_slice_range().index(slice) + ops::RangeInclusive::from(self).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - if self.last == usize::MAX { - str_index_overflow_fail(); - } - self.into_slice_range().index_mut(slice) + ops::RangeInclusive::from(self).index_mut(slice) } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 22f46ec385ce..adc2bbcde51b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1287,73 +1287,27 @@ impl AtomicBool { self.v.get().cast() } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function - /// returned `Some(_)`, else `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been - /// changed from other threads in the meantime, as long as the function - /// returns `Some(_)`, but the function will have been applied only once to - /// the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering for - /// when the operation finally succeeds while the second describes the - /// required ordering for loads. These correspond to the success and failure - /// orderings of [`AtomicBool::compare_exchange`] respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part of this - /// operation [`Relaxed`], and using [`Release`] makes the final successful - /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], - /// [`Acquire`] or [`Relaxed`]. - /// - /// **Note:** This method is only available on platforms that support atomic - /// operations on `u8`. - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]. - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// let x = AtomicBool::new(false); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true)); - /// assert_eq!(x.load(Ordering::SeqCst), false); - /// ``` + /// An alias for [`AtomicBool::try_update`]. #[inline] #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, - mut f: F, + f: F, ) -> Result where F: FnMut(bool) -> Option, { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev, - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional @@ -1395,7 +1349,6 @@ impl AtomicBool { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let x = AtomicBool::new(false); @@ -1405,7 +1358,7 @@ impl AtomicBool { /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -1413,11 +1366,16 @@ impl AtomicBool { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut(bool) -> Option, + mut f: impl FnMut(bool) -> Option, ) -> Result { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -1454,7 +1412,6 @@ impl AtomicBool { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// /// use std::sync::atomic::{AtomicBool, Ordering}; /// @@ -1464,7 +1421,7 @@ impl AtomicBool { /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -2000,83 +1957,27 @@ impl AtomicPtr { unsafe { atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) } } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function - /// returned `Some(_)`, else `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been - /// changed from other threads in the meantime, as long as the function - /// returns `Some(_)`, but the function will have been applied only once to - /// the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering for - /// when the operation finally succeeds while the second describes the - /// required ordering for loads. These correspond to the success and failure - /// orderings of [`AtomicPtr::compare_exchange`] respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part of this - /// operation [`Relaxed`], and using [`Release`] makes the final successful - /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], - /// [`Acquire`] or [`Relaxed`]. - /// - /// **Note:** This method is only available on platforms that support atomic - /// operations on pointers. - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem], - /// which is a particularly common pitfall for pointers! - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - /// use std::sync::atomic::{AtomicPtr, Ordering}; - /// - /// let ptr: *mut _ = &mut 5; - /// let some_ptr = AtomicPtr::new(ptr); - /// - /// let new: *mut _ = &mut 10; - /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr)); - /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { - /// if x == ptr { - /// Some(new) - /// } else { - /// None - /// } - /// }); - /// assert_eq!(result, Ok(ptr)); - /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); - /// ``` + /// An alias for [`AtomicPtr::try_update`]. #[inline] #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, - mut f: F, + f: F, ) -> Result<*mut T, *mut T> where F: FnMut(*mut T) -> Option<*mut T>, { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev, - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function @@ -2118,7 +2019,6 @@ impl AtomicPtr { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// /// let ptr: *mut _ = &mut 5; @@ -2137,7 +2037,7 @@ impl AtomicPtr { /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -2145,11 +2045,16 @@ impl AtomicPtr { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut(*mut T) -> Option<*mut T>, + mut f: impl FnMut(*mut T) -> Option<*mut T>, ) -> Result<*mut T, *mut T> { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -2188,7 +2093,6 @@ impl AtomicPtr { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// /// use std::sync::atomic::{AtomicPtr, Ordering}; /// @@ -2201,7 +2105,7 @@ impl AtomicPtr { /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -3399,69 +3303,25 @@ macro_rules! atomic_int { unsafe { atomic_xor(self.v.get(), val, order) } } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else - /// `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been changed from other threads in - /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied - /// only once to the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. - /// The first describes the required ordering for when the operation finally succeeds while the second - /// describes the required ordering for loads. These correspond to the success and failure orderings of - #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")] - /// respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part - /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load - /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. - /// - /// **Note**: This method is only available on platforms that support atomic operations on - #[doc = concat!("[`", $s_int_type, "`].")] - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem] - /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value* - /// of the atomic is not in and of itself sufficient to ensure any required preconditions. - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] - /// - #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); - /// assert_eq!(x.load(Ordering::SeqCst), 9); - /// ``` + /// An alias for + #[doc = concat!("[`", stringify!($atomic_type), "::try_update`]")] + /// . #[inline] #[stable(feature = "no_more_cas", since = "1.45.0")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update(&self, set_order: Ordering, fetch_order: Ordering, - mut f: F) -> Result<$int_type, $int_type> + f: F) -> Result<$int_type, $int_type> where F: FnMut($int_type) -> Option<$int_type> { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional @@ -3503,7 +3363,6 @@ macro_rules! atomic_int { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] @@ -3513,7 +3372,7 @@ macro_rules! atomic_int { /// assert_eq!(x.load(Ordering::SeqCst), 9); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -3521,11 +3380,16 @@ macro_rules! atomic_int { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut($int_type) -> Option<$int_type>, + mut f: impl FnMut($int_type) -> Option<$int_type>, ) -> Result<$int_type, $int_type> { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -3566,7 +3430,6 @@ macro_rules! atomic_int { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] @@ -3575,7 +3438,7 @@ macro_rules! atomic_int { /// assert_eq!(x.load(Ordering::SeqCst), 9); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b4efc09684e7..a5b654033ba1 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -690,7 +690,6 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_constants)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1)); @@ -801,7 +800,6 @@ impl Duration { /// # Examples /// /// ``` - /// #![feature(duration_constants)] /// use std::time::Duration; /// /// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2)); diff --git a/library/coretests/tests/iter/mod.rs b/library/coretests/tests/iter/mod.rs index 5b2769d04698..f300f421f7c1 100644 --- a/library/coretests/tests/iter/mod.rs +++ b/library/coretests/tests/iter/mod.rs @@ -99,3 +99,18 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +pub fn test_const_iter() { + const X: bool = { + let it = Some(42); + let mut run = false; + #[expect(for_loops_over_fallibles)] + for x in it { + assert!(x == 42); + run = true; + } + run + }; + assert_eq!(true, X); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 8cca714b7393..b8702ee20cbb 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -8,13 +8,11 @@ #![feature(ascii_char_variants)] #![feature(async_iter_from_iter)] #![feature(async_iterator)] -#![feature(bigint_helper_methods)] #![feature(bool_to_result)] #![feature(bstr)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_internals)] #![feature(char_max_len)] -#![feature(clamp_magnitude)] #![feature(clone_to_uninit)] #![feature(const_array)] #![feature(const_bool)] @@ -27,14 +25,15 @@ #![feature(const_drop_in_place)] #![feature(const_eval_select)] #![feature(const_index)] +#![feature(const_iter)] #![feature(const_ops)] #![feature(const_option_ops)] #![feature(const_ref_cell)] #![feature(const_result_trait_fn)] #![feature(const_select_unpredictable)] #![feature(const_trait_impl)] +#![feature(const_unsigned_bigint_helpers)] #![feature(control_flow_ok)] -#![feature(core_float_math)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] #![feature(core_io_borrowed_buf)] @@ -46,7 +45,6 @@ #![feature(drop_guard)] #![feature(duration_constants)] #![feature(duration_constructors)] -#![feature(error_generic_member_access)] #![feature(exact_div)] #![feature(exact_size_is_empty)] #![feature(extend_one)] @@ -54,7 +52,6 @@ #![feature(f16)] #![feature(f128)] #![feature(float_algebraic)] -#![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(flt2dec)] #![feature(fmt_internals)] @@ -65,6 +62,7 @@ #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] +#![feature(int_from_ascii)] #![feature(int_lowest_highest_one)] #![feature(int_roundings)] #![feature(ip)] @@ -89,18 +87,20 @@ #![feature(new_range_api)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] +#![feature(nonzero_from_str_radix)] #![feature(numfmt)] #![feature(one_sided_range)] -#![feature(option_reduce)] #![feature(pattern)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(result_option_map_or_default)] +#![feature(signed_bigint_helpers)] #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] +#![feature(slice_shift)] #![feature(slice_split_once)] #![feature(sliceindex_wrappers)] #![feature(split_array)] @@ -109,7 +109,6 @@ #![feature(step_trait)] #![feature(str_internals)] #![feature(strict_provenance_lints)] -#![feature(test)] #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_blocks)] @@ -117,9 +116,11 @@ #![feature(try_trait_v2)] #![feature(type_info)] #![feature(uint_bit_width)] +#![feature(uint_carryless_mul)] #![feature(uint_gather_scatter_bits)] #![feature(unsize)] #![feature(unwrap_infallible)] +#![feature(widening_mul)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 87f2d5dd8289..2483b4c2aacd 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -1,5 +1,8 @@ +#![allow(dead_code)] + use std::any::{Any, TypeId}; -use std::mem::type_info::{Type, TypeKind}; +use std::mem::offset_of; +use std::mem::type_info::{Const, Generic, GenericType, Type, TypeKind}; #[test] fn test_arrays() { @@ -66,6 +69,155 @@ fn test_tuples() { } } +#[test] +fn test_structs() { + use TypeKind::*; + + const { + struct TestStruct { + first: u8, + second: u16, + reference: &'static u16, + } + + let Type { kind: Struct(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(!ty.non_exhaustive); + assert!(ty.fields.len() == 3); + assert!(ty.fields[0].name == "first"); + assert!(ty.fields[0].ty == TypeId::of::()); + assert!(ty.fields[0].offset == offset_of!(TestStruct, first)); + assert!(ty.fields[1].name == "second"); + assert!(ty.fields[1].ty == TypeId::of::()); + assert!(ty.fields[1].offset == offset_of!(TestStruct, second)); + assert!(ty.fields[2].name == "reference"); + assert!(ty.fields[2].ty == TypeId::of::<&'static u16>()); + assert!(ty.fields[2].offset == offset_of!(TestStruct, reference)); + } + + const { + #[non_exhaustive] + struct NonExhaustive { + a: u8, + } + + let Type { kind: Struct(ty), .. } = Type::of::() else { panic!() }; + assert!(ty.non_exhaustive); + } + + const { + struct TupleStruct(u8, u16); + + let Type { kind: Struct(ty), .. } = Type::of::() else { panic!() }; + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].name == "0"); + assert!(ty.fields[0].ty == TypeId::of::()); + assert!(ty.fields[1].name == "1"); + assert!(ty.fields[1].ty == TypeId::of::()); + } + + const { + struct Generics<'a, T, const C: u64> { + a: &'a T, + } + + let Type { kind: Struct(ty), .. } = Type::of::>() else { + panic!() + }; + assert!(ty.fields.len() == 1); + assert!(ty.generics.len() == 3); + + let Generic::Lifetime(_) = ty.generics[0] else { panic!() }; + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() }; + assert!(const_ty == TypeId::of::()); + } +} + +#[test] +fn test_unions() { + use TypeKind::*; + + const { + union TestUnion { + first: i16, + second: u16, + } + + let Type { kind: Union(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].name == "first"); + assert!(ty.fields[0].offset == offset_of!(TestUnion, first)); + assert!(ty.fields[1].name == "second"); + assert!(ty.fields[1].offset == offset_of!(TestUnion, second)); + } + + const { + union Generics<'a, T: Copy, const C: u64> { + a: T, + z: &'a (), + } + + let Type { kind: Union(ty), .. } = Type::of::>() else { + panic!() + }; + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].offset == offset_of!(Generics<'static, i32, 1_u64>, a)); + assert!(ty.fields[1].offset == offset_of!(Generics<'static, i32, 1_u64>, z)); + + assert!(ty.generics.len() == 3); + let Generic::Lifetime(_) = ty.generics[0] else { panic!() }; + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() }; + assert!(const_ty == TypeId::of::()); + } +} + +#[test] +fn test_enums() { + use TypeKind::*; + + const { + enum E { + Some(u32), + None, + #[non_exhaustive] + Foomp { + a: (), + b: &'static str, + }, + } + + let Type { kind: Enum(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(ty.variants.len() == 3); + + assert!(ty.variants[0].name == "Some"); + assert!(!ty.variants[0].non_exhaustive); + assert!(ty.variants[0].fields.len() == 1); + + assert!(ty.variants[1].name == "None"); + assert!(!ty.variants[1].non_exhaustive); + assert!(ty.variants[1].fields.len() == 0); + + assert!(ty.variants[2].name == "Foomp"); + assert!(ty.variants[2].non_exhaustive); + assert!(ty.variants[2].fields.len() == 2); + } + + const { + let Type { kind: Enum(ty), size, .. } = Type::of::>() else { panic!() }; + assert!(size == Some(size_of::>())); + assert!(ty.variants.len() == 2); + assert!(ty.generics.len() == 1); + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[0] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + } +} + #[test] fn test_primitives() { use TypeKind::*; diff --git a/library/coretests/tests/nonzero.rs b/library/coretests/tests/nonzero.rs index c368a2621740..861e9e05081f 100644 --- a/library/coretests/tests/nonzero.rs +++ b/library/coretests/tests/nonzero.rs @@ -124,6 +124,97 @@ fn test_from_signed_nonzero() { assert_eq!(num, 1i32); } +#[test] +fn test_from_ascii_radix() { + assert_eq!(NonZero::::from_ascii_radix(b"123", 10), Ok(NonZero::new(123).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"1001", 2), Ok(NonZero::new(9).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"123", 8), Ok(NonZero::new(83).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"123", 16), Ok(NonZero::new(291).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"ffff", 16), Ok(NonZero::new(65535).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"z", 36), Ok(NonZero::new(35).unwrap())); + assert_eq!( + NonZero::::from_ascii_radix(b"0", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"-1", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"-129", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::NegOverflow) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"257", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::PosOverflow) + ); + + assert_eq!( + NonZero::::from_ascii_radix(b"Z", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"_", 2).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); +} + +#[test] +fn test_from_ascii() { + assert_eq!(NonZero::::from_ascii(b"123"), Ok(NonZero::new(123).unwrap())); + assert_eq!( + NonZero::::from_ascii(b"0").err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) + ); + assert_eq!( + NonZero::::from_ascii(b"-1").err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii(b"-129").err().map(|e| e.kind().clone()), + Some(IntErrorKind::NegOverflow) + ); + assert_eq!( + NonZero::::from_ascii(b"257").err().map(|e| e.kind().clone()), + Some(IntErrorKind::PosOverflow) + ); +} + +#[test] +fn test_from_str_radix() { + assert_eq!(NonZero::::from_str_radix("123", 10), Ok(NonZero::new(123).unwrap())); + assert_eq!(NonZero::::from_str_radix("1001", 2), Ok(NonZero::new(9).unwrap())); + assert_eq!(NonZero::::from_str_radix("123", 8), Ok(NonZero::new(83).unwrap())); + assert_eq!(NonZero::::from_str_radix("123", 16), Ok(NonZero::new(291).unwrap())); + assert_eq!(NonZero::::from_str_radix("ffff", 16), Ok(NonZero::new(65535).unwrap())); + assert_eq!(NonZero::::from_str_radix("z", 36), Ok(NonZero::new(35).unwrap())); + assert_eq!( + NonZero::::from_str_radix("0", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) + ); + assert_eq!( + NonZero::::from_str_radix("-1", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_str_radix("-129", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::NegOverflow) + ); + assert_eq!( + NonZero::::from_str_radix("257", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::PosOverflow) + ); + + assert_eq!( + NonZero::::from_str_radix("Z", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_str_radix("_", 2).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); +} + #[test] fn test_from_str() { assert_eq!("123".parse::>(), Ok(NonZero::new(123).unwrap())); diff --git a/library/coretests/tests/num/carryless_mul.rs b/library/coretests/tests/num/carryless_mul.rs new file mode 100644 index 000000000000..5d4690beaede --- /dev/null +++ b/library/coretests/tests/num/carryless_mul.rs @@ -0,0 +1,254 @@ +//! Tests the `Unsigned::{carryless_mul, widening_carryless_mul, carrying_carryless_mul}` methods. + +#[test] +fn carryless_mul_u128() { + assert_eq_const_safe!(u128: ::carryless_mul(0, 0), 0); + assert_eq_const_safe!(u128: ::carryless_mul(1, 1), 1); + + assert_eq_const_safe!( + u128: ::carryless_mul( + 0x0123456789ABCDEF_FEDCBA9876543210, + 1u128 << 64, + ), + 0xFEDCBA9876543210_0000000000000000 + ); + + assert_eq_const_safe!( + u128: ::carryless_mul( + 0x0123456789ABCDEF_FEDCBA9876543210, + (1u128 << 64) | 1, + ), + 0xFFFFFFFFFFFFFFFF_FEDCBA9876543210 + ); + + assert_eq_const_safe!( + u128: ::carryless_mul( + 0x0123456789ABCDEF_FEDCBA9876543211, + 1u128 << 127, + ), + 0x8000000000000000_0000000000000000 + ); + + assert_eq_const_safe!( + u128: ::carryless_mul( + 0xAAAAAAAAAAAAAAAA_AAAAAAAAAAAAAAAA, + 0x5555555555555555_5555555555555555, + ), + 0x2222222222222222_2222222222222222 + ); + + assert_eq_const_safe!( + u128: ::carryless_mul( + (1 << 127) | (1 << 64) | 1, + (1 << 63) | 1 + ), + (1 << 64) | (1 << 63) | 1 + ); + + assert_eq_const_safe!( + u128: ::carryless_mul( + 0x8000000000000000_0000000000000001, + 0x7FFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF, + ), + 0xFFFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF + ); +} + +#[test] +fn carryless_mul_u64() { + assert_eq_const_safe!(u64: ::carryless_mul(0, 0), 0); + assert_eq_const_safe!(u64: ::carryless_mul(1, 1), 1); + + assert_eq_const_safe!( + u64: ::carryless_mul( + 0x0123_4567_89AB_CDEF, + 1u64 << 32, + ), + 0x89AB_CDEF_0000_0000 + ); + + assert_eq_const_safe!( + u64: ::carryless_mul( + 0x0123_4567_89AB_CDEF, + (1u64 << 32) | 1, + ), + 0x8888_8888_89AB_CDEF + ); + + assert_eq_const_safe!( + u64: ::carryless_mul( + 0x0123_4567_89AB_CDEF, + 1u64 << 63, + ), + 0x8000_0000_0000_0000 + ); + + assert_eq_const_safe!( + u64: ::carryless_mul( + 0xAAAA_AAAA_AAAA_AAAA, + 0x5555_5555_5555_5555, + ), + 0x2222_2222_2222_2222 + ); + + assert_eq_const_safe!( + u64: ::carryless_mul( + (1u64 << 63) | (1u64 << 32) | 1, + (1u64 << 31) | 1, + ), + (1u64 << 32) | (1u64 << 31) | 1 + ); + + assert_eq_const_safe!( + u64: ::carryless_mul( + 0x8000_0000_0000_0001, + 0x7FFF_FFFF_FFFF_FFFF, + ), + 0xFFFF_FFFF_FFFF_FFFF + ); +} + +#[test] +fn carryless_mul_u32() { + assert_eq_const_safe!( + u32: ::carryless_mul(0x0123_4567, 1u32 << 16), + 0x4567_0000 + ); + + assert_eq_const_safe!( + u32: ::carryless_mul(0xAAAA_AAAA, 0x5555_5555), + 0x2222_2222 + ); +} + +#[test] +fn carryless_mul_u16() { + assert_eq_const_safe!( + u16: ::carryless_mul(0x0123, 1u16 << 8), + 0x2300 + ); + + assert_eq_const_safe!( + u16: ::carryless_mul(0xAAAA, 0x5555), + 0x2222 + ); +} + +#[test] +fn carryless_mul_u8() { + assert_eq_const_safe!( + u8: ::carryless_mul(0x01, 1u8 << 4), + 0x10 + ); + + assert_eq_const_safe!( + u8: ::carryless_mul(0xAA, 0x55), + 0x22 + ); +} + +#[test] +fn widening_carryless_mul() { + assert_eq_const_safe!( + u16: ::widening_carryless_mul(0xEFu8, 1u8 << 7), + 0x7780u16 + ); + assert_eq_const_safe!( + u16: ::widening_carryless_mul(0xEFu8, (1u8 << 7) | 1), + 0x776Fu16 + ); + + assert_eq_const_safe!( + u32: ::widening_carryless_mul(0xBEEFu16, 1u16 << 15), + 0x5F77_8000u32 + ); + assert_eq_const_safe!( + u32: ::widening_carryless_mul(0xBEEFu16, (1u16 << 15) | 1), + 0x5F77_3EEFu32 + ); + + assert_eq_const_safe!( + u64: ::widening_carryless_mul(0xDEAD_BEEFu32, 1u32 << 31), + 0x6F56_DF77_8000_0000u64 + ); + assert_eq_const_safe!( + u64: ::widening_carryless_mul(0xDEAD_BEEFu32, (1u32 << 31) | 1), + 0x6F56_DF77_5EAD_BEEFu64 + ); + + assert_eq_const_safe!( + u128: ::widening_carryless_mul(0xDEAD_BEEF_FACE_FEEDu64, 1u64 << 63), + 147995377545877439359040026616086396928 + + ); + assert_eq_const_safe!( + u128: ::widening_carryless_mul(0xDEAD_BEEF_FACE_FEEDu64, (1u64 << 63) | 1), + 147995377545877439356638973527682121453 + ); +} + +#[test] +fn carrying_carryless_mul() { + assert_eq_const_safe!( + (u8, u8): ::carrying_carryless_mul(0xEFu8, 1u8 << 7, 0), + (0x80u8, 0x77u8) + ); + assert_eq_const_safe!( + (u8, u8): ::carrying_carryless_mul(0xEFu8, (1u8 << 7) | 1, 0xEF), + (0x80u8, 0x77u8) + ); + + assert_eq_const_safe!( + (u16, u16): ::carrying_carryless_mul(0xBEEFu16, 1u16 << 15, 0), + (0x8000u16, 0x5F77u16) + ); + assert_eq_const_safe!( + (u16, u16): ::carrying_carryless_mul(0xBEEFu16, (1u16 << 15) | 1, 0xBEEF), + (0x8000u16, 0x5F77u16) + ); + + assert_eq_const_safe!( + (u32, u32): ::carrying_carryless_mul(0xDEAD_BEEFu32, 1u32 << 31, 0), + (0x8000_0000u32, 0x6F56_DF77u32) + ); + assert_eq_const_safe!( + (u32, u32): ::carrying_carryless_mul(0xDEAD_BEEFu32, (1u32 << 31) | 1, 0xDEAD_BEEF), + (0x8000_0000u32, 0x6F56_DF77u32) + ); + + assert_eq_const_safe!( + (u64, u64): ::carrying_carryless_mul(0xDEAD_BEEF_FACE_FEEDu64, 1u64 << 63, 0), + (9223372036854775808, 8022845492652638070) + ); + assert_eq_const_safe!( + (u64, u64): ::carrying_carryless_mul( + 0xDEAD_BEEF_FACE_FEEDu64, + (1u64 << 63) | 1, + 0xDEAD_BEEF_FACE_FEED, + ), + (9223372036854775808, 8022845492652638070) + ); + + assert_eq_const_safe!( + (u128, u128): ::carrying_carryless_mul( + 0xDEAD_BEEF_FACE_FEED_0123_4567_89AB_CDEFu128, + 1u128 << 127, + 0, + ), + ( + 0x8000_0000_0000_0000_0000_0000_0000_0000u128, + 147995377545877439359081019380694640375, + ) + ); + assert_eq_const_safe!( + (u128, u128): ::carrying_carryless_mul( + 0xDEAD_BEEF_FACE_FEED_0123_4567_89AB_CDEFu128, + (1u128 << 127) | 1, + 0xDEAD_BEEF_FACE_FEED_0123_4567_89AB_CDEF, + ), + ( + 0x8000_0000_0000_0000_0000_0000_0000_0000u128, + 147995377545877439359081019380694640375, + ) + ); +} diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index 913f766ec168..73b0e2333fee 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -22,6 +22,7 @@ mod u64; mod u8; mod bignum; +mod carryless_mul; mod const_from; mod dec2flt; mod float_iter_sum_identity; diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index 7c4fb22599c0..240c66fd5c71 100644 --- a/library/coretests/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs @@ -117,6 +117,13 @@ macro_rules! uint_module { assert_eq_const_safe!($T: <$T>::funnel_shr(_1, _1, 4), <$T>::rotate_right(_1, 4)); } + fn test_carryless_mul() { + assert_eq_const_safe!($T: <$T>::carryless_mul(0, 0), 0); + assert_eq_const_safe!($T: <$T>::carryless_mul(1, 1), 1); + + assert_eq_const_safe!($T: <$T>::carryless_mul(0b0100, 2), 0b1000); + } + fn test_swap_bytes() { assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A); assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B); diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index 6f60f71e8a47..2bb62f36bb0e 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -2507,3 +2507,41 @@ fn test_slice_from_raw_parts_in_const() { assert_eq!(EMPTY_SLICE.as_ptr().addr(), 123456); assert_eq!(EMPTY_SLICE.len(), 0); } + +#[test] +fn test_shift_left() { + #[track_caller] + fn case( + mut a: [i32; M], + i: [i32; N], + j: [i32; N], + b: [i32; M], + ) { + assert_eq!((a.shift_left(i), a), (j, b)); + } + case([], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], []); + case([1], [2, 3, 4, 5], [1, 2, 3, 4], [5]); + case([1, 2], [3, 4, 5], [1, 2, 3], [4, 5]); + case([1, 2, 3], [4, 5], [1, 2], [3, 4, 5]); + case([1, 2, 3, 4], [5], [1], [2, 3, 4, 5]); + case([1, 2, 3, 4, 5], [], [], [1, 2, 3, 4, 5]); +} + +#[test] +fn test_shift_right() { + #[track_caller] + fn case( + i: [i32; N], + mut a: [i32; M], + b: [i32; M], + j: [i32; N], + ) { + assert_eq!((a.shift_right(i), a), (j, b)); + } + case([], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], []); + case([1], [2, 3, 4, 5], [1, 2, 3, 4], [5]); + case([1, 2], [3, 4, 5], [1, 2, 3], [4, 5]); + case([1, 2, 3], [4, 5], [1, 2], [3, 4, 5]); + case([1, 2, 3, 4], [5], [1], [2, 3, 4, 5]); + case([1, 2, 3, 4, 5], [], [], [1, 2, 3, 4, 5]); +} diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 1be19913f260..83f2a3b2c53f 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -17,7 +17,6 @@ #![feature(cfg_emscripten_wasm_eh)] #![feature(cfg_select)] #![feature(core_intrinsics)] -#![feature(lang_items)] #![feature(panic_unwind)] #![feature(staged_api)] #![feature(std_internals)] @@ -25,6 +24,7 @@ #![panic_runtime] #![feature(panic_runtime)] #![allow(internal_features)] +#![allow(unused_features)] #![warn(unreachable_pub)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/portable-simd/.github/workflows/ci.yml b/library/portable-simd/.github/workflows/ci.yml index 3984d8f0d8d9..de7efa355283 100644 --- a/library/portable-simd/.github/workflows/ci.yml +++ b/library/portable-simd/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu] + target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, x86_64-unknown-linux-gnu] # `default` means we use the default target config for the target, # `native` means we run with `-Ctarget-cpu=native`, and anything else is # an arg to `-Ctarget-feature` @@ -68,18 +68,12 @@ jobs: exclude: # -Ctarget-cpu=native sounds like bad-news if target != host - { target: i686-pc-windows-msvc, target_feature: native } - - { target: i586-pc-windows-msvc, target_feature: native } include: # Populate the `matrix.os` field - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: i686-pc-windows-msvc, os: windows-latest } - - { target: i586-pc-windows-msvc, os: windows-latest } - - # These are globally available on all the other targets. - - { target: i586-pc-windows-msvc, target_feature: +sse, os: windows-latest } - - { target: i586-pc-windows-msvc, target_feature: +sse2, os: windows-latest } # Annoyingly, the x86_64-unknown-linux-gnu runner *almost* always has # avx512vl, but occasionally doesn't. Maybe one day we can enable it. @@ -129,7 +123,7 @@ jobs: run: cargo doc --verbose --target=${{ matrix.target }} env: RUSTDOCFLAGS: -Dwarnings - + macos-tests: name: ${{ matrix.target }} runs-on: macos-latest @@ -246,9 +240,18 @@ jobs: miri: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] env: PROPTEST_CASES: 16 steps: - uses: actions/checkout@v4 - - name: Test (Miri) - run: cargo miri test + + - name: Install cargo-nextest + uses: taiki-e/install-action@nextest + + - name: Test (Miri) (partition ${{ matrix.shard }}/4) + run: | + cargo miri nextest run --partition count:${{ matrix.shard }}/4 diff --git a/library/portable-simd/Cargo.lock b/library/portable-simd/Cargo.lock index 1584c704fb22..5a5f0d8907ae 100644 --- a/library/portable-simd/Cargo.lock +++ b/library/portable-simd/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" @@ -16,31 +16,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "core_simd" @@ -54,46 +53,69 @@ dependencies = [ ] [[package]] -name = "js-sys" -version = "0.3.64" +name = "float-cmp" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ + "num-traits", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "log" -version = "0.4.20" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -114,9 +136,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -167,10 +189,25 @@ dependencies = [ ] [[package]] -name = "scoped-tls" -version = "1.0.1" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "std_float" @@ -184,9 +221,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -197,34 +234,46 @@ dependencies = [ name = "test_helpers" version = "0.1.0" dependencies = [ + "float-cmp", "proptest", ] [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -233,21 +282,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -255,9 +305,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -268,19 +318,21 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-bindgen-test" -version = "0.3.37" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" dependencies = [ - "console_error_panic_hook", "js-sys", - "scoped-tls", + "minicov", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", @@ -288,20 +340,123 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.37" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" dependencies = [ "proc-macro2", "quote", + "syn", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/library/portable-simd/beginners-guide.md b/library/portable-simd/beginners-guide.md index dc08d847ced5..4250a18315a6 100644 --- a/library/portable-simd/beginners-guide.md +++ b/library/portable-simd/beginners-guide.md @@ -25,7 +25,7 @@ SIMD has a few special vocabulary terms you should know: * **Scalar:** "Scalar" in mathematical contexts refers to values that can be represented as a single element, mostly numbers like 6, 3.14, or -2. It can also be used to describe "scalar operations" that use strictly scalar values, like addition. This term is mostly used to differentiate between vectorized operations that use SIMD instructions and scalar operations that don't. -* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops. +* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general it is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops. * **Bit Widths:** When talking about SIMD, the bit widths used are the bit size of the vectors involved, *not* the individual elements. So "128-bit SIMD" has 128-bit vectors, and that might be `f32x4`, `i32x4`, `i16x8`, or other variations. While 128-bit SIMD is the most common, there's also 64-bit, 256-bit, and even 512-bit on the newest CPUs. diff --git a/library/portable-simd/crates/core_simd/examples/dot_product.rs b/library/portable-simd/crates/core_simd/examples/dot_product.rs index 75d152ae7f0e..4ef32bfa60b5 100644 --- a/library/portable-simd/crates/core_simd/examples/dot_product.rs +++ b/library/portable-simd/crates/core_simd/examples/dot_product.rs @@ -1,8 +1,6 @@ //! Code taken from the `packed_simd` crate. //! Run this code with `cargo test --example dot_product`. -#![feature(array_chunks)] -#![feature(slice_as_chunks)] // Add these imports to use the stdsimd library #![feature(portable_simd)] use core_simd::simd::prelude::*; @@ -33,7 +31,7 @@ pub fn dot_prod_scalar_1(a: &[f32], b: &[f32]) -> f32 { } // We now move on to the SIMD implementations: notice the following constructs: -// `array_chunks::<4>`: mapping this over the vector will let use construct SIMD vectors +// `as_chunks::<4>`: mapping this over the vector will let us construct SIMD vectors // `f32x4::from_array`: construct the SIMD vector from a slice // `(a * b).reduce_sum()`: Multiply both f32x4 vectors together, and then reduce them. // This approach essentially uses SIMD to produce a vector of length N/4 of all the products, @@ -42,9 +40,11 @@ pub fn dot_prod_scalar_1(a: &[f32], b: &[f32]) -> f32 { pub fn dot_prod_simd_0(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .map(|(a, b)| (a * b).reduce_sum()) .sum() } @@ -60,9 +60,11 @@ pub fn dot_prod_simd_0(a: &[f32], b: &[f32]) -> f32 { pub fn dot_prod_simd_1(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .fold(f32x4::splat(0.0), |acc, zipped| acc + zipped.0 * zipped.1) .reduce_sum() } @@ -74,9 +76,11 @@ pub fn dot_prod_simd_2(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 let mut res = f32x4::splat(0.0); - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .for_each(|(a, b)| { res = a.mul_add(b, res); }); @@ -113,9 +117,11 @@ pub fn dot_prod_simd_3(a: &[f32], b: &[f32]) -> f32 { // next example. pub fn dot_prod_simd_4(a: &[f32], b: &[f32]) -> f32 { let mut sum = a - .array_chunks::<4>() + .as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .map(|(a, b)| a * b) .fold(f32x4::splat(0.0), std::ops::Add::add) .reduce_sum(); @@ -131,9 +137,11 @@ pub fn dot_prod_simd_4(a: &[f32], b: &[f32]) -> f32 { // This version allocates a single `XMM` register for accumulation, and the folds don't allocate on top of that. // Notice the use of `mul_add`, which can do a multiply and an add operation ber iteration. pub fn dot_prod_simd_5(a: &[f32], b: &[f32]) -> f32 { - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .fold(f32x4::splat(0.), |acc, (a, b)| a.mul_add(b, acc)) .reduce_sum() } diff --git a/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs index bad86414401d..ad2eea9153e0 100644 --- a/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs +++ b/library/portable-simd/crates/core_simd/examples/matrix_inversion.rs @@ -1,7 +1,7 @@ //! 4x4 matrix inverse // Code ported from the `packed_simd` crate // Run this code with `cargo test --example matrix_inversion` -#![feature(array_chunks, portable_simd)] +#![feature(portable_simd)] use core_simd::simd::prelude::*; // Gotta define our own 4x4 matrix since Rust doesn't ship multidim arrays yet :^) diff --git a/library/portable-simd/crates/core_simd/src/fmt.rs b/library/portable-simd/crates/core_simd/src/fmt.rs index 3a540f5a0490..90c520e75bb3 100644 --- a/library/portable-simd/crates/core_simd/src/fmt.rs +++ b/library/portable-simd/crates/core_simd/src/fmt.rs @@ -1,9 +1,8 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Simd, SimdElement}; use core::fmt; impl fmt::Debug for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + fmt::Debug, { /// A `Simd` has a debug format like the one for `[T]`: diff --git a/library/portable-simd/crates/core_simd/src/iter.rs b/library/portable-simd/crates/core_simd/src/iter.rs index b3732fd74d5f..fdc458efeda4 100644 --- a/library/portable-simd/crates/core_simd/src/iter.rs +++ b/library/portable-simd/crates/core_simd/src/iter.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; use core::{ iter::{Product, Sum}, ops::{Add, Mul}, @@ -7,8 +7,6 @@ use core::{ macro_rules! impl_traits { { $type:ty } => { impl Sum for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -17,8 +15,6 @@ macro_rules! impl_traits { } impl Product for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { @@ -27,8 +23,6 @@ macro_rules! impl_traits { } impl<'a, const N: usize> Sum<&'a Self> for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -37,8 +31,6 @@ macro_rules! impl_traits { } impl<'a, const N: usize> Product<&'a Self> for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs deleted file mode 100644 index bbdfd5f5f3ed..000000000000 --- a/library/portable-simd/crates/core_simd/src/lane_count.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod sealed { - pub trait Sealed {} -} -use sealed::Sealed; - -/// Specifies the number of lanes in a SIMD vector as a type. -pub struct LaneCount; - -impl LaneCount { - /// The number of bytes in a bitmask with this many lanes. - pub const BITMASK_LEN: usize = N.div_ceil(8); -} - -/// Statically guarantees that a lane count is marked as supported. -/// -/// This trait is *sealed*: the list of implementors below is total. -/// Users do not have the ability to mark additional `LaneCount` values as supported. -/// Only SIMD vectors with supported lane counts are constructable. -pub trait SupportedLaneCount: Sealed { - #[doc(hidden)] - type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; -} - -impl Sealed for LaneCount {} - -macro_rules! supported_lane_count { - ($($lanes:literal),+) => { - $( - impl SupportedLaneCount for LaneCount<$lanes> { - type BitMask = [u8; ($lanes + 7) / 8]; - } - )+ - }; -} - -supported_lane_count!( - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 -); diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index 717b882b64ba..fe26d99b9194 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -9,7 +9,8 @@ simd_ffi, staged_api, prelude_import, - ptr_metadata + ptr_metadata, + rustc_attrs )] #![cfg_attr( all( @@ -30,10 +31,6 @@ any(target_arch = "powerpc", target_arch = "powerpc64"), feature(stdarch_powerpc) )] -#![cfg_attr( - all(target_arch = "x86_64", target_feature = "avx512f"), - feature(stdarch_x86_avx512) -)] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really #![deny( unsafe_op_in_unsafe_fn, @@ -41,7 +38,7 @@ clippy::undocumented_unsafe_blocks )] #![doc(test(attr(deny(warnings))))] -#![allow(internal_features)] +#![allow(internal_features, clippy::repr_packed_without_abi)] #![unstable(feature = "portable_simd", issue = "86656")] //! Portable SIMD module. diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs index 19d45f4d3b31..3e2209556b66 100644 --- a/library/portable-simd/crates/core_simd/src/masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -2,20 +2,33 @@ //! Types representing #![allow(non_camel_case_types)] -#[cfg_attr( - not(all(target_arch = "x86_64", target_feature = "avx512f")), - path = "masks/full_masks.rs" -)] -#[cfg_attr( - all(target_arch = "x86_64", target_feature = "avx512f"), - path = "masks/bitmask.rs" -)] -mod mask_impl; - -use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{Select, Simd, SimdCast, SimdElement}; use core::cmp::Ordering; use core::{fmt, mem}; +pub(crate) trait FixEndianness { + fn fix_endianness(self) -> Self; +} + +macro_rules! impl_fix_endianness { + { $($int:ty),* } => { + $( + impl FixEndianness for $int { + #[inline(always)] + fn fix_endianness(self) -> Self { + if cfg!(target_endian = "big") { + <$int>::reverse_bits(self) + } else { + self + } + } + } + )* + } +} + +impl_fix_endianness! { u8, u16, u32, u64 } + mod sealed { use super::*; @@ -28,7 +41,6 @@ mod sealed { pub trait Sealed { fn valid(values: Simd) -> bool where - LaneCount: SupportedLaneCount, Self: SimdElement; fn eq(self, other: Self) -> bool; @@ -56,8 +68,6 @@ macro_rules! impl_element { impl Sealed for $ty { #[inline] fn valid(value: Simd) -> bool - where - LaneCount: SupportedLaneCount, { // We can't use `Simd` directly, because `Simd`'s functions call this function and // we will end up with an infinite loop. @@ -108,23 +118,19 @@ impl_element! { isize, usize } /// The layout of this type is unspecified, and may change between platforms /// and/or Rust versions, and code should not assume that it is equivalent to /// `[T; N]`. +/// +/// `N` cannot be 0 and may be at most 64. This limit may be increased in +/// the future. #[repr(transparent)] -pub struct Mask(mask_impl::Mask) +pub struct Mask(Simd) where - T: MaskElement, - LaneCount: SupportedLaneCount; + T: MaskElement; -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} +impl Copy for Mask where T: MaskElement {} impl Clone for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn clone(&self) -> Self { @@ -135,12 +141,12 @@ where impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { /// Constructs a mask by setting all elements to the given value. #[inline] - pub fn splat(value: bool) -> Self { - Self(mask_impl::Mask::splat(value)) + #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] + pub const fn splat(value: bool) -> Self { + Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } /// Converts an array of bools to a SIMD mask. @@ -156,7 +162,7 @@ where let bytes: [u8; N] = mem::transmute_copy(&array); let bools: Simd = core::intrinsics::simd::simd_ne(Simd::from_array(bytes), Simd::splat(0u8)); - Mask::from_int_unchecked(core::intrinsics::simd::simd_cast(bools)) + Mask::from_simd_unchecked(core::intrinsics::simd::simd_cast(bools)) } } @@ -174,7 +180,7 @@ where // This would be hypothetically valid as an "in-place" transmute, // but these are "dependently-sized" types, so copy elision it is! unsafe { - let mut bytes: Simd = core::intrinsics::simd::simd_cast(self.to_int()); + let mut bytes: Simd = core::intrinsics::simd::simd_cast(self.to_simd()); bytes &= Simd::splat(1i8); mem::transmute_copy(&bytes) } @@ -187,12 +193,12 @@ where /// All elements must be either 0 or -1. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub unsafe fn from_simd_unchecked(value: Simd) -> Self { // Safety: the caller must confirm this invariant unsafe { core::intrinsics::assume(::valid(value)); - Self(mask_impl::Mask::from_int_unchecked(value)) } + Self(value) } /// Converts a vector of integers to a mask, where 0 represents `false` and -1 @@ -203,25 +209,26 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] #[track_caller] - pub fn from_int(value: Simd) -> Self { + pub fn from_simd(value: Simd) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); // Safety: the validity has been checked - unsafe { Self::from_int_unchecked(value) } + unsafe { Self::from_simd_unchecked(value) } } /// Converts the mask to a vector of integers, where 0 represents `false` and -1 /// represents `true`. #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { - self.0.to_int() + pub fn to_simd(self) -> Simd { + self.0 } /// Converts the mask to a mask of any other element size. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] pub fn cast(self) -> Mask { - Mask(self.0.convert()) + // Safety: mask elements are integers + unsafe { Mask(core::intrinsics::simd::simd_as(self.0)) } } /// Tests the value of the specified element. @@ -232,7 +239,7 @@ where #[must_use = "method returns a new bool and does not mutate the original value"] pub unsafe fn test_unchecked(&self, index: usize) -> bool { // Safety: the caller must confirm this invariant - unsafe { self.0.test_unchecked(index) } + unsafe { T::eq(*self.0.as_array().get_unchecked(index), T::TRUE) } } /// Tests the value of the specified element. @@ -243,9 +250,7 @@ where #[must_use = "method returns a new bool and does not mutate the original value"] #[track_caller] pub fn test(&self, index: usize) -> bool { - assert!(index < N, "element index out of range"); - // Safety: the element index has been checked - unsafe { self.test_unchecked(index) } + T::eq(self.0[index], T::TRUE) } /// Sets the value of the specified element. @@ -256,7 +261,7 @@ where pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) { // Safety: the caller must confirm this invariant unsafe { - self.0.set_unchecked(index, value); + *self.0.as_mut_array().get_unchecked_mut(index) = if value { T::TRUE } else { T::FALSE } } } @@ -267,35 +272,65 @@ where #[inline] #[track_caller] pub fn set(&mut self, index: usize, value: bool) { - assert!(index < N, "element index out of range"); - // Safety: the element index has been checked - unsafe { - self.set_unchecked(index, value); - } + self.0[index] = if value { T::TRUE } else { T::FALSE } } /// Returns true if any element is set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { - self.0.any() + // Safety: `self` is a mask vector + unsafe { core::intrinsics::simd::simd_reduce_any(self.0) } } /// Returns true if all elements are set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { - self.0.all() + // Safety: `self` is a mask vector + unsafe { core::intrinsics::simd::simd_reduce_all(self.0) } } /// Creates a bitmask from a mask. /// /// Each bit is set if the corresponding element in the mask is `true`. - /// If the mask contains more than 64 elements, the bitmask is truncated to the first 64. #[inline] #[must_use = "method returns a new integer and does not mutate the original value"] pub fn to_bitmask(self) -> u64 { - self.0.to_bitmask_integer() + const { + assert!(N <= 64, "number of elements can't be greater than 64"); + } + + #[inline] + unsafe fn to_bitmask_impl( + mask: Mask, + ) -> U + where + T: MaskElement, + { + let resized = mask.resize::(false); + + // Safety: `resized` is an integer vector with length M, which must match T + let bitmask: U = unsafe { core::intrinsics::simd::simd_bitmask(resized.0) }; + + // LLVM assumes bit order should match endianness + bitmask.fix_endianness() + } + + // TODO modify simd_bitmask to zero-extend output, making this unnecessary + if N <= 8 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else if N <= 16 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else if N <= 32 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) } + } } /// Creates a mask from a bitmask. @@ -305,7 +340,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_bitmask(bitmask: u64) -> Self { - Self(mask_impl::Mask::from_bitmask_integer(bitmask)) + Self(bitmask.select(Simd::splat(T::TRUE), Simd::splat(T::FALSE))) } /// Finds the index of the first set element. @@ -351,7 +386,7 @@ where // Safety: the input and output are integer vectors let index: Simd = unsafe { core::intrinsics::simd::simd_cast(index) }; - let masked_index = self.select(index, Self::splat(true).to_int()); + let masked_index = self.select(index, Self::splat(true).to_simd()); // Safety: the input and output are integer vectors let masked_index: Simd = @@ -376,7 +411,6 @@ where impl From<[bool; N]> for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn from(array: [bool; N]) -> Self { @@ -387,7 +421,6 @@ where impl From> for [bool; N] where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn from(vector: Mask) -> Self { @@ -398,7 +431,6 @@ where impl Default for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn default() -> Self { @@ -409,7 +441,6 @@ where impl PartialEq for Mask where T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -420,7 +451,6 @@ where impl PartialOrd for Mask where T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, { #[inline] fn partial_cmp(&self, other: &Self) -> Option { @@ -431,7 +461,6 @@ where impl fmt::Debug for Mask where T: MaskElement + fmt::Debug, - LaneCount: SupportedLaneCount, { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -444,19 +473,18 @@ where impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { - Self(self.0 & rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) } } } impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -468,7 +496,6 @@ where impl core::ops::BitAnd> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -480,19 +507,18 @@ where impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { - Self(self.0 | rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) } } } impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -504,7 +530,6 @@ where impl core::ops::BitOr> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -516,19 +541,18 @@ where impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self::Output { - Self(self.0 ^ rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) } } } impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -540,7 +564,6 @@ where impl core::ops::BitXor> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -552,30 +575,27 @@ where impl core::ops::Not for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] fn not(self) -> Self::Output { - Self(!self.0) + Self::splat(true) ^ self } } impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: Self) { - self.0 = self.0 & rhs.0; + *self = *self & rhs; } } impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: bool) { @@ -586,18 +606,16 @@ where impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: Self) { - self.0 = self.0 | rhs.0; + *self = *self | rhs; } } impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: bool) { @@ -608,18 +626,16 @@ where impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: Self) { - self.0 = self.0 ^ rhs.0; + *self = *self ^ rhs; } } impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: bool) { @@ -631,8 +647,6 @@ macro_rules! impl_from { { $from:ty => $($to:ty),* } => { $( impl From> for Mask<$to, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn from(value: Mask<$from, N>) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs deleted file mode 100644 index 32d37b553392..000000000000 --- a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs +++ /dev/null @@ -1,228 +0,0 @@ -#![allow(unused_imports)] -use super::MaskElement; -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; -use core::marker::PhantomData; - -/// A mask where each lane is represented by a single bit. -#[repr(transparent)] -pub(crate) struct Mask( - as SupportedLaneCount>::BitMask, - PhantomData, -) -where - T: MaskElement, - LaneCount: SupportedLaneCount; - -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Clone for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.0.as_ref() == other.0.as_ref() - } -} - -impl PartialOrd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.as_ref().partial_cmp(other.0.as_ref()) - } -} - -impl Eq for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Ord for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.as_ref().cmp(other.0.as_ref()) - } -} - -impl Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn splat(value: bool) -> Self { - let mut mask = as SupportedLaneCount>::BitMask::default(); - if value { - mask.as_mut().fill(u8::MAX) - } else { - mask.as_mut().fill(u8::MIN) - } - if N % 8 > 0 { - *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); - } - Self(mask, PhantomData) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { - (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 - } - - #[inline] - pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { - unsafe { - self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8) - } - } - - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_int(self) -> Simd { - unsafe { - core::intrinsics::simd::simd_select_bitmask( - self.0, - Simd::splat(T::TRUE), - Simd::splat(T::FALSE), - ) - } - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { - unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } - } - - #[inline] - pub(crate) fn to_bitmask_integer(self) -> u64 { - let mut bitmask = [0u8; 8]; - bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); - u64::from_ne_bytes(bitmask) - } - - #[inline] - pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - let mut bytes = as SupportedLaneCount>::BitMask::default(); - let len = bytes.as_mut().len(); - bytes - .as_mut() - .copy_from_slice(&bitmask.to_ne_bytes()[..len]); - Self(bytes, PhantomData) - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn convert(self) -> Mask - where - U: MaskElement, - { - // Safety: bitmask layout does not depend on the element width - unsafe { core::mem::transmute_copy(&self) } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn any(self) -> bool { - self != Self::splat(false) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn all(self) -> bool { - self == Self::splat(true) - } -} - -impl core::ops::BitAnd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, -{ - type Output = Self; - #[inline] - fn bitand(mut self, rhs: Self) -> Self { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l &= r; - } - self - } -} - -impl core::ops::BitOr for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, -{ - type Output = Self; - #[inline] - fn bitor(mut self, rhs: Self) -> Self { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l |= r; - } - self - } -} - -impl core::ops::BitXor for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitxor(mut self, rhs: Self) -> Self::Output { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l ^= r; - } - self - } -} - -impl core::ops::Not for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn not(mut self) -> Self::Output { - for x in self.0.as_mut() { - *x = !*x; - } - if N % 8 > 0 { - *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); - } - self - } -} diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs deleted file mode 100644 index 4e98db4070a9..000000000000 --- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs +++ /dev/null @@ -1,296 +0,0 @@ -//! Masks that take up full SIMD vector registers. - -use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount}; - -#[repr(transparent)] -pub(crate) struct Mask(Simd) -where - T: MaskElement, - LaneCount: SupportedLaneCount; - -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Clone for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for Mask -where - T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.0.eq(&other.0) - } -} - -impl PartialOrd for Mask -where - T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) - } -} - -impl Eq for Mask -where - T: MaskElement + Eq, - LaneCount: SupportedLaneCount, -{ -} - -impl Ord for Mask -where - T: MaskElement + Ord, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.cmp(&other.0) - } -} - -// Used for bitmask bit order workaround -pub(crate) trait ReverseBits { - // Reverse the least significant `n` bits of `self`. - // (Remaining bits must be 0.) - fn reverse_bits(self, n: usize) -> Self; -} - -macro_rules! impl_reverse_bits { - { $($int:ty),* } => { - $( - impl ReverseBits for $int { - #[inline(always)] - fn reverse_bits(self, n: usize) -> Self { - let rev = <$int>::reverse_bits(self); - let bitsize = size_of::<$int>() * 8; - if n < bitsize { - // Shift things back to the right - rev >> (bitsize - n) - } else { - rev - } - } - } - )* - } -} - -impl_reverse_bits! { u8, u16, u32, u64 } - -impl Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn splat(value: bool) -> Self { - Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { - T::eq(self.0[lane], T::TRUE) - } - - #[inline] - pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { - self.0[lane] = if value { T::TRUE } else { T::FALSE } - } - - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_int(self) -> Simd { - self.0 - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { - Self(value) - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn convert(self) -> Mask - where - U: MaskElement, - { - // Safety: masks are simply integer vectors of 0 and -1, and we can cast the element type. - unsafe { Mask(core::intrinsics::simd::simd_cast(self.0)) } - } - - #[inline] - unsafe fn to_bitmask_impl(self) -> U - where - LaneCount: SupportedLaneCount, - { - let resized = self.to_int().resize::(T::FALSE); - - // Safety: `resized` is an integer vector with length M, which must match T - let bitmask: U = unsafe { core::intrinsics::simd::simd_bitmask(resized) }; - - // LLVM assumes bit order should match endianness - if cfg!(target_endian = "big") { - bitmask.reverse_bits(M) - } else { - bitmask - } - } - - #[inline] - unsafe fn from_bitmask_impl(bitmask: U) -> Self - where - LaneCount: SupportedLaneCount, - { - // LLVM assumes bit order should match endianness - let bitmask = if cfg!(target_endian = "big") { - bitmask.reverse_bits(M) - } else { - bitmask - }; - - // SAFETY: `mask` is the correct bitmask type for a u64 bitmask - let mask: Simd = unsafe { - core::intrinsics::simd::simd_select_bitmask( - bitmask, - Simd::::splat(T::TRUE), - Simd::::splat(T::FALSE), - ) - }; - - // SAFETY: `mask` only contains `T::TRUE` or `T::FALSE` - unsafe { Self::from_int_unchecked(mask.resize::(T::FALSE)) } - } - - #[inline] - pub(crate) fn to_bitmask_integer(self) -> u64 { - // TODO modify simd_bitmask to zero-extend output, making this unnecessary - if N <= 8 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else if N <= 16 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else if N <= 32 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() } - } - } - - #[inline] - pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - // TODO modify simd_bitmask_select to truncate input, making this unnecessary - if N <= 8 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u8) } - } else if N <= 16 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u16) } - } else if N <= 32 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u32) } - } else { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask) } - } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn any(self) -> bool { - // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_any(self.to_int()) } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn all(self) -> bool { - // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) } - } -} - -impl From> for Simd -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn from(value: Mask) -> Self { - value.0 - } -} - -impl core::ops::BitAnd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitand(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) } - } -} - -impl core::ops::BitOr for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitor(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) } - } -} - -impl core::ops::BitXor for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitxor(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) } - } -} - -impl core::ops::Not for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn not(self) -> Self::Output { - Self::splat(true) ^ self - } -} diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs index 45b1a0f97514..5f635d80a178 100644 --- a/library/portable-simd/crates/core_simd/src/mod.rs +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -5,7 +5,6 @@ mod alias; mod cast; mod fmt; mod iter; -mod lane_count; mod masks; mod ops; mod select; @@ -27,8 +26,8 @@ pub mod simd { pub use crate::core_simd::alias::*; pub use crate::core_simd::cast::*; - pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; + pub use crate::core_simd::select::*; pub use crate::core_simd::swizzle::*; pub use crate::core_simd::to_bytes::ToBytes; pub use crate::core_simd::vector::*; diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs index f36e8d01a73b..eb6601f73483 100644 --- a/library/portable-simd/crates/core_simd/src/ops.rs +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; +use crate::simd::{Select, Simd, SimdElement, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; @@ -12,7 +12,6 @@ mod unary; impl core::ops::Index for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { type Output = I::Output; @@ -25,7 +24,6 @@ where impl core::ops::IndexMut for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { #[inline] @@ -130,7 +128,6 @@ macro_rules! for_base_types { impl $op for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = $out; diff --git a/library/portable-simd/crates/core_simd/src/ops/assign.rs b/library/portable-simd/crates/core_simd/src/ops/assign.rs index d21d867de26d..c1830c35df77 100644 --- a/library/portable-simd/crates/core_simd/src/ops/assign.rs +++ b/library/portable-simd/crates/core_simd/src/ops/assign.rs @@ -21,7 +21,6 @@ macro_rules! assign_ops { where Self: $trait, T: SimdElement, - LaneCount: SupportedLaneCount, { #[inline] fn $assign_call(&mut self, rhs: U) { diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs index 913cbbe977c4..360b83c40346 100644 --- a/library/portable-simd/crates/core_simd/src/ops/deref.rs +++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs @@ -13,7 +13,6 @@ macro_rules! deref_lhs { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = Simd; @@ -33,7 +32,6 @@ macro_rules! deref_rhs { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = Simd; @@ -64,7 +62,6 @@ macro_rules! deref_ops { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = $simd; diff --git a/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs b/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs index f5115a5a5e93..7ca83dc40f61 100644 --- a/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs +++ b/library/portable-simd/crates/core_simd/src/ops/shift_scalar.rs @@ -1,13 +1,11 @@ // Shift operations uniquely typically only have a scalar on the right-hand side. // Here, we implement shifts for scalar RHS arguments. -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; macro_rules! impl_splatted_shifts { { impl $trait:ident :: $trait_fn:ident for $ty:ty } => { impl core::ops::$trait<$ty> for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -17,8 +15,6 @@ macro_rules! impl_splatted_shifts { } impl core::ops::$trait<&$ty> for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -28,8 +24,6 @@ macro_rules! impl_splatted_shifts { } impl<'lhs, const N: usize> core::ops::$trait<$ty> for &'lhs Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Simd<$ty, N>; #[inline] @@ -39,8 +33,6 @@ macro_rules! impl_splatted_shifts { } impl<'lhs, const N: usize> core::ops::$trait<&$ty> for &'lhs Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Simd<$ty, N>; #[inline] diff --git a/library/portable-simd/crates/core_simd/src/ops/unary.rs b/library/portable-simd/crates/core_simd/src/ops/unary.rs index 412a5b801171..e1c06167f979 100644 --- a/library/portable-simd/crates/core_simd/src/ops/unary.rs +++ b/library/portable-simd/crates/core_simd/src/ops/unary.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Simd, SimdElement}; use core::ops::{Neg, Not}; // unary ops macro_rules! neg { @@ -6,7 +6,6 @@ macro_rules! neg { $(impl Neg for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = Self; @@ -40,7 +39,6 @@ macro_rules! not { $(impl Not for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = Self; diff --git a/library/portable-simd/crates/core_simd/src/select.rs b/library/portable-simd/crates/core_simd/src/select.rs index f33aa261a928..404f54d8f382 100644 --- a/library/portable-simd/crates/core_simd/src/select.rs +++ b/library/portable-simd/crates/core_simd/src/select.rs @@ -1,54 +1,155 @@ -use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{FixEndianness, Mask, MaskElement, Simd, SimdElement}; -impl Mask +/// Choose elements from two vectors using a mask. +/// +/// For each element in the mask, choose the corresponding element from `true_values` if +/// that element mask is true, and `false_values` if that element mask is false. +/// +/// If the mask is `u64`, it's treated as a bitmask with the least significant bit +/// corresponding to the first element. +/// +/// # Examples +/// +/// ## Selecting values from `Simd` +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Simd, Mask, Select}; +/// let a = Simd::from_array([0, 1, 2, 3]); +/// let b = Simd::from_array([4, 5, 6, 7]); +/// let mask = Mask::::from_array([true, false, false, true]); +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [0, 5, 6, 3]); +/// ``` +/// +/// ## Selecting values from `Mask` +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Mask, Select}; +/// let a = Mask::::from_array([true, true, false, false]); +/// let b = Mask::::from_array([false, false, true, true]); +/// let mask = Mask::::from_array([true, false, false, true]); +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [true, false, true, false]); +/// ``` +/// +/// ## Selecting with a bitmask +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Mask, Select}; +/// let a = Mask::::from_array([true, true, false, false]); +/// let b = Mask::::from_array([false, false, true, true]); +/// let mask = 0b1001; +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [true, false, true, false]); +/// ``` +pub trait Select { + /// Choose elements + fn select(self, true_values: T, false_values: T) -> T; +} + +impl Select> for Mask where - T: MaskElement, - LaneCount: SupportedLaneCount, + T: SimdElement, + U: MaskElement, { - /// Choose elements from two vectors. - /// - /// For each element in the mask, choose the corresponding element from `true_values` if - /// that element mask is true, and `false_values` if that element mask is false. - /// - /// # Examples - /// ``` - /// # #![feature(portable_simd)] - /// # use core::simd::{Simd, Mask}; - /// let a = Simd::from_array([0, 1, 2, 3]); - /// let b = Simd::from_array([4, 5, 6, 7]); - /// let mask = Mask::from_array([true, false, false, true]); - /// let c = mask.select(a, b); - /// assert_eq!(c.to_array(), [0, 5, 6, 3]); - /// ``` #[inline] - #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn select(self, true_values: Simd, false_values: Simd) -> Simd - where - U: SimdElement, - { - // Safety: The mask has been cast to a vector of integers, - // and the operands to select between are vectors of the same type and length. - unsafe { core::intrinsics::simd::simd_select(self.to_int(), true_values, false_values) } - } - - /// Choose elements from two masks. - /// - /// For each element in the mask, choose the corresponding element from `true_values` if - /// that element mask is true, and `false_values` if that element mask is false. - /// - /// # Examples - /// ``` - /// # #![feature(portable_simd)] - /// # use core::simd::Mask; - /// let a = Mask::::from_array([true, true, false, false]); - /// let b = Mask::::from_array([false, false, true, true]); - /// let mask = Mask::::from_array([true, false, false, true]); - /// let c = mask.select_mask(a, b); - /// assert_eq!(c.to_array(), [true, false, true, false]); - /// ``` - #[inline] - #[must_use = "method returns a new mask and does not mutate the original inputs"] - pub fn select_mask(self, true_values: Self, false_values: Self) -> Self { - self & true_values | !self & false_values + fn select(self, true_values: Simd, false_values: Simd) -> Simd { + // Safety: + // simd_as between masks is always safe (they're vectors of ints). + // simd_select uses a mask that matches the width and number of elements + unsafe { + let mask: Simd = core::intrinsics::simd::simd_as(self.to_simd()); + core::intrinsics::simd::simd_select(mask, true_values, false_values) + } + } +} + +impl Select> for u64 +where + T: SimdElement, +{ + #[inline] + fn select(self, true_values: Simd, false_values: Simd) -> Simd { + const { + assert!(N <= 64, "number of elements can't be greater than 64"); + } + + #[inline] + unsafe fn select_impl( + bitmask: U, + true_values: Simd, + false_values: Simd, + ) -> Simd + where + T: SimdElement, + { + let default = true_values[0]; + let true_values = true_values.resize::(default); + let false_values = false_values.resize::(default); + + // LLVM assumes bit order should match endianness + let bitmask = bitmask.fix_endianness(); + + // Safety: the caller guarantees that the size of U matches M + let selected = unsafe { + core::intrinsics::simd::simd_select_bitmask(bitmask, true_values, false_values) + }; + + selected.resize::(default) + } + + // TODO modify simd_bitmask_select to truncate input, making this unnecessary + if N <= 8 { + let bitmask = self as u8; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else if N <= 16 { + let bitmask = self as u16; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else if N <= 32 { + let bitmask = self as u32; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else { + let bitmask = self; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } + } +} + +impl Select> for Mask +where + T: MaskElement, + U: MaskElement, +{ + #[inline] + fn select(self, true_values: Mask, false_values: Mask) -> Mask { + let selected: Simd = + Select::select(self, true_values.to_simd(), false_values.to_simd()); + + // Safety: all values come from masks + unsafe { Mask::from_simd_unchecked(selected) } + } +} + +impl Select> for u64 +where + T: MaskElement, +{ + #[inline] + fn select(self, true_values: Mask, false_values: Mask) -> Mask { + let selected: Simd = + Select::select(self, true_values.to_simd(), false_values.to_simd()); + + // Safety: all values come from masks + unsafe { Mask::from_simd_unchecked(selected) } } } diff --git a/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs index 2312ba401fa7..d553d6c040c9 100644 --- a/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, + Mask, Simd, SimdElement, ptr::{SimdConstPtr, SimdMutPtr}, }; @@ -21,8 +21,6 @@ macro_rules! impl_number { { $($number:ty),* } => { $( impl SimdPartialEq for Simd<$number, N> - where - LaneCount: SupportedLaneCount, { type Mask = Mask<<$number as SimdElement>::Mask, N>; @@ -30,14 +28,14 @@ macro_rules! impl_number { fn simd_eq(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_eq(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_eq(self, other)) } } #[inline] fn simd_ne(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ne(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ne(self, other)) } } } )* @@ -50,8 +48,6 @@ macro_rules! impl_mask { { $($integer:ty),* } => { $( impl SimdPartialEq for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { type Mask = Self; @@ -59,14 +55,14 @@ macro_rules! impl_mask { fn simd_eq(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_eq(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_eq(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ne(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ne(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_ne(self.to_simd(), other.to_simd())) } } } )* @@ -75,10 +71,7 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialEq for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialEq for Simd<*const T, N> { type Mask = Mask; #[inline] @@ -92,10 +85,7 @@ where } } -impl SimdPartialEq for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialEq for Simd<*mut T, N> { type Mask = Mask; #[inline] diff --git a/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs index e813e7613032..5672fbbf54ca 100644 --- a/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, Simd, SupportedLaneCount, + Mask, Select, Simd, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, }; @@ -49,41 +49,37 @@ macro_rules! impl_integer { { $($integer:ty),* } => { $( impl SimdPartialOrd for Simd<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_lt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_le(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_gt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ge(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) } } } impl SimdOrd for Simd<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -115,35 +111,33 @@ macro_rules! impl_float { { $($float:ty),* } => { $( impl SimdPartialOrd for Simd<$float, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_lt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_le(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_gt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ge(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) } } } )* @@ -156,50 +150,46 @@ macro_rules! impl_mask { { $($integer:ty),* } => { $( impl SimdPartialOrd for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_lt(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_le(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_le(self.to_simd(), other.to_simd())) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_gt(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ge(self.to_int(), other.to_int())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(), other.to_simd())) } } } impl SimdOrd for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { - self.simd_gt(other).select_mask(other, self) + self.simd_gt(other).select(other, self) } #[inline] fn simd_min(self, other: Self) -> Self { - self.simd_lt(other).select_mask(other, self) + self.simd_lt(other).select(other, self) } #[inline] @@ -218,10 +208,7 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialOrd for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialOrd for Simd<*const T, N> { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { self.addr().simd_lt(other.addr()) @@ -243,10 +230,7 @@ where } } -impl SimdOrd for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdOrd for Simd<*const T, N> { #[inline] fn simd_max(self, other: Self) -> Self { self.simd_lt(other).select(other, self) @@ -268,10 +252,7 @@ where } } -impl SimdPartialOrd for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialOrd for Simd<*mut T, N> { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { self.addr().simd_lt(other.addr()) @@ -293,10 +274,7 @@ where } } -impl SimdOrd for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdOrd for Simd<*mut T, N> { #[inline] fn simd_max(self, other: Self) -> Self { self.simd_lt(other).select(other, self) diff --git a/library/portable-simd/crates/core_simd/src/simd/num/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs index b5972c47373b..efd7c2469512 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/float.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, + Mask, Select, Simd, SimdCast, SimdElement, cmp::{SimdPartialEq, SimdPartialOrd}, }; @@ -240,15 +240,9 @@ pub trait SimdFloat: Copy + Sealed { macro_rules! impl_trait { { $($ty:ty { bits: $bits_ty:ty, mask: $mask_ty:ty }),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} impl SimdFloat for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Mask = Mask<<$mask_ty as SimdElement>::Mask, N>; type Scalar = $ty; diff --git a/library/portable-simd/crates/core_simd/src/simd/num/int.rs b/library/portable-simd/crates/core_simd/src/simd/num/int.rs index e7253313f036..eee54d396880 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/int.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/int.rs @@ -1,7 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, - cmp::SimdPartialOrd, num::SimdUint, + Mask, Select, Simd, SimdCast, SimdElement, cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, }; /// Operations on SIMD vectors of signed integers. @@ -242,16 +241,9 @@ pub trait SimdInt: Copy + Sealed { macro_rules! impl_trait { { $($ty:ident ($unsigned:ident)),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} - impl SimdInt for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { + impl SimdInt for Simd<$ty, N> { type Mask = Mask<<$ty as SimdElement>::Mask, N>; type Scalar = $ty; type Unsigned = Simd<$unsigned, N>; diff --git a/library/portable-simd/crates/core_simd/src/simd/num/uint.rs b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs index e3ba8658bd80..606107a1f06f 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/uint.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd}; +use crate::simd::{Simd, SimdCast, SimdElement, cmp::SimdOrd}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { @@ -124,15 +124,9 @@ pub trait SimdUint: Copy + Sealed { macro_rules! impl_trait { { $($ty:ident ($signed:ident)),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} impl SimdUint for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Scalar = $ty; type Cast = Simd; diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs index 36452e7ae920..7ef9dc21373e 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; +use crate::simd::{Mask, Simd, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { @@ -88,12 +88,9 @@ pub trait SimdConstPtr: Copy + Sealed { fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*const T, N> where LaneCount: SupportedLaneCount {} +impl Sealed for Simd<*const T, N> {} -impl SimdConstPtr for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdConstPtr for Simd<*const T, N> { type Usize = Simd; type Isize = Simd; type CastPtr = Simd<*const U, N>; diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs index c644f390c20a..3b9b75ddf566 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; +use crate::simd::{Mask, Simd, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { @@ -85,12 +85,9 @@ pub trait SimdMutPtr: Copy + Sealed { fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*mut T, N> where LaneCount: SupportedLaneCount {} +impl Sealed for Simd<*mut T, N> {} -impl SimdMutPtr for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdMutPtr for Simd<*mut T, N> { type Usize = Simd; type Isize = Simd; type CastPtr = Simd<*mut U, N>; diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index dbdd6ef40eba..02dcd71356dd 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Mask, MaskElement, Simd, SimdElement}; /// Constructs a new SIMD vector by copying elements from selected elements in other vectors. /// @@ -82,8 +82,6 @@ pub trait Swizzle { fn swizzle(vector: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // Safety: `vector` is a vector, and the index is a const vector of u32. unsafe { @@ -122,8 +120,6 @@ pub trait Swizzle { fn concat_swizzle(first: Simd, second: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // Safety: `first` and `second` are vectors, and the index is a const vector of u32. unsafe { @@ -161,11 +157,9 @@ pub trait Swizzle { fn swizzle_mask(mask: Mask) -> Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_int())) } + unsafe { Mask::from_simd_unchecked(Self::swizzle(mask.to_simd())) } } /// Creates a new mask from the elements of `first` and `second`. @@ -177,18 +171,17 @@ pub trait Swizzle { fn concat_swizzle_mask(first: Mask, second: Mask) -> Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::concat_swizzle(first.to_int(), second.to_int())) } + unsafe { + Mask::from_simd_unchecked(Self::concat_swizzle(first.to_simd(), second.to_simd())) + } } } impl Simd where T: SimdElement, - LaneCount: SupportedLaneCount, { /// Reverse the order of the elements in the vector. #[inline] @@ -462,10 +455,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn resize(self, value: T) -> Simd - where - LaneCount: SupportedLaneCount, - { + pub fn resize(self, value: T) -> Simd { struct Resize; impl Swizzle for Resize { const INDEX: [usize; M] = const { @@ -493,10 +483,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn extract(self) -> Simd - where - LaneCount: SupportedLaneCount, - { + pub fn extract(self) -> Simd { struct Extract; impl Swizzle for Extract { const INDEX: [usize; LEN] = const { @@ -517,14 +504,13 @@ where impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { /// Reverse the order of the elements in the mask. #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn reverse(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().reverse()) } + unsafe { Self::from_simd_unchecked(self.to_simd().reverse()) } } /// Rotates the mask such that the first `OFFSET` elements of the slice move to the end @@ -534,7 +520,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_left(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_left::()) } + unsafe { Self::from_simd_unchecked(self.to_simd().rotate_elements_left::()) } } /// Rotates the mask such that the first `self.len() - OFFSET` elements of the mask move to @@ -544,7 +530,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_right(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_right::()) } + unsafe { Self::from_simd_unchecked(self.to_simd().rotate_elements_right::()) } } /// Shifts the mask elements to the left by `OFFSET`, filling in with @@ -554,7 +540,7 @@ where pub fn shift_elements_left(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_int().shift_elements_left::(if padding { + Self::from_simd_unchecked(self.to_simd().shift_elements_left::(if padding { T::TRUE } else { T::FALSE @@ -569,7 +555,7 @@ where pub fn shift_elements_right(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_int().shift_elements_right::(if padding { + Self::from_simd_unchecked(self.to_simd().shift_elements_right::(if padding { T::TRUE } else { T::FALSE @@ -598,9 +584,9 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn interleave(self, other: Self) -> (Self, Self) { - let (lo, hi) = self.to_int().interleave(other.to_int()); + let (lo, hi) = self.to_simd().interleave(other.to_simd()); // Safety: swizzles are safe for masks - unsafe { (Self::from_int_unchecked(lo), Self::from_int_unchecked(hi)) } + unsafe { (Self::from_simd_unchecked(lo), Self::from_simd_unchecked(hi)) } } /// Deinterleave two masks. @@ -627,12 +613,12 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn deinterleave(self, other: Self) -> (Self, Self) { - let (even, odd) = self.to_int().deinterleave(other.to_int()); + let (even, odd) = self.to_simd().deinterleave(other.to_simd()); // Safety: swizzles are safe for masks unsafe { ( - Self::from_int_unchecked(even), - Self::from_int_unchecked(odd), + Self::from_simd_unchecked(even), + Self::from_simd_unchecked(odd), ) } } @@ -653,13 +639,10 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn resize(self, value: bool) -> Mask - where - LaneCount: SupportedLaneCount, - { + pub fn resize(self, value: bool) -> Mask { // Safety: swizzles are safe for masks unsafe { - Mask::::from_int_unchecked(self.to_int().resize::(if value { + Mask::::from_simd_unchecked(self.to_simd().resize::(if value { T::TRUE } else { T::FALSE @@ -679,11 +662,8 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn extract(self) -> Mask - where - LaneCount: SupportedLaneCount, - { + pub fn extract(self) -> Mask { // Safety: swizzles are safe for masks - unsafe { Mask::::from_int_unchecked(self.to_int().extract::()) } + unsafe { Mask::::from_simd_unchecked(self.to_simd().extract::()) } } } diff --git a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs index 773bd028bae0..ae0b174973da 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs @@ -1,10 +1,7 @@ -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; use core::mem; -impl Simd -where - LaneCount: SupportedLaneCount, -{ +impl Simd { /// Swizzle a vector of bytes according to the index vector. /// Indices within range select the appropriate byte. /// Indices "out of bounds" instead select 0. @@ -139,7 +136,7 @@ unsafe fn armv7_neon_swizzle_u8x16(bytes: Simd, idxs: Simd) -> S #[inline] #[allow(clippy::let_and_return)] unsafe fn avx2_pshufb(bytes: Simd, idxs: Simd) -> Simd { - use crate::simd::cmp::SimdPartialOrd; + use crate::simd::{Select, cmp::SimdPartialOrd}; #[cfg(target_arch = "x86")] use core::arch::x86; #[cfg(target_arch = "x86_64")] @@ -184,10 +181,7 @@ unsafe fn transize( f: unsafe fn(T, T) -> T, a: Simd, b: Simd, -) -> Simd -where - LaneCount: SupportedLaneCount, -{ +) -> Simd { // SAFETY: Same obligation to use this function as to use mem::transmute_copy. unsafe { mem::transmute_copy(&f(mem::transmute_copy(&a), mem::transmute_copy(&b))) } } @@ -196,11 +190,8 @@ where #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[allow(unused)] #[inline(always)] -fn zeroing_idxs(idxs: Simd) -> Simd -where - LaneCount: SupportedLaneCount, -{ - use crate::simd::cmp::SimdPartialOrd; +fn zeroing_idxs(idxs: Simd) -> Simd { + use crate::simd::{Select, cmp::SimdPartialOrd}; idxs.simd_lt(Simd::splat(N as u8)) .select(idxs, Simd::splat(u8::MAX)) } diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs index fee2cc06c5b0..1fd285e457db 100644 --- a/library/portable-simd/crates/core_simd/src/to_bytes.rs +++ b/library/portable-simd/crates/core_simd/src/to_bytes.rs @@ -1,12 +1,12 @@ use crate::simd::{ - LaneCount, Simd, SimdElement, SupportedLaneCount, + Simd, SimdElement, num::{SimdFloat, SimdInt, SimdUint}, }; mod sealed { use super::*; pub trait Sealed {} - impl Sealed for Simd where LaneCount: SupportedLaneCount {} + impl Sealed for Simd {} } use sealed::Sealed; diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index f40031f8c4da..5b3a689f3611 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -1,5 +1,7 @@ +use core::intrinsics::simd::SimdAlign; + use crate::simd::{ - LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, + Mask, MaskElement, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, @@ -51,6 +53,8 @@ use crate::simd::{ /// Thus it is sound to [`transmute`] `Simd` to `[T; N]` and should optimize to "zero cost", /// but the reverse transmutation may require a copy the compiler cannot simply elide. /// +/// `N` cannot be 0 and may be at most 64. This limit may be increased in the future. +/// /// # ABI "Features" /// Due to Rust's safety guarantees, `Simd` is currently passed and returned via memory, /// not SIMD registers, except as an optimization. Using `#[inline]` on functions that accept @@ -100,14 +104,13 @@ use crate::simd::{ // avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also // causes rustc to emit illegal LLVM IR in some cases. #[repr(simd, packed)] +#[rustc_simd_monomorphize_lane_limit = "64"] pub struct Simd([T; N]) where - LaneCount: SupportedLaneCount, T: SimdElement; impl Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { /// Number of elements in this vector. @@ -146,30 +149,8 @@ where #[inline] #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] pub const fn splat(value: T) -> Self { - const fn splat_const(value: T) -> Simd - where - T: SimdElement, - LaneCount: SupportedLaneCount, - { - Simd::from_array([value; N]) - } - - fn splat_rt(value: T) -> Simd - where - T: SimdElement, - LaneCount: SupportedLaneCount, - { - // This is preferred over `[value; N]`, since it's explicitly a splat: - // https://github.com/rust-lang/rust/issues/97804 - struct Splat; - impl Swizzle for Splat { - const INDEX: [usize; N] = [0; N]; - } - - Splat::swizzle::(Simd::::from([value])) - } - - core::intrinsics::const_eval_select((value,), splat_const, splat_rt) + // SAFETY: T is a SimdElement, and the item type of Self. + unsafe { core::intrinsics::simd::simd_splat(value) } } /// Returns an array reference containing the entire SIMD vector. @@ -195,7 +176,7 @@ where /// Returns a mutable array reference containing the entire SIMD vector. #[inline] - pub fn as_mut_array(&mut self) -> &mut [T; N] { + pub const fn as_mut_array(&mut self) -> &mut [T; N] { // SAFETY: `Simd` is just an overaligned `[T; N]` with // potential padding at the end, so pointer casting to a // `&mut [T; N]` is safe. @@ -324,7 +305,7 @@ where /// ``` #[inline] #[track_caller] - pub fn copy_to_slice(self, slice: &mut [T]) { + pub const fn copy_to_slice(self, slice: &mut [T]) { assert!( slice.len() >= Self::LEN, "slice length must be at least the number of elements" @@ -465,7 +446,7 @@ where /// value from `or` is passed through. /// /// # Safety - /// Enabled `ptr` elements must be safe to read as if by `std::ptr::read`. + /// Enabled `ptr` elements must be safe to read as if by `core::ptr::read`. #[must_use] #[inline] pub unsafe fn load_select_ptr( @@ -475,12 +456,11 @@ where ) -> Self { // SAFETY: The safety of reading elements through `ptr` is ensured by the caller. unsafe { - core::intrinsics::simd::simd_masked_load::< - _, - _, - _, - { core::intrinsics::simd::SimdAlign::Element }, - >(enable.to_int(), ptr, or) + core::intrinsics::simd::simd_masked_load::<_, _, _, { SimdAlign::Element }>( + enable.to_simd(), + ptr, + or, + ) } } @@ -659,7 +639,7 @@ where or: Self, ) -> Self { // Safety: The caller is responsible for upholding all invariants - unsafe { core::intrinsics::simd::simd_gather(or, source, enable.to_int()) } + unsafe { core::intrinsics::simd::simd_gather(or, source, enable.to_simd()) } } /// Conditionally write contiguous elements to `slice`. The `enable` mask controls @@ -731,12 +711,11 @@ where pub unsafe fn store_select_ptr(self, ptr: *mut T, enable: Mask<::Mask, N>) { // SAFETY: The safety of writing elements through `ptr` is ensured by the caller. unsafe { - core::intrinsics::simd::simd_masked_store::< - _, - _, - _, - { core::intrinsics::simd::SimdAlign::Element }, - >(enable.to_int(), ptr, self) + core::intrinsics::simd::simd_masked_store::<_, _, _, { SimdAlign::Element }>( + enable.to_simd(), + ptr, + self, + ) } } @@ -896,20 +875,14 @@ where #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn scatter_select_ptr(self, dest: Simd<*mut T, N>, enable: Mask) { // Safety: The caller is responsible for upholding all invariants - unsafe { core::intrinsics::simd::simd_scatter(self, dest, enable.to_int()) } + unsafe { core::intrinsics::simd::simd_scatter(self, dest, enable.to_simd()) } } } -impl Copy for Simd -where - LaneCount: SupportedLaneCount, - T: SimdElement, -{ -} +impl Copy for Simd where T: SimdElement {} impl Clone for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -920,7 +893,6 @@ where impl Default for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + Default, { #[inline] @@ -931,7 +903,6 @@ where impl PartialEq for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + PartialEq, { #[inline] @@ -940,7 +911,7 @@ where let mask = unsafe { let tfvec: Simd<::Mask, N> = core::intrinsics::simd::simd_eq(*self, *other); - Mask::from_int_unchecked(tfvec) + Mask::from_simd_unchecked(tfvec) }; // Two vectors are equal if all elements are equal when compared elementwise @@ -954,7 +925,7 @@ where let mask = unsafe { let tfvec: Simd<::Mask, N> = core::intrinsics::simd::simd_ne(*self, *other); - Mask::from_int_unchecked(tfvec) + Mask::from_simd_unchecked(tfvec) }; // Two vectors are non-equal if any elements are non-equal when compared elementwise @@ -965,7 +936,6 @@ where /// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl PartialOrd for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + PartialOrd, { #[inline] @@ -975,17 +945,11 @@ where } } -impl Eq for Simd -where - LaneCount: SupportedLaneCount, - T: SimdElement + Eq, -{ -} +impl Eq for Simd where T: SimdElement + Eq {} /// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl Ord for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + Ord, { #[inline] @@ -997,7 +961,6 @@ where impl core::hash::Hash for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + core::hash::Hash, { #[inline] @@ -1012,7 +975,6 @@ where // array references impl AsRef<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1023,7 +985,6 @@ where impl AsMut<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1035,7 +996,6 @@ where // slice references impl AsRef<[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1046,7 +1006,6 @@ where impl AsMut<[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1058,7 +1017,6 @@ where // vector/array conversion impl From<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1069,7 +1027,6 @@ where impl From> for [T; N] where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1080,7 +1037,6 @@ where impl TryFrom<&[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { type Error = core::array::TryFromSliceError; @@ -1093,7 +1049,6 @@ where impl TryFrom<&mut [T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { type Error = core::array::TryFromSliceError; @@ -1231,10 +1186,7 @@ where } #[inline] -fn lane_indices() -> Simd -where - LaneCount: SupportedLaneCount, -{ +fn lane_indices() -> Simd { #![allow(clippy::needless_range_loop)] let mut index = [0; N]; for i in 0..N { @@ -1246,7 +1198,6 @@ where #[inline] fn mask_up_to(len: usize) -> Mask where - LaneCount: SupportedLaneCount, M: MaskElement, { let index = lane_indices::(); diff --git a/library/portable-simd/crates/core_simd/src/vendor/loongarch64.rs b/library/portable-simd/crates/core_simd/src/vendor/loongarch64.rs index 1290bc166b2b..1f84cdb971ec 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/loongarch64.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/loongarch64.rs @@ -1,31 +1,26 @@ use crate::simd::*; use core::arch::loongarch64::*; -from_transmute! { unsafe u8x16 => v16u8 } -from_transmute! { unsafe u8x32 => v32u8 } -from_transmute! { unsafe i8x16 => v16i8 } -from_transmute! { unsafe i8x32 => v32i8 } +from_transmute! { unsafe u8x16 => m128i } +from_transmute! { unsafe u8x32 => m256i } +from_transmute! { unsafe i8x16 => m128i } +from_transmute! { unsafe i8x32 => m256i } -from_transmute! { unsafe u16x8 => v8u16 } -from_transmute! { unsafe u16x16 => v16u16 } -from_transmute! { unsafe i16x8 => v8i16 } -from_transmute! { unsafe i16x16 => v16i16 } +from_transmute! { unsafe u16x8 => m128i } +from_transmute! { unsafe u16x16 => m256i } +from_transmute! { unsafe i16x8 => m128i } +from_transmute! { unsafe i16x16 => m256i } -from_transmute! { unsafe u32x4 => v4u32 } -from_transmute! { unsafe u32x8 => v8u32 } -from_transmute! { unsafe i32x4 => v4i32 } -from_transmute! { unsafe i32x8 => v8i32 } -from_transmute! { unsafe f32x4 => v4f32 } -from_transmute! { unsafe f32x8 => v8f32 } +from_transmute! { unsafe u32x4 => m128i } +from_transmute! { unsafe u32x8 => m256i } +from_transmute! { unsafe i32x4 => m128i } +from_transmute! { unsafe i32x8 => m256i } +from_transmute! { unsafe f32x4 => m128 } +from_transmute! { unsafe f32x8 => m256 } -from_transmute! { unsafe u64x2 => v2u64 } -from_transmute! { unsafe u64x4 => v4u64 } -from_transmute! { unsafe i64x2 => v2i64 } -from_transmute! { unsafe i64x4 => v4i64 } -from_transmute! { unsafe f64x2 => v2f64 } -from_transmute! { unsafe f64x4 => v4f64 } - -from_transmute! { unsafe usizex2 => v2u64 } -from_transmute! { unsafe usizex4 => v4u64 } -from_transmute! { unsafe isizex2 => v2i64 } -from_transmute! { unsafe isizex4 => v4i64 } +from_transmute! { unsafe u64x2 => m128i } +from_transmute! { unsafe u64x4 => m256i } +from_transmute! { unsafe i64x2 => m128i } +from_transmute! { unsafe i64x4 => m256i } +from_transmute! { unsafe f64x2 => m128d } +from_transmute! { unsafe f64x4 => m256d } diff --git a/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs b/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs index ef3baf885b0f..1fdb2bc86d34 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/wasm32.rs @@ -14,17 +14,3 @@ from_transmute! { unsafe f32x4 => v128 } from_transmute! { unsafe u64x2 => v128 } from_transmute! { unsafe i64x2 => v128 } from_transmute! { unsafe f64x2 => v128 } - -#[cfg(target_pointer_width = "32")] -mod p32 { - use super::*; - from_transmute! { unsafe usizex4 => v128 } - from_transmute! { unsafe isizex4 => v128 } -} - -#[cfg(target_pointer_width = "64")] -mod p64 { - use super::*; - from_transmute! { unsafe usizex2 => v128 } - from_transmute! { unsafe isizex2 => v128 } -} diff --git a/library/portable-simd/crates/core_simd/src/vendor/x86.rs b/library/portable-simd/crates/core_simd/src/vendor/x86.rs index 66aaf90eef59..eae42e6fd0d0 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/x86.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/x86.rs @@ -39,25 +39,3 @@ from_transmute! { unsafe i64x8 => __m512i } from_transmute! { unsafe f64x2 => __m128d } from_transmute! { unsafe f64x4 => __m256d } from_transmute! { unsafe f64x8 => __m512d } - -#[cfg(target_pointer_width = "32")] -mod p32 { - use super::*; - from_transmute! { unsafe usizex4 => __m128i } - from_transmute! { unsafe usizex8 => __m256i } - from_transmute! { unsafe Simd => __m512i } - from_transmute! { unsafe isizex4 => __m128i } - from_transmute! { unsafe isizex8 => __m256i } - from_transmute! { unsafe Simd => __m512i } -} - -#[cfg(target_pointer_width = "64")] -mod p64 { - use super::*; - from_transmute! { unsafe usizex2 => __m128i } - from_transmute! { unsafe usizex4 => __m256i } - from_transmute! { unsafe usizex8 => __m512i } - from_transmute! { unsafe isizex2 => __m128i } - from_transmute! { unsafe isizex4 => __m256i } - from_transmute! { unsafe isizex8 => __m512i } -} diff --git a/library/portable-simd/crates/core_simd/tests/masks.rs b/library/portable-simd/crates/core_simd/tests/masks.rs index 48786d02440b..53fb2367b605 100644 --- a/library/portable-simd/crates/core_simd/tests/masks.rs +++ b/library/portable-simd/crates/core_simd/tests/masks.rs @@ -65,9 +65,9 @@ macro_rules! test_mask_api { fn roundtrip_int_conversion() { let values = [true, false, false, true, false, false, true, false]; let mask = Mask::<$type, 8>::from_array(values); - let int = mask.to_int(); + let int = mask.to_simd(); assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); - assert_eq!(Mask::<$type, 8>::from_int(int), mask); + assert_eq!(Mask::<$type, 8>::from_simd(int), mask); } #[test] diff --git a/library/portable-simd/crates/std_float/src/lib.rs b/library/portable-simd/crates/std_float/src/lib.rs index 148aa5f9f177..b269efc9b1d7 100644 --- a/library/portable-simd/crates/std_float/src/lib.rs +++ b/library/portable-simd/crates/std_float/src/lib.rs @@ -11,7 +11,7 @@ use core_simd::simd; use core::intrinsics::simd as intrinsics; -use simd::{LaneCount, Simd, SupportedLaneCount}; +use simd::Simd; #[cfg(feature = "as_crate")] mod experimental { @@ -66,28 +66,43 @@ pub trait StdFloat: Sealed + Sized { /// Produces a vector where every element has the sine of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn sin(self) -> Self; + fn sin(self) -> Self { + unsafe { intrinsics::simd_fsin(self) } + } /// Produces a vector where every element has the cosine of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn cos(self) -> Self; + fn cos(self) -> Self { + unsafe { intrinsics::simd_fcos(self) } + } /// Produces a vector where every element has the exponential (base e) of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn exp(self) -> Self; + fn exp(self) -> Self { + unsafe { intrinsics::simd_fexp(self) } + } /// Produces a vector where every element has the exponential (base 2) of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn exp2(self) -> Self; + fn exp2(self) -> Self { + unsafe { intrinsics::simd_fexp2(self) } + } /// Produces a vector where every element has the natural logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn ln(self) -> Self; + fn ln(self) -> Self { + unsafe { intrinsics::simd_flog(self) } + } /// Produces a vector where every element has the logarithm with respect to an arbitrary /// in the equivalently-indexed elements in `self` and `base`. @@ -99,13 +114,19 @@ pub trait StdFloat: Sealed + Sized { /// Produces a vector where every element has the base-2 logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn log2(self) -> Self; + fn log2(self) -> Self { + unsafe { intrinsics::simd_flog2(self) } + } /// Produces a vector where every element has the base-10 logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn log10(self) -> Self; + fn log10(self) -> Self { + unsafe { intrinsics::simd_flog10(self) } + } /// Returns the smallest integer greater than or equal to each element. #[must_use = "method returns a new vector and does not mutate the original value"] @@ -140,68 +161,19 @@ pub trait StdFloat: Sealed + Sized { fn fract(self) -> Self; } -impl Sealed for Simd where LaneCount: SupportedLaneCount {} -impl Sealed for Simd where LaneCount: SupportedLaneCount {} +impl Sealed for Simd {} +impl Sealed for Simd {} -macro_rules! impl_float { - { - $($fn:ident: $intrinsic:ident,)* - } => { - impl StdFloat for Simd - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn fract(self) -> Self { - self - self.trunc() - } - - $( - #[inline] - fn $fn(self) -> Self { - unsafe { intrinsics::$intrinsic(self) } - } - )* - } - - impl StdFloat for Simd - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn fract(self) -> Self { - self - self.trunc() - } - - $( - #[inline] - fn $fn(self) -> Self { - // https://github.com/llvm/llvm-project/issues/83729 - #[cfg(target_arch = "aarch64")] - { - let mut ln = Self::splat(0f64); - for i in 0..N { - ln[i] = self[i].$fn() - } - ln - } - - #[cfg(not(target_arch = "aarch64"))] - { - unsafe { intrinsics::$intrinsic(self) } - } - } - )* - } +impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { + self - self.trunc() } } -impl_float! { - sin: simd_fsin, - cos: simd_fcos, - exp: simd_fexp, - exp2: simd_fexp2, - ln: simd_flog, - log2: simd_flog2, - log10: simd_flog10, +impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } } diff --git a/library/portable-simd/crates/std_float/tests/float.rs b/library/portable-simd/crates/std_float/tests/float.rs index c66c968f8c66..c608ba49564e 100644 --- a/library/portable-simd/crates/std_float/tests/float.rs +++ b/library/portable-simd/crates/std_float/tests/float.rs @@ -16,15 +16,33 @@ macro_rules! unary_test { } } -macro_rules! binary_test { +macro_rules! unary_approx_test { { $scalar:tt, $($func:tt),+ } => { test_helpers::test_lanes! { $( fn $func() { - test_helpers::test_binary_elementwise( + test_helpers::test_unary_elementwise_approx( + &core_simd::simd::Simd::<$scalar, LANES>::$func, + &$scalar::$func, + &|_| true, + 8, + ) + } + )* + } + } +} + +macro_rules! binary_approx_test { + { $scalar:tt, $($func:tt),+ } => { + test_helpers::test_lanes! { + $( + fn $func() { + test_helpers::test_binary_elementwise_approx( &core_simd::simd::Simd::<$scalar, LANES>::$func, &$scalar::$func, &|_, _| true, + 16, ) } )* @@ -53,10 +71,13 @@ macro_rules! impl_tests { mod $scalar { use std_float::StdFloat; - unary_test! { $scalar, sqrt, sin, cos, exp, exp2, ln, log2, log10, ceil, floor, round, trunc } - binary_test! { $scalar, log } + unary_test! { $scalar, sqrt, ceil, floor, round, trunc } ternary_test! { $scalar, mul_add } + // https://github.com/rust-lang/miri/issues/3555 + unary_approx_test! { $scalar, sin, cos, exp, exp2, ln, log2, log10 } + binary_approx_test! { $scalar, log } + test_helpers::test_lanes! { fn fract() { test_helpers::test_unary_elementwise_flush_subnormals( diff --git a/library/portable-simd/crates/test_helpers/Cargo.toml b/library/portable-simd/crates/test_helpers/Cargo.toml index a5359b9abc84..408bb04c7aa4 100644 --- a/library/portable-simd/crates/test_helpers/Cargo.toml +++ b/library/portable-simd/crates/test_helpers/Cargo.toml @@ -6,3 +6,4 @@ publish = false [dependencies] proptest = { version = "0.10", default-features = false, features = ["alloc"] } +float-cmp = "0.10" diff --git a/library/portable-simd/crates/test_helpers/src/approxeq.rs b/library/portable-simd/crates/test_helpers/src/approxeq.rs new file mode 100644 index 000000000000..57b43a16bc6f --- /dev/null +++ b/library/portable-simd/crates/test_helpers/src/approxeq.rs @@ -0,0 +1,110 @@ +//! Compare numeric types approximately. + +use float_cmp::Ulps; + +pub trait ApproxEq { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool; + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result; +} + +impl ApproxEq for bool { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +macro_rules! impl_integer_approxeq { + { $($type:ty),* } => { + $( + impl ApproxEq for $type { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self) + } + } + )* + }; +} + +impl_integer_approxeq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize } + +macro_rules! impl_float_approxeq { + { $($type:ty),* } => { + $( + impl ApproxEq for $type { + fn approxeq(&self, other: &Self, ulps: i64) -> bool { + if self.is_nan() && other.is_nan() { + true + } else { + (self.ulps(other) as i64).abs() <= ulps + } + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self.to_bits()) + } + } + )* + }; +} + +impl_float_approxeq! { f32, f64 } + +impl ApproxEq for [T; N] { + fn approxeq(&self, other: &Self, ulps: i64) -> bool { + self.iter() + .zip(other.iter()) + .fold(true, |value, (left, right)| { + value && left.approxeq(right, ulps) + }) + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + #[repr(transparent)] + struct Wrapper<'a, T: ApproxEq>(&'a T); + + impl core::fmt::Debug for Wrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } + } + + f.debug_list() + .entries(self.iter().map(|x| Wrapper(x))) + .finish() + } +} + +#[doc(hidden)] +pub struct ApproxEqWrapper<'a, T>(pub &'a T, pub i64); + +impl PartialEq for ApproxEqWrapper<'_, T> { + fn eq(&self, other: &T) -> bool { + self.0.approxeq(other, self.1) + } +} + +impl core::fmt::Debug for ApproxEqWrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } +} + +#[macro_export] +macro_rules! prop_assert_approxeq { + { $a:expr, $b:expr, $ulps:expr $(,)? } => { + { + use $crate::approxeq::ApproxEqWrapper; + let a = $a; + let b = $b; + proptest::prop_assert_eq!(ApproxEqWrapper(&a, $ulps), b); + } + }; +} diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs index 197c920e11ea..eb3d3f68bc2e 100644 --- a/library/portable-simd/crates/test_helpers/src/lib.rs +++ b/library/portable-simd/crates/test_helpers/src/lib.rs @@ -12,6 +12,9 @@ pub mod wasm; #[macro_use] pub mod biteq; +#[macro_use] +pub mod approxeq; + pub mod subnormals; use subnormals::FlushSubnormals; @@ -185,6 +188,41 @@ pub fn test_unary_elementwise( + fv: &dyn Fn(Vector) -> VectorResult, + fs: &dyn Fn(Scalar) -> ScalarResult, + check: &dyn Fn([Scalar; LANES]) -> bool, + ulps: i64, +) where + Scalar: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + approxeq::ApproxEq + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_1(&|x: [Scalar; LANES]| { + proptest::prop_assume!(check(x)); + let result_1: [ScalarResult; LANES] = fv(x.into()).into(); + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .map(fs) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_approxeq!(result_1, result_2, ulps); + Ok(()) + }); +} + /// Test a unary vector function against a unary scalar function, applied elementwise. /// /// Where subnormals are flushed, use approximate equality. @@ -290,6 +328,44 @@ pub fn test_binary_elementwise< }); } +/// Test a binary vector function against a binary scalar function, applied elementwise. +pub fn test_binary_elementwise_approx< + Scalar1, + Scalar2, + ScalarResult, + Vector1, + Vector2, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector1, Vector2) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, + ulps: i64, +) where + Scalar1: Copy + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + approxeq::ApproxEq + core::fmt::Debug + DefaultStrategy, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into(); + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| fs(x, y)) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_approxeq!(result_1, result_2, ulps); + Ok(()) + }); +} + /// Test a binary vector function against a binary scalar function, applied elementwise. /// /// Where subnormals are flushed, use approximate equality. @@ -528,8 +604,6 @@ macro_rules! test_lanes { use super::*; fn implementation() - where - core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body #[cfg(target_arch = "wasm32")] @@ -628,8 +702,6 @@ macro_rules! test_lanes_panic { use super::*; fn implementation() - where - core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body // test some odd and even non-power-of-2 lengths on miri diff --git a/library/portable-simd/rust-toolchain.toml b/library/portable-simd/rust-toolchain.toml index d17c6d2e8894..639d07df7337 100644 --- a/library/portable-simd/rust-toolchain.toml +++ b/library/portable-simd/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-01-16" +channel = "nightly-2026-01-26" components = ["rustfmt", "clippy", "miri", "rust-src"] diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 8f4a79b389f6..696cd4ee3d88 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -98,7 +98,7 @@ pub(crate) use super::symbol::Symbol; macro_rules! define_client_side { ( - $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* ) => { impl Methods { $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)? { @@ -121,7 +121,7 @@ macro_rules! define_client_side { } } } -with_api!(self, define_client_side); +with_api!(define_client_side, TokenStream, Span, Symbol); struct Bridge<'a> { /// Reusable buffer (only `clear`-ed, never shrunk), primarily @@ -129,7 +129,7 @@ struct Bridge<'a> { cached_buffer: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// Provided globals for this macro expansion. globals: ExpnGlobals, diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index e5133907854b..88c4dd6630b1 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -1,10 +1,12 @@ -//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`. +//! Closure type (equivalent to `&mut dyn FnMut(Buffer) -> Buffer`) that's `repr(C)`. use std::marker::PhantomData; +use super::Buffer; + #[repr(C)] -pub(super) struct Closure<'a, A, R> { - call: unsafe extern "C" fn(*mut Env, A) -> R, +pub(super) struct Closure<'a> { + call: extern "C" fn(*mut Env, Buffer) -> Buffer, env: *mut Env, // Prevent Send and Sync impls. // @@ -14,17 +16,17 @@ pub(super) struct Closure<'a, A, R> { struct Env; -impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { +impl<'a, F: FnMut(Buffer) -> Buffer> From<&'a mut F> for Closure<'a> { fn from(f: &'a mut F) -> Self { - unsafe extern "C" fn call R>(env: *mut Env, arg: A) -> R { + extern "C" fn call Buffer>(env: *mut Env, arg: Buffer) -> Buffer { unsafe { (*(env as *mut _ as *mut F))(arg) } } - Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } + Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } } } -impl<'a, A, R> Closure<'a, A, R> { - pub(super) fn call(&mut self, arg: A) -> R { - unsafe { (self.call)(self.env, arg) } +impl<'a> Closure<'a> { + pub(super) fn call(&mut self, arg: Buffer) -> Buffer { + (self.call)(self.env, arg) } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 244ab7d81b02..603adf720789 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -18,71 +18,67 @@ use crate::{Delimiter, Level}; /// Higher-order macro describing the server RPC API, allowing automatic /// generation of type-safe Rust APIs, both client-side and server-side. /// -/// `with_api!(MySelf, my_macro)` expands to: +/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to: /// ```rust,ignore (pseudo-code) /// my_macro! { -/// fn lit_character(ch: char) -> MySelf::Literal; -/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span; -/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span); +/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream; +/// fn span_debug(span: &MySpan) -> String; /// // ... /// } /// ``` /// -/// The first argument serves to customize the argument/return types, -/// to enable several different usecases: -/// -/// If `MySelf` is just `Self`, then the types are only valid inside -/// a trait or a trait impl, where the trait has associated types -/// for each of the API types. If non-associated types are desired, -/// a module name (`self` in practice) can be used instead of `Self`. +/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`) +/// argument serve to customize the argument/return types that need +/// special handling, to enable several different representations of +/// these types. macro_rules! with_api { - ($S:ident, $m:ident) => { + ($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => { $m! { fn injected_env_var(var: &str) -> Option; fn track_env_var(var: &str, value: Option<&str>); fn track_path(path: &str); - fn literal_from_str(s: &str) -> Result, ()>; - fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>); + fn literal_from_str(s: &str) -> Result, ()>; + fn emit_diagnostic(diagnostic: Diagnostic<$Span>); - fn ts_drop(stream: $S::TokenStream); - fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream; - fn ts_is_empty(stream: &$S::TokenStream) -> bool; - fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>; - fn ts_from_str(src: &str) -> $S::TokenStream; - fn ts_to_string(stream: &$S::TokenStream) -> String; + fn ts_drop(stream: $TokenStream); + fn ts_clone(stream: &$TokenStream) -> $TokenStream; + fn ts_is_empty(stream: &$TokenStream) -> bool; + fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>; + fn ts_from_str(src: &str) -> $TokenStream; + fn ts_to_string(stream: &$TokenStream) -> String; fn ts_from_token_tree( - tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>, - ) -> $S::TokenStream; + tree: TokenTree<$TokenStream, $Span, $Symbol>, + ) -> $TokenStream; fn ts_concat_trees( - base: Option<$S::TokenStream>, - trees: Vec>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + trees: Vec>, + ) -> $TokenStream; fn ts_concat_streams( - base: Option<$S::TokenStream>, - streams: Vec<$S::TokenStream>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + streams: Vec<$TokenStream>, + ) -> $TokenStream; fn ts_into_trees( - stream: $S::TokenStream - ) -> Vec>; + stream: $TokenStream + ) -> Vec>; - fn span_debug(span: $S::Span) -> String; - fn span_parent(span: $S::Span) -> Option<$S::Span>; - fn span_source(span: $S::Span) -> $S::Span; - fn span_byte_range(span: $S::Span) -> Range; - fn span_start(span: $S::Span) -> $S::Span; - fn span_end(span: $S::Span) -> $S::Span; - fn span_line(span: $S::Span) -> usize; - fn span_column(span: $S::Span) -> usize; - fn span_file(span: $S::Span) -> String; - fn span_local_file(span: $S::Span) -> Option; - fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>; - fn span_subspan(span: $S::Span, start: Bound, end: Bound) -> Option<$S::Span>; - fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span; - fn span_source_text(span: $S::Span) -> Option; - fn span_save_span(span: $S::Span) -> usize; - fn span_recover_proc_macro_span(id: usize) -> $S::Span; + fn span_debug(span: $Span) -> String; + fn span_parent(span: $Span) -> Option<$Span>; + fn span_source(span: $Span) -> $Span; + fn span_byte_range(span: $Span) -> Range; + fn span_start(span: $Span) -> $Span; + fn span_end(span: $Span) -> $Span; + fn span_line(span: $Span) -> usize; + fn span_column(span: $Span) -> usize; + fn span_file(span: $Span) -> String; + fn span_local_file(span: $Span) -> Option; + fn span_join(span: $Span, other: $Span) -> Option<$Span>; + fn span_subspan(span: $Span, start: Bound, end: Bound) -> Option<$Span>; + fn span_resolved_at(span: $Span, at: $Span) -> $Span; + fn span_source_text(span: $Span) -> Option; + fn span_save_span(span: $Span) -> usize; + fn span_recover_proc_macro_span(id: usize) -> $Span; - fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>; + fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>; } }; } @@ -126,7 +122,7 @@ pub struct BridgeConfig<'a> { input: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// If 'true', always invoke the default panic hook force_show_panics: bool, @@ -137,7 +133,7 @@ impl !Sync for BridgeConfig<'_> {} macro_rules! declare_tags { ( - $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* ) => { #[allow(non_camel_case_types)] pub(super) enum ApiTags { @@ -146,7 +142,7 @@ macro_rules! declare_tags { rpc_encode_decode!(enum ApiTags { $($method),* }); } } -with_api!(self, declare_tags); +with_api!(declare_tags, __, __, __); /// Helper to wrap associated types to allow trait impl dispatch. /// That is, normally a pair of impls for `T::Foo` and `T::Bar` @@ -173,7 +169,7 @@ impl Mark for Marked { self.value } } -impl<'a, T, M> Mark for &'a Marked { +impl<'a, T> Mark for &'a Marked { type Unmarked = &'a T; fn mark(_: Self::Unmarked) -> Self { unreachable!() @@ -220,6 +216,8 @@ mark_noop! { Delimiter, LitKind, Level, + Bound, + Range, } rpc_encode_decode!( @@ -318,7 +316,7 @@ macro_rules! compound_traits { }; } -compound_traits!( +rpc_encode_decode!( enum Bound { Included(x), Excluded(x), @@ -390,7 +388,7 @@ pub struct Literal { pub span: Span, } -compound_traits!(struct Literal { kind, symbol, suffix, span }); +compound_traits!(struct Literal { kind, symbol, suffix, span }); #[derive(Clone)] pub enum TokenTree { @@ -434,6 +432,6 @@ compound_traits!( struct ExpnGlobals { def_site, call_site, mixed_site } ); -compound_traits!( +rpc_encode_decode!( struct Range { start, end } ); diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 63329c8c0260..7fee8654bc78 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -52,45 +52,37 @@ macro_rules! rpc_encode_decode { } }; (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => { - impl),+)?> Encode for $name $(<$($T),+>)? { - fn encode(self, w: &mut Buffer, s: &mut S) { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_camel_case_types)] - #[repr(u8)] - enum Tag { $($variant),* } + #[allow(non_upper_case_globals, non_camel_case_types)] + const _: () = { + #[repr(u8)] enum Tag { $($variant),* } - match self { - $($name::$variant $(($field))* => { - (Tag::$variant as u8).encode(w, s); - $($field.encode(w, s);)* - })* + $(const $variant: u8 = Tag::$variant as u8;)* + + impl),+)?> Encode for $name $(<$($T),+>)? { + fn encode(self, w: &mut Buffer, s: &mut S) { + match self { + $($name::$variant $(($field))* => { + $variant.encode(w, s); + $($field.encode(w, s);)* + })* + } } } - } - impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> - for $name $(<$($T),+>)? - { - fn decode(r: &mut &'a [u8], s: &mut S) -> Self { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_upper_case_globals, non_camel_case_types)] - mod tag { - #[repr(u8)] enum Tag { $($variant),* } - - $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* - } - - match u8::decode(r, s) { - $(tag::$variant => { - $(let $field = Decode::decode(r, s);)* - $name::$variant $(($field))* - })* - _ => unreachable!(), + impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> + for $name $(<$($T),+>)? + { + fn decode(r: &mut &'a [u8], s: &mut S) -> Self { + match u8::decode(r, s) { + $($variant => { + $(let $field = Decode::decode(r, s);)* + $name::$variant $(($field))* + })* + _ => unreachable!(), + } } } - } + }; } } diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index a53550e0b9e0..1a9951af8c9f 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -38,47 +38,27 @@ use std::mem; -// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement. -macro_rules! define_reify_functions { - ($( - fn $name:ident $(<$($param:ident),*>)? - for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty; - )+) => { - $(pub(super) const fn $name< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty { - // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic - // formatting becomes possible in `const fn`. - const { assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } - - $(extern $abi)? fn wrapper< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >($($arg: $arg_ty),*) -> $ret_ty { - let f = unsafe { - // SAFETY: `F` satisfies all criteria for "out of thin air" - // reconstructability (see module-level doc comment). - mem::MaybeUninit::::uninit().assume_init() - }; - f($($arg),*) - } - let _f_proof = f; - wrapper::< - $($($param,)*)? - F - > - })+ +pub(super) const fn reify_to_extern_c_fn_hrt_bridge< + R, + F: Fn(super::BridgeConfig<'_>) -> R + Copy, +>( + f: F, +) -> extern "C" fn(super::BridgeConfig<'_>) -> R { + // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic + // formatting becomes possible in `const fn`. + const { + assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } -} - -define_reify_functions! { - fn _reify_to_extern_c_fn_unary for extern "C" fn(arg: A) -> R; - - // HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>) - // -> T` but that doesn't work with just `reify_to_extern_c_fn_unary` - // because of the `fn` pointer type being "higher-ranked" (i.e. the - // `for<'a>` binder). - // FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help. - fn reify_to_extern_c_fn_hrt_bridge for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R; + extern "C" fn wrapper) -> R + Copy>( + bridge: super::BridgeConfig<'_>, + ) -> R { + let f = unsafe { + // SAFETY: `F` satisfies all criteria for "out of thin air" + // reconstructability (see module-level doc comment). + mem::conjure_zst::() + }; + f(bridge) + } + let _f_proof = f; + wrapper:: } diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 073ddb554994..1151798fccf4 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -1,7 +1,7 @@ //! Server-side traits. use std::cell::Cell; -use std::marker::PhantomData; +use std::sync::mpsc; use super::*; @@ -53,17 +53,12 @@ impl Decode<'_, '_, HandleStore> for MarkedSpan { } } -struct Dispatcher { - handle_store: HandleStore, - server: S, -} - -macro_rules! define_server_dispatcher_impl { +macro_rules! define_server { ( - $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* ) => { pub trait Server { - type TokenStream: 'static + Clone; + type TokenStream: 'static + Clone + Default; type Span: 'static + Copy + Eq + Hash; type Symbol: 'static; @@ -77,22 +72,21 @@ macro_rules! define_server_dispatcher_impl { $(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?;)* } + } +} +with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol); - // FIXME(eddyb) `pub` only for `ExecutionStrategy` below. - pub trait DispatcherTrait { - // HACK(eddyb) these are here to allow `Self::$name` to work below. - type TokenStream; - type Span; - type Symbol; - - fn dispatch(&mut self, buf: Buffer) -> Buffer; - } - - impl DispatcherTrait for Dispatcher { - type TokenStream = MarkedTokenStream; - type Span = MarkedSpan; - type Symbol = MarkedSymbol; +// FIXME(eddyb) `pub` only for `ExecutionStrategy` below. +pub struct Dispatcher { + handle_store: HandleStore, + server: S, +} +macro_rules! define_dispatcher { + ( + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* + ) => { + impl Dispatcher { fn dispatch(&mut self, mut buf: Buffer) -> Buffer { let Dispatcher { handle_store, server } = self; @@ -102,9 +96,7 @@ macro_rules! define_server_dispatcher_impl { let mut call_method = || { $(let $arg = <$arg_ty>::decode(&mut reader, handle_store).unmark();)* let r = server.$method($($arg),*); - $( - let r: $ret_ty = Mark::mark(r); - )* + $(let r: $ret_ty = Mark::mark(r);)? r }; // HACK(eddyb) don't use `panic::catch_unwind` in a panic. @@ -127,12 +119,15 @@ macro_rules! define_server_dispatcher_impl { } } } -with_api!(Self, define_server_dispatcher_impl); +with_api!(define_dispatcher, MarkedTokenStream, MarkedSpan, MarkedSymbol); +// This trait is currently only implemented and used once, inside of this crate. +// We keep it public to allow implementing more complex execution strategies in +// the future, such as wasm proc-macros. pub trait ExecutionStrategy { fn run_bridge_and_client( &self, - dispatcher: &mut impl DispatcherTrait, + dispatcher: &mut Dispatcher, input: Buffer, run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, force_show_panics: bool, @@ -171,110 +166,78 @@ impl Drop for RunningSameThreadGuard { } } -pub struct MaybeCrossThread

{ - cross_thread: bool, - marker: PhantomData

, +pub struct MaybeCrossThread { + pub cross_thread: bool, } -impl

MaybeCrossThread

{ - pub const fn new(cross_thread: bool) -> Self { - MaybeCrossThread { cross_thread, marker: PhantomData } - } -} +pub const SAME_THREAD: MaybeCrossThread = MaybeCrossThread { cross_thread: false }; +pub const CROSS_THREAD: MaybeCrossThread = MaybeCrossThread { cross_thread: true }; -impl

ExecutionStrategy for MaybeCrossThread

-where - P: MessagePipe + Send + 'static, -{ +impl ExecutionStrategy for MaybeCrossThread { fn run_bridge_and_client( &self, - dispatcher: &mut impl DispatcherTrait, + dispatcher: &mut Dispatcher, input: Buffer, run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, force_show_panics: bool, ) -> Buffer { if self.cross_thread || ALREADY_RUNNING_SAME_THREAD.get() { - >::new().run_bridge_and_client( - dispatcher, - input, - run_client, - force_show_panics, - ) + let (mut server, mut client) = MessagePipe::new(); + + let join_handle = thread::spawn(move || { + let mut dispatch = |b: Buffer| -> Buffer { + client.send(b); + client.recv().expect("server died while client waiting for reply") + }; + + run_client(BridgeConfig { + input, + dispatch: (&mut dispatch).into(), + force_show_panics, + }) + }); + + while let Some(b) = server.recv() { + server.send(dispatcher.dispatch(b)); + } + + join_handle.join().unwrap() } else { - SameThread.run_bridge_and_client(dispatcher, input, run_client, force_show_panics) - } - } -} + let _guard = RunningSameThreadGuard::new(); -pub struct SameThread; - -impl ExecutionStrategy for SameThread { - fn run_bridge_and_client( - &self, - dispatcher: &mut impl DispatcherTrait, - input: Buffer, - run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, - force_show_panics: bool, - ) -> Buffer { - let _guard = RunningSameThreadGuard::new(); - - let mut dispatch = |buf| dispatcher.dispatch(buf); - - run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics }) - } -} - -pub struct CrossThread

(PhantomData

); - -impl

CrossThread

{ - pub const fn new() -> Self { - CrossThread(PhantomData) - } -} - -impl

ExecutionStrategy for CrossThread

-where - P: MessagePipe + Send + 'static, -{ - fn run_bridge_and_client( - &self, - dispatcher: &mut impl DispatcherTrait, - input: Buffer, - run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, - force_show_panics: bool, - ) -> Buffer { - let (mut server, mut client) = P::new(); - - let join_handle = thread::spawn(move || { - let mut dispatch = |b: Buffer| -> Buffer { - client.send(b); - client.recv().expect("server died while client waiting for reply") - }; + let mut dispatch = |buf| dispatcher.dispatch(buf); run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics }) - }); - - while let Some(b) = server.recv() { - server.send(dispatcher.dispatch(b)); } - - join_handle.join().unwrap() } } /// A message pipe used for communicating between server and client threads. -pub trait MessagePipe: Sized { +struct MessagePipe { + tx: mpsc::SyncSender, + rx: mpsc::Receiver, +} + +impl MessagePipe { /// Creates a new pair of endpoints for the message pipe. - fn new() -> (Self, Self); + fn new() -> (Self, Self) { + let (tx1, rx1) = mpsc::sync_channel(1); + let (tx2, rx2) = mpsc::sync_channel(1); + (MessagePipe { tx: tx1, rx: rx2 }, MessagePipe { tx: tx2, rx: rx1 }) + } /// Send a message to the other endpoint of this pipe. - fn send(&mut self, value: T); + fn send(&mut self, value: T) { + self.tx.send(value).unwrap(); + } /// Receive a message from the other endpoint of this pipe. /// /// Returns `None` if the other end of the pipe has been destroyed, and no /// message was received. - fn recv(&mut self) -> Option; + fn recv(&mut self) -> Option { + self.rx.recv().ok() + } } fn run_server< @@ -312,7 +275,6 @@ impl client::Client { ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( @@ -338,7 +300,6 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 95a7ea7d7b3b..e2f39c015bdd 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,6 +27,7 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(extend_one)] +#![feature(mem_conjure_zst)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] @@ -54,7 +55,9 @@ use std::{error, fmt}; pub use diagnostic::{Diagnostic, Level, MultiSpan}; #[unstable(feature = "proc_macro_value", issue = "136652")] pub use rustc_literal_escaper::EscapeError; -use rustc_literal_escaper::{MixedUnit, unescape_byte_str, unescape_c_str, unescape_str}; +use rustc_literal_escaper::{ + MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, +}; #[unstable(feature = "proc_macro_totokens", issue = "130977")] pub use to_tokens::ToTokens; @@ -1451,6 +1454,28 @@ impl Literal { }) } + /// Returns the unescaped character value if the current literal is a byte character literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn byte_character_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Char => { + unescape_byte(symbol).map_err(ConversionErrorKind::FailedToUnescape) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped character value if the current literal is a character literal. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn character_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Char => { + unescape_char(symbol).map_err(ConversionErrorKind::FailedToUnescape) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + /// Returns the unescaped string value if the current literal is a string or a string literal. #[unstable(feature = "proc_macro_value", issue = "136652")] pub fn str_value(&self) -> Result { diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 5c068ad2471a..1f0ced5d0fd0 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -518,8 +518,8 @@ pub struct JoinPathsError { /// /// Returns an [`Err`] (containing an error message) if one of the input /// [`Path`]s contains an invalid character for constructing the `PATH` -/// variable (a double quote on Windows or a colon on Unix), or if the system -/// does not have a `PATH`-like variable (e.g. UEFI or WASI). +/// variable (a double quote on Windows or a colon on Unix or semicolon on +/// UEFI), or if the system does not have a `PATH`-like variable (e.g. WASI). /// /// # Examples /// @@ -728,7 +728,7 @@ pub fn temp_dir() -> PathBuf { /// /// You expected to safely execute the current executable, but you're /// instead executing something completely different. The code you -/// just executed run with your privileges. +/// just executed runs with your privileges. /// /// This sort of behavior has been known to [lead to privilege escalation] when /// used incorrectly. diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 4e4d377ae270..ca910153e526 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1565,7 +1565,7 @@ impl Ord for OsStr { macro_rules! impl_cmp { ($lhs:ty, $rhs: ty) => { #[stable(feature = "cmp_os_str", since = "1.8.0")] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other) @@ -1573,7 +1573,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_os_str", since = "1.8.0")] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self, other) @@ -1581,7 +1581,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_os_str", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$rhs> for $lhs { + impl PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other) @@ -1589,7 +1589,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_os_str", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$lhs> for $rhs { + impl PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self, other) @@ -1599,10 +1599,10 @@ macro_rules! impl_cmp { } impl_cmp!(OsString, OsStr); -impl_cmp!(OsString, &'a OsStr); -impl_cmp!(Cow<'a, OsStr>, OsStr); -impl_cmp!(Cow<'a, OsStr>, &'b OsStr); -impl_cmp!(Cow<'a, OsStr>, OsString); +impl_cmp!(OsString, &OsStr); +impl_cmp!(Cow<'_, OsStr>, OsStr); +impl_cmp!(Cow<'_, OsStr>, &OsStr); +impl_cmp!(Cow<'_, OsStr>, OsString); #[stable(feature = "rust1", since = "1.0.0")] impl Hash for OsStr { diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index a24baad61501..cf6f9594c002 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -277,6 +277,7 @@ pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various timestamps on a file. #[derive(Copy, Clone, Debug, Default)] #[stable(feature = "file_set_times", since = "1.75.0")] +#[must_use = "must be applied to a file via `File::set_times` to have any effect"] pub struct FileTimes(fs_imp::FileTimes); /// Representation of the various permissions on a file. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 6d0b261dcadc..42f3ccc340b2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2301,6 +2301,57 @@ fn test_fs_set_times() { } } +#[test] +fn test_fs_set_times_on_dir() { + #[cfg(target_vendor = "apple")] + use crate::os::darwin::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + let dir_path = tmp.join("testdir"); + fs::create_dir(&dir_path).unwrap(); + + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + + #[cfg(any(windows, target_vendor = "apple"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_vendor = "apple"))] + { + times = times.set_created(created); + } + + match fs::set_times(&dir_path, times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting directory times: {e:?}"), + Ok(_) => {} + } + + let metadata = fs::metadata(&dir_path).unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_vendor = "apple"))] + { + assert_eq!(metadata.created().unwrap(), created); + } +} + #[test] fn test_fs_set_times_follows_symlink() { #[cfg(target_vendor = "apple")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b213fa749177..03e3da013cd2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -260,6 +260,7 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] +#![cfg_attr(all(test, target_os = "uefi"), feature(uefi_std))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] // @@ -314,6 +315,7 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] +#![feature(uint_carryless_mul)] // tidy-alphabetical-end // // Library features (core): @@ -393,7 +395,6 @@ // // Only for re-exporting: // tidy-alphabetical-start -#![feature(assert_matches)] #![feature(async_iterator)] #![feature(c_variadic)] #![feature(cfg_accessible)] @@ -725,7 +726,7 @@ pub use core::{ assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented, unreachable, write, writeln, }; -#[unstable(feature = "assert_matches", issue = "82775")] +#[stable(feature = "assert_matches", since = "CURRENT_RUSTC_VERSION")] pub use core::{assert_matches, debug_assert_matches}; // Re-export unstable derive macro defined through core. diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs index 6f1fd2975b71..2c8898a6aa86 100644 --- a/library/std/src/num/f128.rs +++ b/library/std/src/num/f128.rs @@ -16,6 +16,7 @@ use crate::intrinsics; use crate::sys::cmath; #[cfg(not(test))] +#[doc(test(attr(allow(unused_features))))] impl f128 { /// Raises a number to a floating point power. /// diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs index 20d0b4e1e552..318a0b3af86a 100644 --- a/library/std/src/num/f16.rs +++ b/library/std/src/num/f16.rs @@ -916,7 +916,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(float_gamma)] /// # #[cfg(not(miri))] /// # #[cfg(target_has_reliable_f16_math)] { /// @@ -952,7 +951,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(float_gamma)] /// # #[cfg(not(miri))] /// # #[cfg(target_has_reliable_f16_math)] { /// @@ -988,7 +986,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(float_erf)] /// # #[cfg(not(miri))] /// # #[cfg(target_has_reliable_f16_math)] { /// /// The error function relates what percent of a normal distribution lies @@ -1028,7 +1025,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(float_erf)] /// # #[cfg(not(miri))] /// # #[cfg(target_has_reliable_f16_math)] { /// let x: f16 = 0.123; diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 95cf4932e6e2..473d7ae3e2ae 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -16,6 +16,9 @@ mod owned; #[cfg(not(target_os = "trusty"))] mod net; +// Implementation of stdio file descriptor constants. +mod stdio; + #[cfg(test)] mod tests; @@ -24,3 +27,5 @@ mod tests; pub use owned::*; #[stable(feature = "os_fd", since = "1.66.0")] pub use raw::*; +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub use stdio::*; diff --git a/library/std/src/os/fd/stdio.rs b/library/std/src/os/fd/stdio.rs new file mode 100644 index 000000000000..c50cbd39849b --- /dev/null +++ b/library/std/src/os/fd/stdio.rs @@ -0,0 +1,53 @@ +use super::BorrowedFd; + +/// The file descriptor for the standard input stream of the current process. +/// +/// See [`io::stdin()`][`crate::io::stdin`] for the higher level handle, which should be preferred +/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats. +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDIN: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(0) }; + +/// The file descriptor for the standard output stream of the current process. +/// +/// See [`io::stdout()`][`crate::io::stdout`] for the higher level handle, which should be preferred +/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats. In +/// addition to the issues discussed there, note that [`Stdout`][`crate::io::Stdout`] is buffered by +/// default, and writing to the file descriptor will bypass this buffer. +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDOUT: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(1) }; + +/// The file descriptor for the standard error stream of the current process. +/// +/// See [`io::stderr()`][`crate::io::stderr`] for the higher level handle, which should be preferred +/// whenever possible. However, there are situations where touching the `std::io` handles (or most +/// other parts of the standard library) risks deadlocks or other subtle bugs. For example: +/// +/// - Global allocators must be careful to [avoid reentrancy][global-alloc-reentrancy], and the +/// `std::io` handles may allocate memory on (some) accesses. +/// - Signal handlers must be *async-signal-safe*, which rules out panicking, taking locks (may +/// deadlock if the signal handler interrupted a thread holding that lock), allocating memory, or +/// anything else that is not explicitly declared async-signal-safe. +/// - `CommandExt::pre_exec` callbacks can safely panic (with some limitations), but otherwise must +/// abide by similar limitations as signal handlers. In particular, at the time these callbacks +/// run, the stdio file descriptors have already been replaced, but the locks protecting the +/// `std::io` handles may be permanently locked if another thread held the lock at `fork()` time. +/// +/// In these and similar cases, direct access to the file descriptor may be required. However, in +/// most cases, using the `std::io` handles and accessing the file descriptor via the `AsFd` +/// implementations is preferable, as it enables cooperation with the standard library's locking and +/// buffering. +/// +/// # I/O safety +/// +/// This is a `BorrowedFd<'static>` because the standard input/output/error streams are shared +/// resources that must remain available for the lifetime of the process. This is only true when +/// linking `std`, and may not always hold for [code running before `main()`][before-after-main] or +/// in `no_std` environments. It is [unsound][io-safety] to close these file descriptors. Safe +/// patterns for changing these file descriptors are available on Unix via the `StdioExt` extension +/// trait. +/// +/// [before-after-main]: ../../../std/index.html#use-before-and-after-main +/// [io-safety]: ../../../std/io/index.html#io-safety +/// [global-alloc-reentrancy]: ../../../std/alloc/trait.GlobalAlloc.html#re-entrance +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDERR: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(2) }; diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs index ab5406e605c6..82e3fc9775cb 100644 --- a/library/std/src/os/uefi/env.rs +++ b/library/std/src/os/uefi/env.rs @@ -4,13 +4,25 @@ use crate::ffi::c_void; use crate::ptr::NonNull; -use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, Ordering}; +use crate::sync::atomic::Ordering; -static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); -static IMAGE_HANDLE: Atomic<*mut c_void> = 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: Atomic = AtomicBool::new(false); +#[doc(hidden)] +#[cfg(not(test))] +pub mod globals { + use crate::ffi::c_void; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr}; + + pub static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); + pub static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); + // Flag to check if BootServices are still valid. + // Start with assuming that they are not available + pub static BOOT_SERVICES_FLAG: Atomic = AtomicBool::new(false); +} + +#[cfg(not(test))] +use globals::*; +#[cfg(test)] +use realstd::os::uefi::env::globals::*; /// Initializes the global System Table and Image Handle pointers. /// diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index f452403ee842..53c33d17a9f6 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -29,6 +29,8 @@ pub mod ffi; pub mod fs; pub mod io; +#[unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +pub mod net; pub mod process; pub mod raw; pub mod thread; diff --git a/library/std/src/os/windows/net/addr.rs b/library/std/src/os/windows/net/addr.rs new file mode 100644 index 000000000000..ef2263edcf61 --- /dev/null +++ b/library/std/src/os/windows/net/addr.rs @@ -0,0 +1,173 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::bstr::ByteStr; +use crate::ffi::OsStr; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{AF_UNIX, SOCKADDR, SOCKADDR_UN}; +use crate::sys::cvt_nz; +use crate::{fmt, io, mem, ptr}; + +#[cfg(not(doc))] +pub fn sockaddr_un(path: &Path) -> io::Result<(SOCKADDR_UN, usize)> { + // SAFETY: All zeros is a valid representation for `sockaddr_un`. + let mut addr: SOCKADDR_UN = unsafe { mem::zeroed() }; + addr.sun_family = AF_UNIX; + + // path to UTF-8 bytes + let bytes = path + .to_str() + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "path must be valid UTF-8"))? + .as_bytes(); + if bytes.len() >= addr.sun_path.len() { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "path too long")); + } + // SAFETY: `bytes` and `addr.sun_path` are not overlapping and + // both point to valid memory. + // NOTE: We zeroed the memory above, so the path is already null + // terminated. + unsafe { + ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len()) + }; + + let len = SUN_PATH_OFFSET + bytes.len() + 1; + Ok((addr, len)) +} +#[cfg(not(doc))] +const SUN_PATH_OFFSET: usize = mem::offset_of!(SOCKADDR_UN, sun_path); +pub struct SocketAddr { + #[cfg(not(doc))] + pub(super) addr: SOCKADDR_UN, + pub(super) len: u32, // Use u32 here as same as libc::socklen_t +} +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.address() { + AddressKind::Unnamed => write!(fmt, "(unnamed)"), + AddressKind::Abstract(name) => write!(fmt, "{name:?} (abstract)"), + AddressKind::Pathname(path) => write!(fmt, "{path:?} (pathname)"), + } + } +} + +impl SocketAddr { + #[cfg(not(doc))] + pub(super) fn new(f: F) -> io::Result + where + F: FnOnce(*mut SOCKADDR, *mut i32) -> i32, + { + unsafe { + let mut addr: SOCKADDR_UN = mem::zeroed(); + let mut len = mem::size_of::() as i32; + cvt_nz(f(&raw mut addr as *mut _, &mut len))?; + SocketAddr::from_parts(addr, len) + } + } + #[cfg(not(doc))] + pub(super) fn from_parts(addr: SOCKADDR_UN, len: i32) -> io::Result { + if addr.sun_family != AF_UNIX { + Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address family")) + } else if len < SUN_PATH_OFFSET as _ || len > mem::size_of::() as _ { + Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address length")) + } else { + Ok(SocketAddr { addr, len: len as _ }) + } + } + + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// use std::path::Path; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixListener::bind("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// Ok(()) + /// } + /// ``` + pub fn as_pathname(&self) -> Option<&Path> { + if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } + } + + /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path. + /// + /// # Errors + /// + /// Returns an error if the path is longer than `SUN_LEN` or if it contains + /// NULL bytes. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::SocketAddr; + /// use std::path::Path; + /// + /// # fn main() -> std::io::Result<()> { + /// let address = SocketAddr::from_pathname("/path/to/socket")?; + /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); + /// # Ok(()) + /// # } + /// ``` + /// + /// Creating a `SocketAddr` with a NULL byte results in an error. + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::SocketAddr; + /// + /// assert!(SocketAddr::from_pathname("/path/with/\0/bytes").is_err()); + /// ``` + pub fn from_pathname

(path: P) -> io::Result + where + P: AsRef, + { + sockaddr_un(path.as_ref()).map(|(addr, len)| SocketAddr { addr, len: len as _ }) + } + fn address(&self) -> AddressKind<'_> { + let len = self.len as usize - SUN_PATH_OFFSET; + let path = unsafe { mem::transmute::<&[i8], &[u8]>(&self.addr.sun_path) }; + + if len == 0 { + AddressKind::Unnamed + } else if self.addr.sun_path[0] == 0 { + AddressKind::Abstract(ByteStr::from_bytes(&path[1..len])) + } else { + AddressKind::Pathname(unsafe { + OsStr::from_encoded_bytes_unchecked(&path[..len - 1]).as_ref() + }) + } + } + + /// Returns `true` if the address is unnamed. + /// + /// # Examples + /// + /// A named address: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixListener::bind("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// Ok(()) + /// } + /// ``` + pub fn is_unnamed(&self) -> bool { + matches!(self.address(), AddressKind::Unnamed) + } +} +enum AddressKind<'a> { + Unnamed, + Pathname(&'a Path), + Abstract(&'a ByteStr), +} diff --git a/library/std/src/os/windows/net/listener.rs b/library/std/src/os/windows/net/listener.rs new file mode 100644 index 000000000000..345cfe8d22ba --- /dev/null +++ b/library/std/src/os/windows/net/listener.rs @@ -0,0 +1,344 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +use crate::os::windows::net::{SocketAddr, UnixStream}; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{AF_UNIX, SOCK_STREAM, SOCKADDR_UN, bind, getsockname, listen}; +use crate::sys::net::Socket; +#[cfg(not(doc))] +use crate::sys::winsock::startup; +use crate::sys::{AsInner, cvt_nz}; +use crate::{fmt, io}; + +/// A structure representing a Unix domain socket server. +/// +/// Under Windows, it will only work starting from Windows 10 17063. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::thread; +/// use std::os::windows::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// fn main() -> std::io::Result<()> { +/// let listener = UnixListener::bind("/path/to/the/socket")?; +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// Ok(()) +/// } +/// ``` +pub struct UnixListener(Socket); + +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("sock", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return + /// } + /// }; + /// ``` + pub fn bind>(path: P) -> io::Result { + let socket_addr = SocketAddr::from_pathname(path)?; + Self::bind_addr(&socket_addr) + } + + /// Creates a new `UnixListener` bound to the specified [`socket address`]. + /// + /// [`socket address`]: crate::os::windows::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::{UnixListener}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener1 = UnixListener::bind("path/to/socket")?; + /// let addr = listener1.local_addr()?; + /// + /// let listener2 = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {err:?}"); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + startup(); + let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?; + unsafe { + cvt_nz(bind(inner.as_raw(), &raw const socket_addr.addr as _, socket_addr.len as _))?; + cvt_nz(listen(inner.as_raw(), 128))?; + } + Ok(UnixListener(inner)) + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: crate::os::windows::net::UnixStream + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {addr:?}"), + /// Err(e) => println!("accept function failed: {e:?}"), + /// } + /// Ok(()) + /// } + /// ``` + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + let mut storage = SOCKADDR_UN::default(); + let mut len = size_of::() as _; + let inner = self.0.accept(&raw mut storage as *mut _, &raw mut len)?; + let addr = SocketAddr::from_parts(storage, len)?; + Ok((UnixStream(inner), addr)) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// Ok(()) + /// } + /// ``` + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) }) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// Ok(()) + /// } + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// This will result in the `accept` operation becoming nonblocking, + /// i.e., immediately returning from their calls. If the IO operation is + /// successful, `Ok` is returned and no further action is required. If the + /// IO operation could not be completed and needs to be retried, an error + /// with kind [`io::ErrorKind::WouldBlock`] is returned. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// Ok(()) + /// } + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/tmp/sock")?; + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {err:?}"); + /// } + /// Ok(()) + /// } + /// ``` + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::thread; + /// use std::os::windows::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// Ok(()) + /// } + /// ``` + pub fn incoming(&self) -> Incoming<'_> { + Incoming { listener: self } + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::thread; +/// use std::os::windows::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// fn main() -> std::io::Result<()> { +/// let listener = UnixListener::bind("/path/to/the/socket")?; +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// Ok(()) +/// } +/// ``` +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + +impl AsRawSocket for UnixListener { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.0.as_raw_socket() + } +} + +impl FromRawSocket for UnixListener { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> Self { + UnixListener(unsafe { Socket::from_raw_socket(sock) }) + } +} + +impl IntoRawSocket for UnixListener { + #[inline] + fn into_raw_socket(self) -> RawSocket { + self.0.into_raw_socket() + } +} + +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} diff --git a/library/std/src/os/windows/net/mod.rs b/library/std/src/os/windows/net/mod.rs new file mode 100644 index 000000000000..6b3f062b8ab4 --- /dev/null +++ b/library/std/src/os/windows/net/mod.rs @@ -0,0 +1,6 @@ +mod addr; +mod listener; +mod stream; +pub use addr::*; +pub use listener::*; +pub use stream::*; diff --git a/library/std/src/os/windows/net/stream.rs b/library/std/src/os/windows/net/stream.rs new file mode 100644 index 000000000000..f2d0f7c09e9f --- /dev/null +++ b/library/std/src/os/windows/net/stream.rs @@ -0,0 +1,423 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::net::Shutdown; +use crate::os::windows::io::{ + AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, RawSocket, +}; +use crate::os::windows::net::SocketAddr; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{ + AF_UNIX, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_STREAM, connect, getpeername, getsockname, +}; +use crate::sys::net::Socket; +#[cfg(not(doc))] +use crate::sys::winsock::startup; +use crate::sys::{AsInner, cvt_nz}; +use crate::time::Duration; +use crate::{fmt, io}; +/// A Unix stream socket. +/// +/// Under Windows, it will only work starting from Windows 10 17063. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::os::windows::net::UnixStream; +/// use std::io::prelude::*; +/// +/// fn main() -> std::io::Result<()> { +/// let mut stream = UnixStream::connect("/path/to/my/socket")?; +/// stream.write_all(b"hello world")?; +/// let mut response = String::new(); +/// stream.read_to_string(&mut response)?; +/// println!("{response}"); +/// Ok(()) +/// } +/// ``` +pub struct UnixStream(pub(super) Socket); +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("sock", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return + /// } + /// }; + /// ``` + pub fn connect>(path: P) -> io::Result { + let socket_addr = SocketAddr::from_pathname(path)?; + Self::connect_addr(&socket_addr) + } + + /// Connects to the socket specified by [`address`]. + /// + /// [`address`]: crate::os::windows::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::{UnixListener, UnixStream}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let addr = listener.local_addr()?; + /// + /// let sock = match UnixStream::connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ```` + pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { + startup(); + let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?; + unsafe { + cvt_nz(connect( + inner.as_raw(), + &raw const socket_addr.addr as *const _, + socket_addr.len as _, + ))?; + } + Ok(UnixStream(inner)) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// Ok(()) + /// } + /// ``` + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) }) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// Ok(()) + /// } + /// ``` + pub fn peer_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getpeername(self.0.as_raw(), addr, len) }) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0))); + /// Ok(()) + /// } + /// ``` + pub fn read_timeout(&self) -> io::Result> { + self.0.timeout(SO_RCVTIMEO) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// Ok(()) + /// } + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`read`]: io::Read::read + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// Ok(()) + /// } + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::io; + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + /// Ok(()) + /// } + /// ``` + pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { + self.0.set_timeout(dur, SO_RCVTIMEO) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`read`]: io::Read::read + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("Couldn't set write timeout"); + /// Ok(()) + /// } + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::io; + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + /// Ok(()) + /// } + /// ``` + pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { + self.0.set_timeout(dur, SO_SNDTIMEO) + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::net::Shutdown; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// Ok(()) + /// } + /// ``` + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + self.0.shutdown(how) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {err:?}"); + /// } + /// Ok(()) + /// } + /// ``` + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// Ok(()) + /// } + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0))); + /// Ok(()) + /// } + /// ``` + pub fn write_timeout(&self) -> io::Result> { + self.0.timeout(SO_SNDTIMEO) + } +} + +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &*self, buf) + } +} + +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } +} + +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &*self, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &*self) + } +} +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.write_vectored(&[io::IoSlice::new(buf)]) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} + +impl AsSocket for UnixStream { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + self.0.as_socket() + } +} + +impl AsRawSocket for UnixStream { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.0.as_raw_socket() + } +} + +impl FromRawSocket for UnixStream { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> Self { + unsafe { UnixStream(Socket::from_raw_socket(sock)) } + } +} + +impl IntoRawSocket for UnixStream { + fn into_raw_socket(self) -> RawSocket { + self.0.into_raw_socket() + } +} diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 25bd7005b994..bf27df7b0428 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -19,6 +19,20 @@ //! matter the platform or filesystem. An exception to this is made for Windows //! drive letters. //! +//! ## Path normalization +//! +//! Several methods in this module perform basic path normalization by disregarding +//! repeated separators, non-leading `.` components, and trailing separators. These include: +//! - Methods for iteration, such as [`Path::components`] and [`Path::iter`] +//! - Methods for inspection, such as [`Path::has_root`] +//! - Comparisons using [`PartialEq`], [`PartialOrd`], and [`Ord`] +//! +//! [`Path::join`] and [`PathBuf::push`] also disregard trailing slashes. +//! +// FIXME(normalize_lexically): mention normalize_lexically once stable +//! These methods **do not** resolve `..` components or symlinks. For full normalization +//! including `..` resolution, use [`Path::canonicalize`] (which does access the filesystem). +//! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building @@ -3827,9 +3841,9 @@ impl<'a> IntoIterator for &'a Path { } macro_rules! impl_cmp { - (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { + ($lhs:ty, $rhs: ty) => { #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<$($life),*> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other) @@ -3837,7 +3851,7 @@ macro_rules! impl_cmp { } #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<$($life),*> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self, other) @@ -3845,7 +3859,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialOrd<$rhs> for $lhs { + impl PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other) @@ -3853,7 +3867,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialOrd<$lhs> for $rhs { + impl PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self, other) @@ -3862,16 +3876,16 @@ macro_rules! impl_cmp { }; } -impl_cmp!(<> PathBuf, Path); -impl_cmp!(<'a> PathBuf, &'a Path); -impl_cmp!(<'a> Cow<'a, Path>, Path); -impl_cmp!(<'a, 'b> Cow<'a, Path>, &'b Path); -impl_cmp!(<'a> Cow<'a, Path>, PathBuf); +impl_cmp!(PathBuf, Path); +impl_cmp!(PathBuf, &Path); +impl_cmp!(Cow<'_, Path>, Path); +impl_cmp!(Cow<'_, Path>, &Path); +impl_cmp!(Cow<'_, Path>, PathBuf); macro_rules! impl_cmp_os_str { - (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { + ($lhs:ty, $rhs: ty) => { #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialEq<$rhs> for $lhs { + impl PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other.as_ref()) @@ -3879,7 +3893,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialEq<$lhs> for $rhs { + impl PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self.as_ref(), other) @@ -3887,7 +3901,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialOrd<$rhs> for $lhs { + impl PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other.as_ref()) @@ -3895,7 +3909,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<$($life),*> PartialOrd<$lhs> for $rhs { + impl PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self.as_ref(), other) @@ -3904,20 +3918,20 @@ macro_rules! impl_cmp_os_str { }; } -impl_cmp_os_str!(<> PathBuf, OsStr); -impl_cmp_os_str!(<'a> PathBuf, &'a OsStr); -impl_cmp_os_str!(<'a> PathBuf, Cow<'a, OsStr>); -impl_cmp_os_str!(<> PathBuf, OsString); -impl_cmp_os_str!(<> Path, OsStr); -impl_cmp_os_str!(<'a> Path, &'a OsStr); -impl_cmp_os_str!(<'a> Path, Cow<'a, OsStr>); -impl_cmp_os_str!(<> Path, OsString); -impl_cmp_os_str!(<'a> &'a Path, OsStr); -impl_cmp_os_str!(<'a, 'b> &'a Path, Cow<'b, OsStr>); -impl_cmp_os_str!(<'a> &'a Path, OsString); -impl_cmp_os_str!(<'a> Cow<'a, Path>, OsStr); -impl_cmp_os_str!(<'a, 'b> Cow<'a, Path>, &'b OsStr); -impl_cmp_os_str!(<'a> Cow<'a, Path>, OsString); +impl_cmp_os_str!(PathBuf, OsStr); +impl_cmp_os_str!(PathBuf, &OsStr); +impl_cmp_os_str!(PathBuf, Cow<'_, OsStr>); +impl_cmp_os_str!(PathBuf, OsString); +impl_cmp_os_str!(Path, OsStr); +impl_cmp_os_str!(Path, &OsStr); +impl_cmp_os_str!(Path, Cow<'_, OsStr>); +impl_cmp_os_str!(Path, OsString); +impl_cmp_os_str!(&Path, OsStr); +impl_cmp_os_str!(&Path, Cow<'_, OsStr>); +impl_cmp_os_str!(&Path, OsString); +impl_cmp_os_str!(Cow<'_, Path>, OsStr); +impl_cmp_os_str!(Cow<'_, Path>, &OsStr); +impl_cmp_os_str!(Cow<'_, Path>, OsString); #[stable(since = "1.7.0", feature = "strip_prefix")] impl fmt::Display for StripPrefixError { diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index acfeb96900cc..c01ee17eecda 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -56,24 +56,36 @@ use crate::sys::sync as sys; /// # Examples /// /// ``` -/// use std::sync::RwLock; +/// use std::sync::{Arc, RwLock}; +/// use std::thread; +/// use std::time::Duration; /// -/// let lock = RwLock::new(5); +/// let data = Arc::new(RwLock::new(5)); /// -/// // many reader locks can be held at once -/// { -/// let r1 = lock.read().unwrap(); -/// let r2 = lock.read().unwrap(); -/// assert_eq!(*r1, 5); -/// assert_eq!(*r2, 5); -/// } // read locks are dropped at this point +/// // Multiple readers can access in parallel. +/// for i in 0..3 { +/// let lock_clone = Arc::clone(&data); /// -/// // only one write lock may be held, however -/// { -/// let mut w = lock.write().unwrap(); -/// *w += 1; -/// assert_eq!(*w, 6); -/// } // write lock is dropped here +/// thread::spawn(move || { +/// let value = lock_clone.read().unwrap(); +/// +/// println!("Reader {}: Read value {}, now holding lock...", i, *value); +/// +/// // Simulating a long read operation +/// thread::sleep(Duration::from_secs(1)); +/// +/// println!("Reader {}: Dropping lock.", i); +/// // Read lock unlocked when going out of scope. +/// }); +/// } +/// +/// thread::sleep(Duration::from_millis(100)); // Wait for readers to start +/// +/// // While all readers can proceed, a call to .write() has to wait for +// // current active reader locks. +/// let mut writable_data = data.write().unwrap(); +/// println!("Writer proceeds..."); +/// *writable_data += 1; /// ``` /// /// [`Mutex`]: super::Mutex @@ -370,7 +382,8 @@ impl RwLock { /// /// # Panics /// - /// This function might panic when called if the lock is already held by the current thread. + /// This function might panic when called if the lock is already held by the current thread + /// in read or write mode. /// /// # Examples /// @@ -467,7 +480,8 @@ impl RwLock { /// /// # Panics /// - /// This function might panic when called if the lock is already held by the current thread. + /// This function might panic when called if the lock is already held by the current thread + /// in read or write mode. /// /// # Examples /// diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs index af16a02642a4..bc2aed423179 100644 --- a/library/std/src/sys/env/uefi.rs +++ b/library/std/src/sys/env/uefi.rs @@ -43,7 +43,20 @@ mod uefi_env { pub(crate) fn unset(key: &OsStr) -> io::Result<()> { let mut key_ptr = helpers::os_string_to_raw(key) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; - unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } + let r = unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }; + + // The UEFI Shell spec only lists `EFI_SUCCESS` as a possible return value for + // `SetEnv`, but the edk2 implementation can return errors. Allow most of these + // errors to bubble up to the caller, but ignore `NotFound` errors; deleting a + // nonexistent variable is not listed as an error condition of + // `std::env::remove_var`. + if let Err(err) = &r + && err.kind() == io::ErrorKind::NotFound + { + Ok(()) + } else { + r + } } pub(crate) fn get_all() -> io::Result> { diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 3ca84db0f47f..7db474544f04 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -2132,9 +2132,6 @@ pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { // Android has `linkat` on newer versions, but we happen to know // `link` always has the correct behavior, so it's here as well. target_os = "android", - // wasi-sdk-29-and-prior have a buggy `linkat` so use `link` instead - // until wasi-sdk is updated (see WebAssembly/wasi-libc#690) - target_os = "wasi", // Other misc platforms target_os = "horizon", target_os = "vita", diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index fc8aec2f3f7c..74854cdeb498 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1556,7 +1556,7 @@ pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> { pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> { let mut opts = OpenOptions::new(); - opts.write(true); + opts.access_mode(c::FILE_WRITE_ATTRIBUTES); opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); let file = File::open_native(p, &opts)?; file.set_times(times) @@ -1564,7 +1564,7 @@ pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> { pub fn set_times_nofollow(p: &WCStr, times: FileTimes) -> io::Result<()> { let mut opts = OpenOptions::new(); - opts.write(true); + opts.access_mode(c::FILE_WRITE_ATTRIBUTES); // `FILE_FLAG_OPEN_REPARSE_POINT` for no_follow behavior opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); let file = File::open_native(p, &opts)?; diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 178f7f506341..5b9785c8371e 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -5,10 +5,13 @@ use super::{helpers, unsupported_err}; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::uefi; +use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::path::{self, PathBuf}; use crate::ptr::NonNull; use crate::{fmt, io}; +const PATHS_SEP: u16 = b';' as u16; + pub fn getcwd() -> io::Result { match helpers::open_shell() { Some(shell) => { @@ -54,17 +57,34 @@ impl<'a> Iterator for SplitPaths<'a> { #[derive(Debug)] pub struct JoinPathsError; -pub fn join_paths(_paths: I) -> Result +// UEFI Shell Path variable is defined in Section 3.6.1 +// [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf). +pub fn join_paths(paths: I) -> Result where I: Iterator, T: AsRef, { - Err(JoinPathsError) + let mut joined = Vec::new(); + + for (i, path) in paths.enumerate() { + if i > 0 { + joined.push(PATHS_SEP) + } + + let v = path.as_ref().encode_wide().collect::>(); + if v.contains(&PATHS_SEP) { + return Err(JoinPathsError); + } + + joined.extend_from_slice(&v); + } + + Ok(OsString::from_wide(&joined)) } impl fmt::Display for JoinPathsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) + "path segment contains `;`".fmt(f) } } diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 6127bb98f80e..0fbf37fda7fb 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -169,15 +169,15 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { pub const SIG_DFL: u8 = 3; } - let (sigpipe_attr_specified, handler) = match sigpipe { + let (on_broken_pipe_used, handler) = match sigpipe { sigpipe::DEFAULT => (false, Some(libc::SIG_IGN)), sigpipe::INHERIT => (true, None), sigpipe::SIG_IGN => (true, Some(libc::SIG_IGN)), sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)), _ => unreachable!(), }; - if sigpipe_attr_specified { - ON_BROKEN_PIPE_FLAG_USED.store(true, crate::sync::atomic::Ordering::Relaxed); + if on_broken_pipe_used { + ON_BROKEN_PIPE_USED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); @@ -199,7 +199,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vxworks", target_os = "vita", )))] -static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic = +static ON_BROKEN_PIPE_USED: crate::sync::atomic::Atomic = crate::sync::atomic::AtomicBool::new(false); #[cfg(not(any( @@ -211,8 +211,8 @@ static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic = target_os = "vita", target_os = "nuttx", )))] -pub(crate) fn on_broken_pipe_flag_used() -> bool { - ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed) +pub(crate) fn on_broken_pipe_used() -> bool { + ON_BROKEN_PIPE_USED.load(crate::sync::atomic::Ordering::Relaxed) } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 17e3cdbecd5c..0cd915261471 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -233,6 +233,11 @@ pub fn cvt(i: I) -> io::Result { if i.is_zero() { Err(io::Error::last_os_error()) } else { Ok(i) } } +#[allow(dead_code)] +pub fn cvt_nz(i: I) -> crate::io::Result<()> { + if i.is_zero() { Ok(()) } else { Err(crate::io::Error::last_os_error()) } +} + pub fn dur2timeout(dur: Duration) -> u32 { // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the // timeouts in windows APIs are typically u32 milliseconds. To translate, we diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 62d6e0581e6c..82ff94fb1e03 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -356,7 +356,7 @@ impl Command { // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // // -Zon-broken-pipe is an opportunity to change the default here. - if !crate::sys::pal::on_broken_pipe_flag_used() { + if !crate::sys::pal::on_broken_pipe_used() { #[cfg(target_os = "android")] // see issue #88585 { let mut action: libc::sigaction = mem::zeroed(); @@ -455,7 +455,7 @@ impl Command { use core::sync::atomic::{Atomic, AtomicU8, Ordering}; use crate::mem::MaybeUninit; - use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; + use crate::sys::{self, cvt_nz, on_broken_pipe_used}; if self.get_gid().is_some() || self.get_uid().is_some() @@ -731,7 +731,7 @@ impl Command { // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // // -Zon-broken-pipe is an opportunity to change the default here. - if !on_broken_pipe_flag_used() { + if !on_broken_pipe_used() { let mut default_set = MaybeUninit::::uninit(); cvt(sigemptyset(default_set.as_mut_ptr()))?; cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?; diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs index 21a1587214a1..5d1b14443c62 100644 --- a/library/std/src/sys/sync/condvar/xous.rs +++ b/library/std/src/sys/sync/condvar/xous.rs @@ -38,7 +38,7 @@ impl Condvar { // possible for `counter` to decrease due to a condvar timing out, in which // case the corresponding `timed_out` will increase accordingly. let Ok(waiter_count) = - self.counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |counter| { + self.counter.try_update(Ordering::Relaxed, Ordering::Relaxed, |counter| { if counter == 0 { return None; } else { diff --git a/library/std/src/sys/sync/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs index 961819cae8d6..0e8e954de075 100644 --- a/library/std/src/sys/sync/rwlock/futex.rs +++ b/library/std/src/sys/sync/rwlock/futex.rs @@ -86,7 +86,7 @@ impl RwLock { #[inline] pub fn try_read(&self) -> bool { self.state - .fetch_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED)) + .try_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED)) .is_ok() } @@ -164,7 +164,7 @@ impl RwLock { #[inline] pub fn try_write(&self) -> bool { self.state - .fetch_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED)) + .try_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED)) .is_ok() } diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs index 62f084acfd25..b41a65f7303b 100644 --- a/library/std/src/sys/sync/rwlock/queue.rs +++ b/library/std/src/sys/sync/rwlock/queue.rs @@ -329,7 +329,7 @@ impl RwLock { #[inline] pub fn try_read(&self) -> bool { - self.state.fetch_update(Acquire, Relaxed, read_lock).is_ok() + self.state.try_update(Acquire, Relaxed, read_lock).is_ok() } #[inline] @@ -343,7 +343,7 @@ impl RwLock { pub fn try_write(&self) -> bool { // Atomically set the `LOCKED` bit. This is lowered to a single atomic instruction on most // modern processors (e.g. "lock bts" on x86 and "ldseta" on modern AArch64), and therefore - // is more efficient than `fetch_update(lock(true))`, which can spuriously fail if a new + // is more efficient than `try_update(lock(true))`, which can spuriously fail if a new // node is appended to the queue. self.state.fetch_or(LOCKED, Acquire).addr() & LOCKED == 0 } @@ -453,7 +453,7 @@ impl RwLock { #[inline] pub unsafe fn read_unlock(&self) { - match self.state.fetch_update(Release, Acquire, |state| { + match self.state.try_update(Release, Acquire, |state| { if state.addr() & QUEUED == 0 { // If there are no threads queued, simply decrement the reader count. let count = state.addr() - (SINGLE | LOCKED); diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b758737d00c6..22f9bfef5a38 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -44,15 +44,6 @@ impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn new(stack: usize, init: Box) -> io::Result { - // FIXME: remove this block once wasi-sdk is updated with the fix from - // https://github.com/WebAssembly/wasi-libc/pull/716 - // WASI does not support threading via pthreads. While wasi-libc provides - // pthread stubs, pthread_create returns EAGAIN, which causes confusing - // errors. We return UNSUPPORTED_PLATFORM directly instead. - if cfg!(all(target_os = "wasi", not(target_feature = "atomics"))) { - return Err(io::Error::UNSUPPORTED_PLATFORM); - } - let data = init; let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); diff --git a/library/std/src/thread/join_handle.rs b/library/std/src/thread/join_handle.rs index 7112fe44f907..93dcc634d2df 100644 --- a/library/std/src/thread/join_handle.rs +++ b/library/std/src/thread/join_handle.rs @@ -101,6 +101,8 @@ impl JoinHandle { /// Waits for the associated thread to finish. /// /// This function will return immediately if the associated thread has already finished. + /// Otherwise, it fully waits for the thread to finish, including all destructors + /// for thread-local variables that might be running after the main function of the thread. /// /// In terms of [atomic memory orderings], the completion of the associated /// thread synchronizes with this function returning. In other words, all diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 3ac9956336d7..929f7fdc6dca 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -80,6 +80,9 @@ impl ScopeData { /// /// All threads spawned within the scope that haven't been manually joined /// will be automatically joined before this function returns. +/// However, note that joining will only wait for the main function of these threads to finish; even +/// when this function returns, destructors of thread-local variables in these threads might still +/// be running. /// /// # Panics /// @@ -290,6 +293,8 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { /// Waits for the associated thread to finish. /// /// This function will return immediately if the associated thread has already finished. + /// Otherwise, it fully waits for the thread to finish, including all destructors + /// for thread-local variables that might be running after the main function of the thread. /// /// In terms of [atomic memory orderings], the completion of the associated /// thread synchronizes with this function returning. diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs index 8bb8eb4bfc1a..012349350b0b 100644 --- a/library/std/tests/floats/lib.rs +++ b/library/std/tests/floats/lib.rs @@ -1,4 +1,4 @@ -#![feature(f16, f128, float_gamma, float_minimum_maximum, cfg_target_has_reliable_f16_f128)] +#![feature(f16, f128, float_gamma, cfg_target_has_reliable_f16_f128)] #![expect(internal_features)] // for reliable_f16_f128 use std::fmt; diff --git a/library/std/tests/sync/oneshot.rs b/library/std/tests/sync/oneshot.rs index 6a87c72b9cb5..8c47f35ebfea 100644 --- a/library/std/tests/sync/oneshot.rs +++ b/library/std/tests/sync/oneshot.rs @@ -127,6 +127,7 @@ fn recv_before_send() { } #[test] +#[ignore = "Inherently flaky and has caused several CI failures"] fn recv_timeout_before_send() { let (sender, receiver) = oneshot::channel(); @@ -135,6 +136,8 @@ fn recv_timeout_before_send() { sender.send(99u128).unwrap(); }); + // FIXME(#152145): Under load, there's no guarantee that thread `t` has + // ever been scheduled and run before this timeout expires. match receiver.recv_timeout(Duration::from_secs(1)) { Ok(99) => {} _ => panic!("expected Ok(99)"), diff --git a/library/std/tests/volatile-fat-ptr.rs b/library/std/tests/volatile-fat-ptr.rs index b005c12c6187..b00277e7a411 100644 --- a/library/std/tests/volatile-fat-ptr.rs +++ b/library/std/tests/volatile-fat-ptr.rs @@ -1,5 +1,4 @@ #![allow(stable_features)] -#![feature(volatile)] use std::ptr::{read_volatile, write_volatile}; diff --git a/library/std/tests/windows_unix_socket.rs b/library/std/tests/windows_unix_socket.rs new file mode 100644 index 000000000000..1d16ec9ed841 --- /dev/null +++ b/library/std/tests/windows_unix_socket.rs @@ -0,0 +1,220 @@ +#![cfg(windows)] +#![cfg(not(miri))] // no socket support in Miri +#![feature(windows_unix_domain_sockets)] +// Now only test windows_unix_domain_sockets feature +// in the future, will test both unix and windows uds +use std::io::{Read, Write}; +use std::os::windows::net::{UnixListener, UnixStream}; +use std::{mem, thread}; + +macro_rules! skip_nonapplicable_oses { + () => { + // UDS have been available under Windows since Insider Preview Build + // 17063. "Redstone 4" (RS4, version 1803, build number 17134) is + // therefore the first official release to include it. + if !is_windows_10_v1803_or_greater() { + println!("Not running this test on too-old Windows."); + return; + } + }; +} + +#[test] +fn win_uds_smoke_bind_connect() { + skip_nonapplicable_oses!(); + + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-smoke.sock"); + let _ = std::fs::remove_file(&sock_path); + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let sock_path_clone = sock_path.clone(); + let tx = thread::spawn(move || { + let mut stream = UnixStream::connect(&sock_path_clone).expect("connect failed"); + stream.write_all(b"hello").expect("write failed"); + }); + + let (mut stream, _) = listener.accept().expect("accept failed"); + let mut buf = [0; 5]; + stream.read_exact(&mut buf).expect("read failed"); + assert_eq!(&buf, b"hello"); + + tx.join().unwrap(); + + drop(listener); + let _ = std::fs::remove_file(&sock_path); +} + +#[test] +fn win_uds_echo() { + skip_nonapplicable_oses!(); + + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-echo.sock"); + let _ = std::fs::remove_file(&sock_path); + + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let srv = thread::spawn(move || { + let (mut stream, _) = listener.accept().expect("accept failed"); + let mut buf = [0u8; 128]; + loop { + let n = match stream.read(&mut buf) { + Ok(0) => break, + Ok(n) => n, + Err(e) => panic!("read error: {}", e), + }; + stream.write_all(&buf[..n]).expect("write_all failed"); + } + }); + + let sock_path_clone = sock_path.clone(); + let cli = thread::spawn(move || { + let mut stream = UnixStream::connect(&sock_path_clone).expect("connect failed"); + let req = b"hello windows uds"; + stream.write_all(req).expect("write failed"); + let mut resp = vec![0u8; req.len()]; + stream.read_exact(&mut resp).expect("read failed"); + assert_eq!(resp, req); + }); + + cli.join().unwrap(); + srv.join().unwrap(); + + let _ = std::fs::remove_file(&sock_path); +} + +#[test] +fn win_uds_path_too_long() { + skip_nonapplicable_oses!(); + + let tmp = std::env::temp_dir(); + let long_path = tmp.join("a".repeat(200)); + let result = UnixListener::bind(&long_path); + assert!(result.is_err()); + let _ = std::fs::remove_file(&long_path); +} + +#[test] +fn win_uds_existing_bind() { + skip_nonapplicable_oses!(); + + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-existing.sock"); + let _ = std::fs::remove_file(&sock_path); + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let result = UnixListener::bind(&sock_path); + assert!(result.is_err()); + drop(listener); + let _ = std::fs::remove_file(&sock_path); +} + +/// Returns true if we are currently running on Windows 10 v1803 (RS4) or greater. +fn is_windows_10_v1803_or_greater() -> bool { + is_windows_version_greater_or_equal(NTDDI_WIN10_RS4) +} + +/// Returns true if we are currently running on the given version of Windows +/// 10 (or newer). +fn is_windows_version_greater_or_equal(min_version: u32) -> bool { + is_windows_version_or_greater(HIBYTE(OSVER(min_version)), LOBYTE(OSVER(min_version)), 0, 0) +} + +/// Checks if we are running a version of Windows newer than the specified one. +fn is_windows_version_or_greater( + major: u8, + minor: u8, + service_pack: u8, + build_number: u32, +) -> bool { + let mut osvi = OSVERSIONINFOEXW { + dwOSVersionInfoSize: mem::size_of::() as _, + dwMajorVersion: u32::from(major), + dwMinorVersion: u32::from(minor), + wServicePackMajor: u16::from(service_pack), + dwBuildNumber: build_number, + ..OSVERSIONINFOEXW::default() + }; + + // SAFETY: this function is always safe to call. + let condmask = unsafe { + VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask( + VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL as _), + VER_MINORVERSION, + VER_GREATER_EQUAL as _, + ), + VER_SERVICEPACKMAJOR, + VER_GREATER_EQUAL as _, + ), + VER_BUILDNUMBER, + VER_GREATER_EQUAL as _, + ) + }; + + // SAFETY: osvi needs to point to a memory region valid for at least + // dwOSVersionInfoSize bytes, which is the case here. + (unsafe { + RtlVerifyVersionInfo( + &raw mut osvi, + VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, + condmask, + ) + }) == STATUS_SUCCESS +} + +#[expect(non_snake_case)] +const fn HIBYTE(x: u16) -> u8 { + ((x >> 8) & 0xFF) as u8 +} + +#[expect(non_snake_case)] +const fn LOBYTE(x: u16) -> u8 { + (x & 0xFF) as u8 +} + +#[expect(non_snake_case)] +const fn OSVER(x: u32) -> u16 { + ((x & OSVERSION_MASK) >> 16) as u16 +} + +// Inlined bindings because outside of `std` here. + +type NTSTATUS = i32; +const STATUS_SUCCESS: NTSTATUS = 0; + +#[expect(non_camel_case_types)] +type VER_FLAGS = u32; +const VER_BUILDNUMBER: VER_FLAGS = 4u32; +const VER_GREATER_EQUAL: VER_FLAGS = 3u32; +const VER_MAJORVERSION: VER_FLAGS = 2u32; +const VER_MINORVERSION: VER_FLAGS = 1u32; +const VER_SERVICEPACKMAJOR: VER_FLAGS = 32u32; + +const OSVERSION_MASK: u32 = 4294901760u32; +const NTDDI_WIN10_RS4: u32 = 167772165u32; + +#[expect(non_snake_case)] +#[repr(C)] +#[derive(Clone, Copy)] +struct OSVERSIONINFOEXW { + pub dwOSVersionInfoSize: u32, + pub dwMajorVersion: u32, + pub dwMinorVersion: u32, + pub dwBuildNumber: u32, + pub dwPlatformId: u32, + pub szCSDVersion: [u16; 128], + pub wServicePackMajor: u16, + pub wServicePackMinor: u16, + pub wSuiteMask: u16, + pub wProductType: u8, + pub wReserved: u8, +} + +impl Default for OSVERSIONINFOEXW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} + +windows_link::link!("ntdll.dll" "system" fn RtlVerifyVersionInfo(versioninfo : *const OSVERSIONINFOEXW, typemask : u32, conditionmask : u64) -> NTSTATUS); +windows_link::link!("kernel32.dll" "system" fn VerSetConditionMask(conditionmask : u64, typemask : VER_FLAGS, condition : u8) -> u64); diff --git a/library/std_detect/tests/cpu-detection.rs b/library/std_detect/tests/cpu-detection.rs index 196abfdb7c4d..0aad088af7de 100644 --- a/library/std_detect/tests/cpu-detection.rs +++ b/library/std_detect/tests/cpu-detection.rs @@ -1,4 +1,4 @@ -#![allow(internal_features)] +#![allow(internal_features, unused_features)] #![feature(stdarch_internal)] #![cfg_attr(target_arch = "arm", feature(stdarch_arm_feature_detection))] #![cfg_attr( diff --git a/library/std_detect/tests/macro_trailing_commas.rs b/library/std_detect/tests/macro_trailing_commas.rs index 29bd3f1162a4..a60b34acb872 100644 --- a/library/std_detect/tests/macro_trailing_commas.rs +++ b/library/std_detect/tests/macro_trailing_commas.rs @@ -1,4 +1,4 @@ -#![allow(internal_features)] +#![allow(internal_features, unused_features)] #![cfg_attr( any( target_arch = "arm", diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 9507b71106dd..5d547500b1cc 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -1565,7 +1565,7 @@ pub fn vceqh_f16(a: f16, b: f16) -> u16 { #[inline(always)] #[cfg_attr(test, assert_instr(fcmeq))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vceqz_f16(a: float16x4_t) -> uint16x4_t { let b: f16x4 = f16x4::new(0.0, 0.0, 0.0, 0.0); @@ -1576,7 +1576,7 @@ pub fn vceqz_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcmeq))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vceqzq_f16(a: float16x8_t) -> uint16x8_t { let b: f16x8 = f16x8::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -4092,7 +4092,7 @@ pub fn vcmlaq_rot90_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_f32( @@ -4113,7 +4113,7 @@ pub fn vcopy_lane_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { @@ -4137,7 +4137,7 @@ pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_ #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { @@ -4157,7 +4157,7 @@ pub fn vcopy_lane_s16(a: int16x4_t, b: int16 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { @@ -4175,7 +4175,7 @@ pub fn vcopy_lane_s32(a: int32x2_t, b: int32 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { @@ -4199,7 +4199,7 @@ pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u16( @@ -4222,7 +4222,7 @@ pub fn vcopy_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u32( @@ -4243,7 +4243,7 @@ pub fn vcopy_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { @@ -4267,7 +4267,7 @@ pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p16( @@ -4290,7 +4290,7 @@ pub fn vcopy_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_f32( @@ -4312,7 +4312,7 @@ pub fn vcopy_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x16_t) -> int8x8_t { @@ -4338,7 +4338,7 @@ pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x1 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s16( @@ -4362,7 +4362,7 @@ pub fn vcopy_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s32( @@ -4384,7 +4384,7 @@ pub fn vcopy_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u8( @@ -4413,7 +4413,7 @@ pub fn vcopy_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u16( @@ -4437,7 +4437,7 @@ pub fn vcopy_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u32( @@ -4459,7 +4459,7 @@ pub fn vcopy_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p8( @@ -4488,7 +4488,7 @@ pub fn vcopy_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p16( @@ -4624,7 +4624,7 @@ pub fn vcopyq_lane_p64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x8_t) -> int8x16_t { @@ -4994,7 +4994,7 @@ pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s16( @@ -5022,7 +5022,7 @@ pub fn vcopyq_lane_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s32( @@ -5046,7 +5046,7 @@ pub fn vcopyq_lane_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u8( @@ -5419,7 +5419,7 @@ pub fn vcopyq_lane_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u16( @@ -5447,7 +5447,7 @@ pub fn vcopyq_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u32( @@ -5471,7 +5471,7 @@ pub fn vcopyq_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p8( @@ -5844,7 +5844,7 @@ pub fn vcopyq_lane_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p16( @@ -5872,7 +5872,7 @@ pub fn vcopyq_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f32( @@ -5895,7 +5895,7 @@ pub fn vcopyq_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f64( @@ -5916,7 +5916,7 @@ pub fn vcopyq_laneq_f64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s8( @@ -6287,7 +6287,7 @@ pub fn vcopyq_laneq_s8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s16( @@ -6314,7 +6314,7 @@ pub fn vcopyq_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s32( @@ -6337,7 +6337,7 @@ pub fn vcopyq_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s64( @@ -6358,7 +6358,7 @@ pub fn vcopyq_laneq_s64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u8( @@ -6729,7 +6729,7 @@ pub fn vcopyq_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u16( @@ -6756,7 +6756,7 @@ pub fn vcopyq_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u32( @@ -6779,7 +6779,7 @@ pub fn vcopyq_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u64( @@ -6800,7 +6800,7 @@ pub fn vcopyq_laneq_u64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p8( @@ -7171,7 +7171,7 @@ pub fn vcopyq_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p16( @@ -7198,7 +7198,7 @@ pub fn vcopyq_laneq_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p64( @@ -7283,7 +7283,7 @@ pub fn vcvtq_f64_u64(a: uint64x2_t) -> float64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtn2))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvt_high_f16_f32(a: float16x4_t, b: float32x4_t) -> float16x8_t { vcombine_f16(a, vcvt_f16_f32(b)) @@ -7293,7 +7293,7 @@ pub fn vcvt_high_f16_f32(a: float16x4_t, b: float32x4_t) -> float16x8_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtl2))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvt_high_f32_f16(a: float16x8_t) -> float32x4_t { vcvt_f32_f16(vget_high_f16(a)) @@ -7532,7 +7532,7 @@ pub fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtas))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvta_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -7549,7 +7549,7 @@ pub fn vcvta_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtas))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtaq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -7630,7 +7630,7 @@ pub fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtau))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvta_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -7647,7 +7647,7 @@ pub fn vcvta_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtau))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtaq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8218,7 +8218,7 @@ pub fn vcvth_u64_f16(a: f16) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtms))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtm_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8235,7 +8235,7 @@ pub fn vcvtm_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtms))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtmq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -8316,7 +8316,7 @@ pub fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtmu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtm_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -8333,7 +8333,7 @@ pub fn vcvtm_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtmu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtmq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8566,7 +8566,7 @@ pub fn vcvtmd_u64_f64(a: f64) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtns))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtn_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8583,7 +8583,7 @@ pub fn vcvtn_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtns))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtnq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -8664,7 +8664,7 @@ pub fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtnu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtn_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -8681,7 +8681,7 @@ pub fn vcvtn_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtnu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtnq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8914,7 +8914,7 @@ pub fn vcvtnd_u64_f64(a: f64) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtps))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtp_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8931,7 +8931,7 @@ pub fn vcvtp_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtps))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtpq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -9012,7 +9012,7 @@ pub fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtpu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtp_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -9029,7 +9029,7 @@ pub fn vcvtp_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtpu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtpq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -9493,7 +9493,7 @@ pub fn vcvtxd_f32_f64(a: f64) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vdiv_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fdiv))] pub fn vdiv_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -9503,7 +9503,7 @@ pub fn vdiv_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vdivq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fdiv))] pub fn vdivq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -10108,7 +10108,7 @@ pub fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfma_lane_f16( a: float16x4_t, @@ -10124,7 +10124,7 @@ pub fn vfma_lane_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfma_laneq_f16( a: float16x4_t, @@ -10140,7 +10140,7 @@ pub fn vfma_laneq_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmaq_lane_f16( a: float16x8_t, @@ -10156,7 +10156,7 @@ pub fn vfmaq_lane_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmaq_laneq_f16( a: float16x8_t, @@ -10434,7 +10434,7 @@ pub fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal2))] pub fn vfmlal_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10452,7 +10452,7 @@ pub fn vfmlal_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal2))] pub fn vfmlalq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10472,7 +10472,7 @@ pub fn vfmlalq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_lane_high_f16( r: float32x2_t, @@ -10489,7 +10489,7 @@ pub fn vfmlal_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_laneq_high_f16( r: float32x2_t, @@ -10506,7 +10506,7 @@ pub fn vfmlal_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_lane_high_f16( r: float32x4_t, @@ -10523,7 +10523,7 @@ pub fn vfmlalq_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_laneq_high_f16( r: float32x4_t, @@ -10540,7 +10540,7 @@ pub fn vfmlalq_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_lane_low_f16( r: float32x2_t, @@ -10557,7 +10557,7 @@ pub fn vfmlal_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_laneq_low_f16( r: float32x2_t, @@ -10574,7 +10574,7 @@ pub fn vfmlal_laneq_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_lane_low_f16( r: float32x4_t, @@ -10591,7 +10591,7 @@ pub fn vfmlalq_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_laneq_low_f16( r: float32x4_t, @@ -10606,7 +10606,7 @@ pub fn vfmlalq_laneq_low_f16( #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal))] pub fn vfmlal_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10624,7 +10624,7 @@ pub fn vfmlal_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal))] pub fn vfmlalq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10642,7 +10642,7 @@ pub fn vfmlalq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl2))] pub fn vfmlsl_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10660,7 +10660,7 @@ pub fn vfmlsl_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl2))] pub fn vfmlslq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10680,7 +10680,7 @@ pub fn vfmlslq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_lane_high_f16( r: float32x2_t, @@ -10697,7 +10697,7 @@ pub fn vfmlsl_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_laneq_high_f16( r: float32x2_t, @@ -10714,7 +10714,7 @@ pub fn vfmlsl_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_lane_high_f16( r: float32x4_t, @@ -10731,7 +10731,7 @@ pub fn vfmlslq_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_laneq_high_f16( r: float32x4_t, @@ -10748,7 +10748,7 @@ pub fn vfmlslq_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_lane_low_f16( r: float32x2_t, @@ -10765,7 +10765,7 @@ pub fn vfmlsl_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_laneq_low_f16( r: float32x2_t, @@ -10782,7 +10782,7 @@ pub fn vfmlsl_laneq_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_lane_low_f16( r: float32x4_t, @@ -10799,7 +10799,7 @@ pub fn vfmlslq_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_laneq_low_f16( r: float32x4_t, @@ -10814,7 +10814,7 @@ pub fn vfmlslq_laneq_low_f16( #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl))] pub fn vfmlsl_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10832,7 +10832,7 @@ pub fn vfmlsl_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl))] pub fn vfmlslq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10863,7 +10863,7 @@ pub fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfms_lane_f16( a: float16x4_t, @@ -10879,7 +10879,7 @@ pub fn vfms_lane_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfms_laneq_f16( a: float16x4_t, @@ -10895,7 +10895,7 @@ pub fn vfms_laneq_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmsq_lane_f16( a: float16x8_t, @@ -10911,7 +10911,7 @@ pub fn vfmsq_lane_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmsq_laneq_f16( a: float16x8_t, @@ -12858,6 +12858,7 @@ pub unsafe fn vld4q_u64(a: *const u64) -> uint64x2x4_t { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE == 0); let atomic_src = crate::sync::atomic::AtomicI64::from_ptr(ptr as *mut i64); @@ -12876,6 +12877,7 @@ pub unsafe fn vldap1_lane_s64(ptr: *const i64, src: int64x1_t) #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_t { static_assert_uimm_bits!(LANE, 1); let atomic_src = crate::sync::atomic::AtomicI64::from_ptr(ptr as *mut i64); @@ -12894,6 +12896,7 @@ pub unsafe fn vldap1q_lane_s64(ptr: *const i64, src: int64x2_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12907,6 +12910,7 @@ pub unsafe fn vldap1q_lane_f64(ptr: *const f64, src: float64x2_ #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE == 0); transmute(vldap1_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12920,6 +12924,7 @@ pub unsafe fn vldap1_lane_u64(ptr: *const u64, src: uint64x1_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12933,6 +12938,7 @@ pub unsafe fn vldap1q_lane_u64(ptr: *const u64, src: uint64x2_t #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE == 0); transmute(vldap1_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12946,6 +12952,7 @@ pub unsafe fn vldap1_lane_p64(ptr: *const p64, src: poly64x1_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -15078,7 +15085,7 @@ pub fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> float64 #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmul_laneq_f16(a: float16x4_t, b: float16x8_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 3); @@ -15095,7 +15102,7 @@ pub fn vmul_laneq_f16(a: float16x4_t, b: float16x8_t) -> float1 #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulq_laneq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); @@ -15602,7 +15609,7 @@ pub fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmulx_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmulx))] pub fn vmulx_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -15619,7 +15626,7 @@ pub fn vmulx_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmulxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmulx))] pub fn vmulxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -15702,7 +15709,7 @@ pub fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulx_lane_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 2); @@ -15719,7 +15726,7 @@ pub fn vmulx_lane_f16(a: float16x4_t, b: float16x4_t) -> float1 #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulx_laneq_f16(a: float16x4_t, b: float16x8_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 3); @@ -15736,7 +15743,7 @@ pub fn vmulx_laneq_f16(a: float16x4_t, b: float16x8_t) -> float #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulxq_lane_f16(a: float16x8_t, b: float16x4_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 2); @@ -15766,7 +15773,7 @@ pub fn vmulxq_lane_f16(a: float16x8_t, b: float16x4_t) -> float #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulxq_laneq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); @@ -16128,7 +16135,7 @@ pub fn vpaddd_u64(a: uint64x2_t) -> u64 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpaddq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(faddp))] pub fn vpaddq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16347,7 +16354,7 @@ pub fn vpaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmax_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxp))] pub fn vpmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16364,7 +16371,7 @@ pub fn vpmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxp))] pub fn vpmaxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16381,7 +16388,7 @@ pub fn vpmaxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxnm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxnmp))] pub fn vpmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16398,7 +16405,7 @@ pub fn vpmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxnmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxnmp))] pub fn vpmaxnmq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16655,7 +16662,7 @@ pub fn vpmaxs_f32(a: float32x2_t) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmin_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminp))] pub fn vpmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16672,7 +16679,7 @@ pub fn vpmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminp))] pub fn vpminq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16689,7 +16696,7 @@ pub fn vpminq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminnm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminnmp))] pub fn vpminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16706,7 +16713,7 @@ pub fn vpminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminnmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminnmp))] pub fn vpminnmq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -21832,7 +21839,7 @@ pub fn vrecpxh_f16(a: f16) -> f16 { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { @@ -21843,7 +21850,7 @@ pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { @@ -21855,7 +21862,7 @@ pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { @@ -21866,7 +21873,7 @@ pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { @@ -21881,7 +21888,7 @@ pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { @@ -21892,7 +21899,7 @@ pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { @@ -21906,7 +21913,7 @@ pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { @@ -21917,7 +21924,7 @@ pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { @@ -23496,7 +23503,7 @@ pub fn vrnd64z_f64(a: float64x1_t) -> float64x1_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrnd_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintz))] pub fn vrnd_f16(a: float16x4_t) -> float16x4_t { @@ -23506,7 +23513,7 @@ pub fn vrnd_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintz))] pub fn vrndq_f16(a: float16x8_t) -> float16x8_t { @@ -23552,7 +23559,7 @@ pub fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrnda_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinta))] pub fn vrnda_f16(a: float16x4_t) -> float16x4_t { @@ -23562,7 +23569,7 @@ pub fn vrnda_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndaq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinta))] pub fn vrndaq_f16(a: float16x8_t) -> float16x8_t { @@ -23628,7 +23635,7 @@ pub fn vrndh_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndi_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinti))] pub fn vrndi_f16(a: float16x4_t) -> float16x4_t { @@ -23645,7 +23652,7 @@ pub fn vrndi_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndiq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinti))] pub fn vrndiq_f16(a: float16x8_t) -> float16x8_t { @@ -23743,7 +23750,7 @@ pub fn vrndih_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintm))] pub fn vrndm_f16(a: float16x4_t) -> float16x4_t { @@ -23753,7 +23760,7 @@ pub fn vrndm_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintm))] pub fn vrndmq_f16(a: float16x8_t) -> float16x8_t { @@ -23874,7 +23881,7 @@ pub fn vrndns_f32(a: f32) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndp_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintp))] pub fn vrndp_f16(a: float16x4_t) -> float16x4_t { @@ -23884,7 +23891,7 @@ pub fn vrndp_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndpq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintp))] pub fn vrndpq_f16(a: float16x8_t) -> float16x8_t { @@ -23940,7 +23947,7 @@ pub fn vrndph_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndx_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { @@ -23950,7 +23957,7 @@ pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndxq_f16(a: float16x8_t) -> float16x8_t { @@ -25453,7 +25460,7 @@ pub fn vsqadds_u32(a: u32, b: i32) -> u32 { #[inline(always)] #[cfg_attr(test, assert_instr(fsqrt))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vsqrt_f16(a: float16x4_t) -> float16x4_t { unsafe { simd_fsqrt(a) } @@ -25463,7 +25470,7 @@ pub fn vsqrt_f16(a: float16x4_t) -> float16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fsqrt))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vsqrtq_f16(a: float16x8_t) -> float16x8_t { unsafe { simd_fsqrt(a) } @@ -27122,6 +27129,7 @@ pub unsafe fn vst4q_u64(a: *mut u64, b: uint64x2x4_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_f64(ptr: *mut f64, val: float64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27133,6 +27141,7 @@ pub fn vstl1_lane_f64(ptr: *mut f64, val: float64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_f64(ptr: *mut f64, val: float64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27144,6 +27153,7 @@ pub fn vstl1q_lane_f64(ptr: *mut f64, val: float64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_u64(ptr: *mut u64, val: uint64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27155,6 +27165,7 @@ pub fn vstl1_lane_u64(ptr: *mut u64, val: uint64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_u64(ptr: *mut u64, val: uint64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27166,6 +27177,7 @@ pub fn vstl1q_lane_u64(ptr: *mut u64, val: uint64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_p64(ptr: *mut p64, val: poly64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27177,6 +27189,7 @@ pub fn vstl1_lane_p64(ptr: *mut p64, val: poly64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_p64(ptr: *mut p64, val: poly64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27188,6 +27201,7 @@ pub fn vstl1q_lane_p64(ptr: *mut p64, val: poly64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_s64(ptr: *mut i64, val: int64x1_t) { static_assert!(LANE == 0); let atomic_dst = ptr as *mut crate::sync::atomic::AtomicI64; @@ -27203,6 +27217,7 @@ pub fn vstl1_lane_s64(ptr: *mut i64, val: int64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_s64(ptr: *mut i64, val: int64x2_t) { static_assert_uimm_bits!(LANE, 1); let atomic_dst = ptr as *mut crate::sync::atomic::AtomicI64; @@ -28016,7 +28031,7 @@ pub fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn1))] pub fn vtrn1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28026,7 +28041,7 @@ pub fn vtrn1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn1))] pub fn vtrn1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28252,7 +28267,7 @@ pub fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn2))] pub fn vtrn2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28262,7 +28277,7 @@ pub fn vtrn2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn2))] pub fn vtrn2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28762,7 +28777,7 @@ pub fn vuqadds_s32(a: i32, b: u32) -> i32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp1))] pub fn vuzp1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28772,7 +28787,7 @@ pub fn vuzp1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp1))] pub fn vuzp1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28998,7 +29013,7 @@ pub fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp2))] pub fn vuzp2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29008,7 +29023,7 @@ pub fn vuzp2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp2))] pub fn vuzp2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -29252,7 +29267,7 @@ pub fn vxarq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip1))] pub fn vzip1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29262,7 +29277,7 @@ pub fn vzip1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip1))] pub fn vzip1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -29488,7 +29503,7 @@ pub fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip2))] pub fn vzip2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29498,7 +29513,7 @@ pub fn vzip2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip2))] pub fn vzip2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index b172b57f3254..580f203ef066 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -569,47 +569,46 @@ mod tests { use crate::core_arch::aarch64::test_support::*; use crate::core_arch::arm_shared::test_support::*; use crate::core_arch::{aarch64::neon::*, aarch64::*, simd::*}; - use std::mem::transmute; use stdarch_test::simd_test; #[simd_test(enable = "neon")] - unsafe fn test_vadd_f64() { - let a = 1.; - let b = 8.; - let e = 9.; - let r: f64 = transmute(vadd_f64(transmute(a), transmute(b))); + fn test_vadd_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([8.]); + let e = f64x1::from_array([9.]); + let r = f64x1::from(vadd_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddq_f64() { + fn test_vaddq_f64() { let a = f64x2::new(1., 2.); let b = f64x2::new(8., 7.); let e = f64x2::new(9., 9.); - let r: f64x2 = transmute(vaddq_f64(transmute(a), transmute(b))); + let r = f64x2::from(vaddq_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_s64() { - let a = 1_i64; - let b = 8_i64; - let e = 9_i64; - let r: i64 = transmute(vadd_s64(transmute(a), transmute(b))); + fn test_vadd_s64() { + let a = i64x1::from_array([1]); + let b = i64x1::from_array([8]); + let e = i64x1::from_array([9]); + let r = i64x1::from(vadd_s64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_u64() { - let a = 1_u64; - let b = 8_u64; - let e = 9_u64; - let r: u64 = transmute(vadd_u64(transmute(a), transmute(b))); + fn test_vadd_u64() { + let a = u64x1::from_array([1]); + let b = u64x1::from_array([8]); + let e = u64x1::from_array([9]); + let r = u64x1::from(vadd_u64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_s64() { + fn test_vaddd_s64() { let a = 1_i64; let b = 8_i64; let e = 9_i64; @@ -618,7 +617,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_u64() { + fn test_vaddd_u64() { let a = 1_u64; let b = 8_u64; let e = 9_u64; @@ -627,25 +626,25 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vext_p64() { - let a: i64x1 = i64x1::new(0); - let b: i64x1 = i64x1::new(1); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vext_p64::<0>(transmute(a), transmute(b))); + fn test_vext_p64() { + let a = u64x1::new(0); + let b = u64x1::new(1); + let e = u64x1::new(0); + let r = u64x1::from(vext_p64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_f64() { - let a: f64x1 = f64x1::new(0.); - let b: f64x1 = f64x1::new(1.); - let e: f64x1 = f64x1::new(0.); - let r: f64x1 = transmute(vext_f64::<0>(transmute(a), transmute(b))); + fn test_vext_f64() { + let a = f64x1::new(0.); + let b = f64x1::new(1.); + let e = f64x1::new(0.); + let r = f64x1::from(vext_f64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_s64() { + fn test_vshld_n_s64() { let a: i64 = 1; let e: i64 = 4; let r: i64 = vshld_n_s64::<2>(a); @@ -653,7 +652,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_u64() { + fn test_vshld_n_u64() { let a: u64 = 1; let e: u64 = 4; let r: u64 = vshld_n_u64::<2>(a); @@ -661,7 +660,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_s64() { + fn test_vshrd_n_s64() { let a: i64 = 4; let e: i64 = 1; let r: i64 = vshrd_n_s64::<2>(a); @@ -669,7 +668,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_u64() { + fn test_vshrd_n_u64() { let a: u64 = 4; let e: u64 = 1; let r: u64 = vshrd_n_u64::<2>(a); @@ -677,7 +676,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_s64() { + fn test_vsrad_n_s64() { let a: i64 = 1; let b: i64 = 4; let e: i64 = 2; @@ -686,7 +685,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_u64() { + fn test_vsrad_n_u64() { let a: u64 = 1; let b: u64 = 4; let e: u64 = 2; @@ -695,298 +694,461 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_f64() { + fn test_vdup_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vdup_n_f64(a)); + let r = f64x1::from(vdup_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_p64() { + fn test_vdup_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vdup_n_p64(a)); + let r = u64x1::from(vdup_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_f64() { + fn test_vdupq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vdupq_n_f64(a)); + let r = f64x2::from(vdupq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_p64() { + fn test_vdupq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vdupq_n_p64(a)); + let r = u64x2::from(vdupq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_p64() { + fn test_vmov_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vmov_n_p64(a)); + let r = u64x1::from(vmov_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_f64() { + fn test_vmov_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vmov_n_f64(a)); + let r = f64x1::from(vmov_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_p64() { + fn test_vmovq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vmovq_n_p64(a)); + let r = u64x2::from(vmovq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_f64() { + fn test_vmovq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vmovq_n_f64(a)); + let r = f64x2::from(vmovq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_f64() { + fn test_vget_high_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(2.0); - let r: f64x1 = transmute(vget_high_f64(transmute(a))); + let r = f64x1::from(vget_high_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_p64() { + fn test_vget_high_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(2); - let r: u64x1 = transmute(vget_high_p64(transmute(a))); + let r = u64x1::from(vget_high_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_f64() { + fn test_vget_low_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(1.0); - let r: f64x1 = transmute(vget_low_f64(transmute(a))); + let r = f64x1::from(vget_low_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_p64() { + fn test_vget_low_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(1); - let r: u64x1 = transmute(vget_low_p64(transmute(a))); + let r = u64x1::from(vget_low_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_lane_f64() { + fn test_vget_lane_f64() { let v = f64x1::new(1.0); - let r = vget_lane_f64::<0>(transmute(v)); + let r = vget_lane_f64::<0>(v.into()); assert_eq!(r, 1.0); } #[simd_test(enable = "neon")] - unsafe fn test_vgetq_lane_f64() { + fn test_vgetq_lane_f64() { let v = f64x2::new(0.0, 1.0); - let r = vgetq_lane_f64::<1>(transmute(v)); + let r = vgetq_lane_f64::<1>(v.into()); assert_eq!(r, 1.0); - let r = vgetq_lane_f64::<0>(transmute(v)); + let r = vgetq_lane_f64::<0>(v.into()); assert_eq!(r, 0.0); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_s64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_s64() { + let a = i64x1::new(1); + let b = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_lane_s64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_lane_u64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_u64() { + let a = u64x1::new(1); + let b = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_u64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_p64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_p64() { + let a = u64x1::new(1); + let b = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_p64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_f64() { - let a: f64 = 1.; - let b: f64 = 0.; - let e: f64 = 0.; - let r: f64 = transmute(vcopy_lane_f64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([0.]); + let e = f64x1::from_array([0.]); + let r = f64x1::from(vcopy_lane_f64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_s64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_s64() { + let a = i64x1::new(1); + let b = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_laneq_s64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_laneq_u64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_u64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_u64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_p64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_p64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_p64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(0., 0.5); - let e: f64 = 0.5; - let r: f64 = transmute(vcopy_laneq_f64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_f64() { + let a = f64x1::from_array([1.]); + let b = f64x2::from_array([0., 0.5]); + let e = f64x1::from_array([0.5]); + let r = f64x1::from(vcopy_laneq_f64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vbsl_f64() { + fn test_vbsl_f64() { let a = u64x1::new(0x8000000000000000); let b = f64x1::new(-1.23f64); let c = f64x1::new(2.34f64); let e = f64x1::new(-2.34f64); - let r: f64x1 = transmute(vbsl_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x1::from(vbsl_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbsl_p64() { + fn test_vbsl_p64() { let a = u64x1::new(1); let b = u64x1::new(u64::MAX); let c = u64x1::new(u64::MIN); let e = u64x1::new(1); - let r: u64x1 = transmute(vbsl_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x1::from(vbsl_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_f64() { + fn test_vbslq_f64() { let a = u64x2::new(1, 0x8000000000000000); let b = f64x2::new(f64::MAX, -1.23f64); let c = f64x2::new(f64::MIN, 2.34f64); let e = f64x2::new(f64::MIN, -2.34f64); - let r: f64x2 = transmute(vbslq_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x2::from(vbslq_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_p64() { + fn test_vbslq_p64() { let a = u64x2::new(u64::MAX, 1); let b = u64x2::new(u64::MAX, u64::MAX); let c = u64x2::new(u64::MIN, u64::MIN); let e = u64x2::new(u64::MAX, 1); - let r: u64x2 = transmute(vbslq_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x2::from(vbslq_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64() { + fn test_vld1_f64() { let a: [f64; 2] = [0., 1.]; let e = f64x1::new(1.); - let r: f64x1 = transmute(vld1_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64() { + fn test_vld1q_f64() { let a: [f64; 3] = [0., 1., 2.]; let e = f64x2::new(1., 2.); - let r: f64x2 = transmute(vld1q_f64(a[1..].as_ptr())); + let r = unsafe { f64x2::from(vld1q_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_dup_f64() { + fn test_vld1_dup_f64() { let a: [f64; 2] = [1., 42.]; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_dup_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_dup_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_dup_f64() { + fn test_vld1q_dup_f64() { let elem: f64 = 42.; let e = f64x2::new(42., 42.); - let r: f64x2 = transmute(vld1q_dup_f64(&elem)); + let r = unsafe { f64x2::from(vld1q_dup_f64(&elem)) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_lane_f64() { + fn test_vld1_lane_f64() { let a = f64x1::new(0.); let elem: f64 = 42.; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_lane_f64::<0>(&elem, transmute(a))); + let r = unsafe { f64x1::from(vld1_lane_f64::<0>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_lane_f64() { + fn test_vld1q_lane_f64() { let a = f64x2::new(0., 1.); let elem: f64 = 42.; let e = f64x2::new(0., 42.); - let r: f64x2 = transmute(vld1q_lane_f64::<1>(&elem, transmute(a))); + let r = unsafe { f64x2::from(vld1q_lane_f64::<1>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64() { + fn test_vst1_f64() { let mut vals = [0_f64; 2]; let a = f64x1::new(1.); - vst1_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64() { + fn test_vst1q_f64() { let mut vals = [0_f64; 3]; let a = f64x2::new(1., 2.); - vst1q_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1q_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); assert_eq!(vals[2], 2.); } + + macro_rules! wide_store_load_roundtrip { + ($elem_ty:ty, $len:expr, $vec_ty:ty, $store:expr, $load:expr) => { + let vals: [$elem_ty; $len] = crate::array::from_fn(|i| i as $elem_ty); + let a: $vec_ty = transmute(vals); + let mut tmp = [0 as $elem_ty; $len]; + $store(tmp.as_mut_ptr().cast(), a); + let r: $vec_ty = $load(tmp.as_ptr().cast()); + let out: [$elem_ty; $len] = transmute(r); + assert_eq!(out, vals); + }; + } + + macro_rules! wide_store_load_roundtrip_fp16 { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_fp16! { + test_vld1_f16_x2(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); + test_vld1_f16_x3(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); + test_vld1_f16_x4(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); + + test_vld1q_f16_x2(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); + test_vld1q_f16_x3(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); + test_vld1q_f16_x4(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); + } + + macro_rules! wide_store_load_roundtrip_aes { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,aes")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_aes! { + test_vld1_p64_x2(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); + test_vld1_p64_x3(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); + test_vld1_p64_x4(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); + + test_vld1q_p64_x2(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); + test_vld1q_p64_x3(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); + test_vld1q_p64_x4(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); + } + + macro_rules! wide_store_load_roundtrip_neon { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_neon! { + test_vld1_f32_x2(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); + test_vld1_f32_x3(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); + test_vld1_f32_x4(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); + + test_vld1q_f32_x2(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); + test_vld1q_f32_x3(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); + test_vld1q_f32_x4(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); + + test_vld1_s8_x2(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); + test_vld1_s8_x3(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); + test_vld1_s8_x4(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); + + test_vld1q_s8_x2(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); + test_vld1q_s8_x3(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); + test_vld1q_s8_x4(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); + + test_vld1_s16_x2(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); + test_vld1_s16_x3(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); + test_vld1_s16_x4(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); + + test_vld1q_s16_x2(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); + test_vld1q_s16_x3(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); + test_vld1q_s16_x4(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); + + test_vld1_s32_x2(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); + test_vld1_s32_x3(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); + test_vld1_s32_x4(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); + + test_vld1q_s32_x2(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); + test_vld1q_s32_x3(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); + test_vld1q_s32_x4(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); + + test_vld1_s64_x2(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); + test_vld1_s64_x3(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); + test_vld1_s64_x4(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); + + test_vld1q_s64_x2(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); + test_vld1q_s64_x3(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); + test_vld1q_s64_x4(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); + + test_vld1_u8_x2(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); + test_vld1_u8_x3(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); + test_vld1_u8_x4(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); + + test_vld1q_u8_x2(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); + test_vld1q_u8_x3(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); + test_vld1q_u8_x4(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); + + test_vld1_u16_x2(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); + test_vld1_u16_x3(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); + test_vld1_u16_x4(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); + + test_vld1q_u16_x2(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); + test_vld1q_u16_x3(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); + test_vld1q_u16_x4(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); + + test_vld1_u32_x2(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); + test_vld1_u32_x3(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); + test_vld1_u32_x4(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); + + test_vld1q_u32_x2(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); + test_vld1q_u32_x3(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); + test_vld1q_u32_x4(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); + + test_vld1_u64_x2(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); + test_vld1_u64_x3(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); + test_vld1_u64_x4(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); + + test_vld1q_u64_x2(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); + test_vld1q_u64_x3(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); + test_vld1q_u64_x4(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); + + test_vld1_p8_x2(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); + test_vld1_p8_x3(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); + test_vld1_p8_x4(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); + + test_vld1q_p8_x2(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); + test_vld1q_p8_x3(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); + test_vld1q_p8_x4(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); + + test_vld1_p16_x2(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); + test_vld1_p16_x3(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); + test_vld1_p16_x4(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); + + test_vld1q_p16_x2(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); + test_vld1q_p16_x3(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); + test_vld1q_p16_x4(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); + } } #[cfg(test)] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 3b67208182cb..d05d37640225 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -821,7 +821,7 @@ pub fn vabaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -851,7 +851,7 @@ pub fn vabd_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1422,7 +1422,7 @@ pub fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1444,7 +1444,7 @@ pub fn vabs_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1673,7 +1673,7 @@ pub fn vabsh_f16(a: f16) -> f16 { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1695,7 +1695,7 @@ pub fn vadd_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -3879,7 +3879,7 @@ pub fn vbicq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -3907,7 +3907,7 @@ pub fn vbsl_f16(a: uint16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4529,7 +4529,7 @@ pub fn vbslq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4559,7 +4559,7 @@ pub fn vcage_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4647,7 +4647,7 @@ pub fn vcageq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4677,7 +4677,7 @@ pub fn vcagt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4765,7 +4765,7 @@ pub fn vcagtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4787,7 +4787,7 @@ pub fn vcale_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4851,7 +4851,7 @@ pub fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4873,7 +4873,7 @@ pub fn vcalt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4937,7 +4937,7 @@ pub fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4959,7 +4959,7 @@ pub fn vceq_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5317,7 +5317,7 @@ pub fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5339,7 +5339,7 @@ pub fn vcge_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5655,7 +5655,7 @@ pub fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5678,7 +5678,7 @@ pub fn vcgez_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5701,7 +5701,7 @@ pub fn vcgezq_f16(a: float16x8_t) -> uint16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5723,7 +5723,7 @@ pub fn vcgt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6039,7 +6039,7 @@ pub fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6062,7 +6062,7 @@ pub fn vcgtz_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6085,7 +6085,7 @@ pub fn vcgtzq_f16(a: float16x8_t) -> uint16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6107,7 +6107,7 @@ pub fn vcle_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6423,7 +6423,7 @@ pub fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6446,7 +6446,7 @@ pub fn vclez_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6769,7 +6769,7 @@ pub fn vclsq_u32(a: uint32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6791,7 +6791,7 @@ pub fn vclt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7107,7 +7107,7 @@ pub fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7130,7 +7130,7 @@ pub fn vcltz_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7812,7 +7812,7 @@ pub fn vcntq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8041,7 +8041,7 @@ pub fn vcombine_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8065,7 +8065,7 @@ pub fn vcreate_f16(a: u64) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8577,7 +8577,7 @@ pub fn vcreate_p64(a: u64) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8599,7 +8599,7 @@ pub fn vcvt_f16_f32(a: float32x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8621,7 +8621,7 @@ pub fn vcvt_f16_s16(a: int16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8643,7 +8643,7 @@ pub fn vcvtq_f16_s16(a: int16x8_t) -> float16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8665,7 +8665,7 @@ pub fn vcvt_f16_u16(a: uint16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8688,7 +8688,7 @@ pub fn vcvtq_f16_u16(a: uint16x8_t) -> float16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8795,7 +8795,7 @@ pub fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8830,7 +8830,7 @@ pub fn vcvt_n_f16_s16(a: int16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8865,7 +8865,7 @@ pub fn vcvtq_n_f16_s16(a: int16x8_t) -> float16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8900,7 +8900,7 @@ pub fn vcvt_n_f16_u16(a: uint16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9087,7 +9087,7 @@ pub fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9122,7 +9122,7 @@ pub fn vcvt_n_s16_f16(a: float16x4_t) -> int16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9233,7 +9233,7 @@ pub fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9268,7 +9268,7 @@ pub fn vcvt_n_u16_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9378,7 +9378,7 @@ pub fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9400,7 +9400,7 @@ pub fn vcvt_s16_f16(a: float16x4_t) -> int16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9480,7 +9480,7 @@ pub fn vcvtq_s32_f32(a: float32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9502,7 +9502,7 @@ pub fn vcvt_u16_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10140,7 +10140,7 @@ pub fn vdotq_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10165,7 +10165,7 @@ pub fn vdup_lane_f16(a: float16x4_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10719,7 +10719,7 @@ pub fn vdup_lane_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10744,7 +10744,7 @@ pub fn vdup_laneq_f16(a: float16x8_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -12261,7 +12261,7 @@ pub fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -12640,7 +12640,7 @@ pub fn vextq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13228,7 +13228,7 @@ pub fn vextq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13250,7 +13250,7 @@ pub fn vfma_f16(a: float16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13357,7 +13357,7 @@ pub fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13383,7 +13383,7 @@ pub fn vfms_f16(a: float16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13494,7 +13494,7 @@ pub fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13513,7 +13513,7 @@ pub fn vget_high_f16(a: float16x8_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -15808,21 +15808,13 @@ pub unsafe fn vld1q_f16(ptr: *const f16) -> float16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x2(a: *const f16) -> float16x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4f16.p0")] - fn _vld1_f16_x2(a: *const f16) -> float16x4x2_t; - } - _vld1_f16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f16_x3)"] @@ -15834,21 +15826,13 @@ pub unsafe fn vld1_f16_x2(a: *const f16) -> float16x4x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x3(a: *const f16) -> float16x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4f16.p0")] - fn _vld1_f16_x3(a: *const f16) -> float16x4x3_t; - } - _vld1_f16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f16_x4)"] @@ -15860,21 +15844,13 @@ pub unsafe fn vld1_f16_x3(a: *const f16) -> float16x4x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x4(a: *const f16) -> float16x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4f16.p0")] - fn _vld1_f16_x4(a: *const f16) -> float16x4x4_t; - } - _vld1_f16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x2)"] @@ -15886,21 +15862,13 @@ pub unsafe fn vld1_f16_x4(a: *const f16) -> float16x4x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x2(a: *const f16) -> float16x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8f16.p0")] - fn _vld1q_f16_x2(a: *const f16) -> float16x8x2_t; - } - _vld1q_f16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x3)"] @@ -15912,21 +15880,13 @@ pub unsafe fn vld1q_f16_x2(a: *const f16) -> float16x8x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x3(a: *const f16) -> float16x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8f16.p0")] - fn _vld1q_f16_x3(a: *const f16) -> float16x8x3_t; - } - _vld1q_f16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x4)"] @@ -15938,21 +15898,13 @@ pub unsafe fn vld1q_f16_x3(a: *const f16) -> float16x8x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x4(a: *const f16) -> float16x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8f16.p0")] - fn _vld1q_f16_x4(a: *const f16) -> float16x8x4_t; - } - _vld1q_f16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32)"] @@ -16156,10 +16108,10 @@ pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16170,15 +16122,7 @@ pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2f32.p0")] - fn _vld1_f32_x2(a: *const f32) -> float32x2x2_t; - } - _vld1_f32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32_x3)"] @@ -16187,10 +16131,10 @@ pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16201,15 +16145,7 @@ pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2f32.p0")] - fn _vld1_f32_x3(a: *const f32) -> float32x2x3_t; - } - _vld1_f32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32_x4)"] @@ -16218,10 +16154,10 @@ pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16232,15 +16168,7 @@ pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2f32.p0")] - fn _vld1_f32_x4(a: *const f32) -> float32x2x4_t; - } - _vld1_f32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x2)"] @@ -16249,10 +16177,10 @@ pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16263,15 +16191,7 @@ pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4f32.p0")] - fn _vld1q_f32_x2(a: *const f32) -> float32x4x2_t; - } - _vld1q_f32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x3)"] @@ -16280,10 +16200,10 @@ pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16294,15 +16214,7 @@ pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4f32.p0")] - fn _vld1q_f32_x3(a: *const f32) -> float32x4x3_t; - } - _vld1q_f32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x4)"] @@ -16311,10 +16223,10 @@ pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16325,15 +16237,7 @@ pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4f32.p0")] - fn _vld1q_f32_x4(a: *const f32) -> float32x4x4_t; - } - _vld1q_f32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load one single-element structure to one lane of one register"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_f16)"] @@ -17000,10 +16904,10 @@ pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { #[inline(always)] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17014,7 +16918,7 @@ pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { - transmute(vld1_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64_x3)"] @@ -17026,7 +16930,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17037,7 +16941,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { - transmute(vld1_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64_x4)"] @@ -17049,7 +16953,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17060,20 +16964,19 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { - transmute(vld1_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17084,47 +16987,19 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { - transmute(vld1q_s64_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { - let mut ret_val: poly64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17135,48 +17010,19 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { - transmute(vld1q_s64_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { - let mut ret_val: poly64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17187,36 +17033,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { - transmute(vld1q_s64_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { - let mut ret_val: poly64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8)"] @@ -17329,10 +17146,10 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17343,15 +17160,7 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i8.p0")] - fn _vld1_s8_x2(a: *const i8) -> int8x8x2_t; - } - _vld1_s8_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8_x3)"] @@ -17360,10 +17169,10 @@ pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17374,15 +17183,7 @@ pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i8.p0")] - fn _vld1_s8_x3(a: *const i8) -> int8x8x3_t; - } - _vld1_s8_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8_x4)"] @@ -17391,10 +17192,10 @@ pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17405,15 +17206,7 @@ pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i8.p0")] - fn _vld1_s8_x4(a: *const i8) -> int8x8x4_t; - } - _vld1_s8_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x2)"] @@ -17422,10 +17215,10 @@ pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17436,15 +17229,7 @@ pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v16i8.p0")] - fn _vld1q_s8_x2(a: *const i8) -> int8x16x2_t; - } - _vld1q_s8_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x3)"] @@ -17453,10 +17238,10 @@ pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17467,15 +17252,7 @@ pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v16i8.p0")] - fn _vld1q_s8_x3(a: *const i8) -> int8x16x3_t; - } - _vld1q_s8_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x4)"] @@ -17484,10 +17261,10 @@ pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17498,15 +17275,7 @@ pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v16i8.p0")] - fn _vld1q_s8_x4(a: *const i8) -> int8x16x4_t; - } - _vld1q_s8_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x2)"] @@ -17515,10 +17284,10 @@ pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17529,15 +17298,7 @@ pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i16.p0")] - fn _vld1_s16_x2(a: *const i16) -> int16x4x2_t; - } - _vld1_s16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x3)"] @@ -17546,10 +17307,10 @@ pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17560,15 +17321,7 @@ pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i16.p0")] - fn _vld1_s16_x3(a: *const i16) -> int16x4x3_t; - } - _vld1_s16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x4)"] @@ -17577,10 +17330,10 @@ pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17591,15 +17344,7 @@ pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i16.p0")] - fn _vld1_s16_x4(a: *const i16) -> int16x4x4_t; - } - _vld1_s16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x2)"] @@ -17608,10 +17353,10 @@ pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17622,15 +17367,7 @@ pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i16.p0")] - fn _vld1q_s16_x2(a: *const i16) -> int16x8x2_t; - } - _vld1q_s16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x3)"] @@ -17639,10 +17376,10 @@ pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17653,15 +17390,7 @@ pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i16.p0")] - fn _vld1q_s16_x3(a: *const i16) -> int16x8x3_t; - } - _vld1q_s16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x4)"] @@ -17670,10 +17399,10 @@ pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17684,15 +17413,7 @@ pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i16.p0")] - fn _vld1q_s16_x4(a: *const i16) -> int16x8x4_t; - } - _vld1q_s16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x2)"] @@ -17701,10 +17422,10 @@ pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17715,15 +17436,7 @@ pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i32.p0")] - fn _vld1_s32_x2(a: *const i32) -> int32x2x2_t; - } - _vld1_s32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x3)"] @@ -17732,10 +17445,10 @@ pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17746,15 +17459,7 @@ pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i32.p0")] - fn _vld1_s32_x3(a: *const i32) -> int32x2x3_t; - } - _vld1_s32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x4)"] @@ -17763,10 +17468,10 @@ pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17777,15 +17482,7 @@ pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i32.p0")] - fn _vld1_s32_x4(a: *const i32) -> int32x2x4_t; - } - _vld1_s32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x2)"] @@ -17794,10 +17491,10 @@ pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17808,15 +17505,7 @@ pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i32.p0")] - fn _vld1q_s32_x2(a: *const i32) -> int32x4x2_t; - } - _vld1q_s32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x3)"] @@ -17825,10 +17514,10 @@ pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17839,15 +17528,7 @@ pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i32.p0")] - fn _vld1q_s32_x3(a: *const i32) -> int32x4x3_t; - } - _vld1q_s32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x4)"] @@ -17856,10 +17537,10 @@ pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17870,15 +17551,7 @@ pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i32.p0")] - fn _vld1q_s32_x4(a: *const i32) -> int32x4x4_t; - } - _vld1q_s32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x2)"] @@ -17887,10 +17560,10 @@ pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17901,15 +17574,7 @@ pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v1i64.p0")] - fn _vld1_s64_x2(a: *const i64) -> int64x1x2_t; - } - _vld1_s64_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x3)"] @@ -17918,10 +17583,10 @@ pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17932,15 +17597,7 @@ pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v1i64.p0")] - fn _vld1_s64_x3(a: *const i64) -> int64x1x3_t; - } - _vld1_s64_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x4)"] @@ -17949,10 +17606,10 @@ pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17963,15 +17620,7 @@ pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v1i64.p0")] - fn _vld1_s64_x4(a: *const i64) -> int64x1x4_t; - } - _vld1_s64_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x2)"] @@ -17980,10 +17629,10 @@ pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17994,15 +17643,7 @@ pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i64.p0")] - fn _vld1q_s64_x2(a: *const i64) -> int64x2x2_t; - } - _vld1q_s64_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x3)"] @@ -18011,10 +17652,10 @@ pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18025,15 +17666,7 @@ pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i64.p0")] - fn _vld1q_s64_x3(a: *const i64) -> int64x2x3_t; - } - _vld1q_s64_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x4)"] @@ -18042,10 +17675,10 @@ pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18056,28 +17689,19 @@ pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i64.p0")] - fn _vld1q_s64_x4(a: *const i64) -> int64x2x4_t; - } - _vld1q_s64_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18088,47 +17712,19 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { - transmute(vld1_s8_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { - let mut ret_val: uint8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18139,48 +17735,19 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - let mut ret_val: uint8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18191,49 +17758,19 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - let mut ret_val: uint8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18244,59 +17781,19 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - let mut ret_val: uint8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18307,66 +17804,19 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - let mut ret_val: uint8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18377,73 +17827,19 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - let mut ret_val: uint8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18454,47 +17850,19 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - let mut ret_val: uint16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18505,48 +17873,19 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - let mut ret_val: uint16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18557,49 +17896,19 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - let mut ret_val: uint16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18610,47 +17919,19 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - let mut ret_val: uint16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18661,48 +17942,19 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - let mut ret_val: uint16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18713,49 +17965,19 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - transmute(vld1q_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - let mut ret_val: uint16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18766,47 +17988,19 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - transmute(vld1_s32_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - let mut ret_val: uint32x2x2_t = transmute(vld1_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18817,48 +18011,19 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - transmute(vld1_s32_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - let mut ret_val: uint32x2x3_t = transmute(vld1_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18869,49 +18034,19 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - transmute(vld1_s32_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - let mut ret_val: uint32x2x4_t = transmute(vld1_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18922,47 +18057,19 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - transmute(vld1q_s32_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - let mut ret_val: uint32x4x2_t = transmute(vld1q_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18973,48 +18080,19 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - transmute(vld1q_s32_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - let mut ret_val: uint32x4x3_t = transmute(vld1q_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19025,36 +18103,7 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - transmute(vld1q_s32_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - let mut ret_val: uint32x4x4_t = transmute(vld1q_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x2)"] @@ -19063,10 +18112,10 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19077,7 +18126,7 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { - transmute(vld1_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x3)"] @@ -19086,10 +18135,10 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19100,7 +18149,7 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { - transmute(vld1_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x4)"] @@ -19109,10 +18158,10 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19123,20 +18172,19 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { - transmute(vld1_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19147,47 +18195,19 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - transmute(vld1q_s64_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - let mut ret_val: uint64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19198,48 +18218,19 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - transmute(vld1q_s64_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - let mut ret_val: uint64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19250,49 +18241,19 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - transmute(vld1q_s64_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - let mut ret_val: uint64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19303,47 +18264,19 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - transmute(vld1_s8_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - let mut ret_val: poly8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19354,48 +18287,19 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - let mut ret_val: poly8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19406,49 +18310,19 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - let mut ret_val: poly8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19459,59 +18333,19 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - let mut ret_val: poly8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19522,66 +18356,19 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - let mut ret_val: poly8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19592,73 +18379,19 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - let mut ret_val: poly8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19669,47 +18402,19 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - let mut ret_val: poly16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19720,48 +18425,19 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - let mut ret_val: poly16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19772,49 +18448,19 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - let mut ret_val: poly16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19825,47 +18471,19 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - let mut ret_val: poly16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19876,48 +18494,19 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - let mut ret_val: poly16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -19928,36 +18517,7 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { - transmute(vld1q_s16_x4(transmute(a))) -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { - let mut ret_val: poly16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val + crate::ptr::read_unaligned(a.cast()) } #[inline(always)] #[rustc_legacy_const_generics(1)] @@ -28187,7 +26747,7 @@ pub unsafe fn vldrq_p128(a: *const p128) -> p128 { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28217,7 +26777,7 @@ pub fn vmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28593,7 +27153,7 @@ pub fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28615,7 +27175,7 @@ pub fn vmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28679,7 +27239,7 @@ pub fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28709,7 +27269,7 @@ pub fn vmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -29085,7 +27645,7 @@ pub fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -29107,7 +27667,7 @@ pub fn vminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33043,7 +31603,7 @@ pub fn vmovn_u64(a: uint64x2_t) -> uint32x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33065,7 +31625,7 @@ pub fn vmul_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33130,7 +31690,7 @@ pub fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33159,7 +31719,7 @@ pub fn vmul_lane_f16(a: float16x4_t, v: float16x4_t) -> float16 #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -35131,7 +33691,7 @@ pub fn vmvnq_u8(a: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -35153,7 +33713,7 @@ pub fn vneg_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -36391,7 +34951,7 @@ pub fn vpadalq_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42473,7 +41033,7 @@ pub fn vraddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42503,7 +41063,7 @@ pub fn vrecpe_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42649,7 +41209,7 @@ pub fn vrecpeq_u32(a: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42679,7 +41239,7 @@ pub fn vrecps_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42768,7 +41328,7 @@ pub fn vrecpsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42791,7 +41351,7 @@ pub fn vreinterpret_f32_f16(a: float16x4_t) -> float32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42818,7 +41378,7 @@ pub fn vreinterpret_f32_f16(a: float16x4_t) -> float32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42841,7 +41401,7 @@ pub fn vreinterpret_s8_f16(a: float16x4_t) -> int8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42868,7 +41428,7 @@ pub fn vreinterpret_s8_f16(a: float16x4_t) -> int8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42891,7 +41451,7 @@ pub fn vreinterpret_s16_f16(a: float16x4_t) -> int16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42918,7 +41478,7 @@ pub fn vreinterpret_s16_f16(a: float16x4_t) -> int16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42941,7 +41501,7 @@ pub fn vreinterpret_s32_f16(a: float16x4_t) -> int32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42968,7 +41528,7 @@ pub fn vreinterpret_s32_f16(a: float16x4_t) -> int32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42991,7 +41551,7 @@ pub fn vreinterpret_s64_f16(a: float16x4_t) -> int64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43015,7 +41575,7 @@ pub fn vreinterpret_s64_f16(a: float16x4_t) -> int64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43038,7 +41598,7 @@ pub fn vreinterpret_u8_f16(a: float16x4_t) -> uint8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43065,7 +41625,7 @@ pub fn vreinterpret_u8_f16(a: float16x4_t) -> uint8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43088,7 +41648,7 @@ pub fn vreinterpret_u16_f16(a: float16x4_t) -> uint16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43115,7 +41675,7 @@ pub fn vreinterpret_u16_f16(a: float16x4_t) -> uint16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43138,7 +41698,7 @@ pub fn vreinterpret_u32_f16(a: float16x4_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43165,7 +41725,7 @@ pub fn vreinterpret_u32_f16(a: float16x4_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43188,7 +41748,7 @@ pub fn vreinterpret_u64_f16(a: float16x4_t) -> uint64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43212,7 +41772,7 @@ pub fn vreinterpret_u64_f16(a: float16x4_t) -> uint64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43235,7 +41795,7 @@ pub fn vreinterpret_p8_f16(a: float16x4_t) -> poly8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43262,7 +41822,7 @@ pub fn vreinterpret_p8_f16(a: float16x4_t) -> poly8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43285,7 +41845,7 @@ pub fn vreinterpret_p16_f16(a: float16x4_t) -> poly16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43312,7 +41872,7 @@ pub fn vreinterpret_p16_f16(a: float16x4_t) -> poly16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43335,7 +41895,7 @@ pub fn vreinterpretq_f32_f16(a: float16x8_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43362,7 +41922,7 @@ pub fn vreinterpretq_f32_f16(a: float16x8_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43385,7 +41945,7 @@ pub fn vreinterpretq_s8_f16(a: float16x8_t) -> int8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43416,7 +41976,7 @@ pub fn vreinterpretq_s8_f16(a: float16x8_t) -> int8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43439,7 +41999,7 @@ pub fn vreinterpretq_s16_f16(a: float16x8_t) -> int16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43466,7 +42026,7 @@ pub fn vreinterpretq_s16_f16(a: float16x8_t) -> int16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43489,7 +42049,7 @@ pub fn vreinterpretq_s32_f16(a: float16x8_t) -> int32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43516,7 +42076,7 @@ pub fn vreinterpretq_s32_f16(a: float16x8_t) -> int32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43539,7 +42099,7 @@ pub fn vreinterpretq_s64_f16(a: float16x8_t) -> int64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43566,7 +42126,7 @@ pub fn vreinterpretq_s64_f16(a: float16x8_t) -> int64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43589,7 +42149,7 @@ pub fn vreinterpretq_u8_f16(a: float16x8_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43620,7 +42180,7 @@ pub fn vreinterpretq_u8_f16(a: float16x8_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43643,7 +42203,7 @@ pub fn vreinterpretq_u16_f16(a: float16x8_t) -> uint16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43670,7 +42230,7 @@ pub fn vreinterpretq_u16_f16(a: float16x8_t) -> uint16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43693,7 +42253,7 @@ pub fn vreinterpretq_u32_f16(a: float16x8_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43720,7 +42280,7 @@ pub fn vreinterpretq_u32_f16(a: float16x8_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43743,7 +42303,7 @@ pub fn vreinterpretq_u64_f16(a: float16x8_t) -> uint64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43770,7 +42330,7 @@ pub fn vreinterpretq_u64_f16(a: float16x8_t) -> uint64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43793,7 +42353,7 @@ pub fn vreinterpretq_p8_f16(a: float16x8_t) -> poly8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43824,7 +42384,7 @@ pub fn vreinterpretq_p8_f16(a: float16x8_t) -> poly8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43847,7 +42407,7 @@ pub fn vreinterpretq_p16_f16(a: float16x8_t) -> poly16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43874,7 +42434,7 @@ pub fn vreinterpretq_p16_f16(a: float16x8_t) -> poly16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43897,7 +42457,7 @@ pub fn vreinterpret_f16_f32(a: float32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43924,7 +42484,7 @@ pub fn vreinterpret_f16_f32(a: float32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43947,7 +42507,7 @@ pub fn vreinterpretq_f16_f32(a: float32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43974,7 +42534,7 @@ pub fn vreinterpretq_f16_f32(a: float32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43997,7 +42557,7 @@ pub fn vreinterpret_f16_s8(a: int8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44024,7 +42584,7 @@ pub fn vreinterpret_f16_s8(a: int8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44047,7 +42607,7 @@ pub fn vreinterpretq_f16_s8(a: int8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44075,7 +42635,7 @@ pub fn vreinterpretq_f16_s8(a: int8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44098,7 +42658,7 @@ pub fn vreinterpret_f16_s16(a: int16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44125,7 +42685,7 @@ pub fn vreinterpret_f16_s16(a: int16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44148,7 +42708,7 @@ pub fn vreinterpretq_f16_s16(a: int16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44175,7 +42735,7 @@ pub fn vreinterpretq_f16_s16(a: int16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44198,7 +42758,7 @@ pub fn vreinterpret_f16_s32(a: int32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44225,7 +42785,7 @@ pub fn vreinterpret_f16_s32(a: int32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44248,7 +42808,7 @@ pub fn vreinterpretq_f16_s32(a: int32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44275,7 +42835,7 @@ pub fn vreinterpretq_f16_s32(a: int32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44298,7 +42858,7 @@ pub fn vreinterpret_f16_s64(a: int64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44324,7 +42884,7 @@ pub fn vreinterpret_f16_s64(a: int64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44347,7 +42907,7 @@ pub fn vreinterpretq_f16_s64(a: int64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44374,7 +42934,7 @@ pub fn vreinterpretq_f16_s64(a: int64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44397,7 +42957,7 @@ pub fn vreinterpret_f16_u8(a: uint8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44424,7 +42984,7 @@ pub fn vreinterpret_f16_u8(a: uint8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44447,7 +43007,7 @@ pub fn vreinterpretq_f16_u8(a: uint8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44475,7 +43035,7 @@ pub fn vreinterpretq_f16_u8(a: uint8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44498,7 +43058,7 @@ pub fn vreinterpret_f16_u16(a: uint16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44525,7 +43085,7 @@ pub fn vreinterpret_f16_u16(a: uint16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44548,7 +43108,7 @@ pub fn vreinterpretq_f16_u16(a: uint16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44575,7 +43135,7 @@ pub fn vreinterpretq_f16_u16(a: uint16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44598,7 +43158,7 @@ pub fn vreinterpret_f16_u32(a: uint32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44625,7 +43185,7 @@ pub fn vreinterpret_f16_u32(a: uint32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44648,7 +43208,7 @@ pub fn vreinterpretq_f16_u32(a: uint32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44675,7 +43235,7 @@ pub fn vreinterpretq_f16_u32(a: uint32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44698,7 +43258,7 @@ pub fn vreinterpret_f16_u64(a: uint64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44724,7 +43284,7 @@ pub fn vreinterpret_f16_u64(a: uint64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44747,7 +43307,7 @@ pub fn vreinterpretq_f16_u64(a: uint64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44774,7 +43334,7 @@ pub fn vreinterpretq_f16_u64(a: uint64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44797,7 +43357,7 @@ pub fn vreinterpret_f16_p8(a: poly8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44824,7 +43384,7 @@ pub fn vreinterpret_f16_p8(a: poly8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44847,7 +43407,7 @@ pub fn vreinterpretq_f16_p8(a: poly8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44875,7 +43435,7 @@ pub fn vreinterpretq_f16_p8(a: poly8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44898,7 +43458,7 @@ pub fn vreinterpret_f16_p16(a: poly16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44925,7 +43485,7 @@ pub fn vreinterpret_f16_p16(a: poly16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44948,7 +43508,7 @@ pub fn vreinterpretq_f16_p16(a: poly16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44975,7 +43535,7 @@ pub fn vreinterpretq_f16_p16(a: poly16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44998,7 +43558,7 @@ pub fn vreinterpretq_f16_p128(a: p128) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45024,7 +43584,7 @@ pub fn vreinterpretq_f16_p128(a: p128) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45047,7 +43607,7 @@ pub fn vreinterpret_p64_f16(a: float16x4_t) -> poly64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45071,7 +43631,7 @@ pub fn vreinterpret_p64_f16(a: float16x4_t) -> poly64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45094,7 +43654,7 @@ pub fn vreinterpretq_p128_f16(a: float16x8_t) -> p128 { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45118,7 +43678,7 @@ pub fn vreinterpretq_p128_f16(a: float16x8_t) -> p128 { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45141,7 +43701,7 @@ pub fn vreinterpretq_p64_f16(a: float16x8_t) -> poly64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45168,7 +43728,7 @@ pub fn vreinterpretq_p64_f16(a: float16x8_t) -> poly64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45191,7 +43751,7 @@ pub fn vreinterpret_f16_p64(a: poly64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45217,7 +43777,7 @@ pub fn vreinterpret_f16_p64(a: poly64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45240,7 +43800,7 @@ pub fn vreinterpretq_f16_p64(a: poly64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59244,7 +57804,7 @@ pub fn vrev64q_u8(a: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59266,7 +57826,7 @@ pub fn vrev64_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59636,7 +58196,7 @@ pub fn vrhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59665,7 +58225,7 @@ pub fn vrndn_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60756,7 +59316,7 @@ pub fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60786,7 +59346,7 @@ pub fn vrsqrte_f16(a: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60932,7 +59492,7 @@ pub fn vrsqrteq_u32(a: uint32x4_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60962,7 +59522,7 @@ pub fn vrsqrts_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -72516,7 +71076,7 @@ pub unsafe fn vstrq_p128(a: *mut p128, b: p128) { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -72538,7 +71098,7 @@ pub fn vsub_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -74519,7 +73079,7 @@ pub fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -74549,7 +73109,7 @@ pub fn vtrn_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -75832,7 +74392,7 @@ pub fn vusmmlaq_s32(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -75862,7 +74422,7 @@ pub fn vuzp_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -76438,7 +74998,7 @@ pub fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -76468,7 +75028,7 @@ pub fn vzip_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs index 1ca8ce2b1395..8a4a6e922822 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs @@ -104,7 +104,7 @@ types! { } types! { - #![cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION"))] + #![cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "1.94.0"))] #![cfg_attr(target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800"))] /// Arm-specific 64-bit wide vector of four packed `f16`. @@ -750,7 +750,7 @@ pub struct uint32x4x4_t( #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -763,7 +763,7 @@ pub struct float16x4x2_t(pub float16x4_t, pub float16x4_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -776,7 +776,7 @@ pub struct float16x4x3_t(pub float16x4_t, pub float16x4_t, pub float16x4_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -794,7 +794,7 @@ pub struct float16x4x4_t( #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -807,7 +807,7 @@ pub struct float16x8x2_t(pub float16x8_t, pub float16x8_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -820,7 +820,7 @@ pub struct float16x8x3_t(pub float16x8_t, pub float16x8_t, pub float16x8_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 3992eaee30fd..039a4c4411f2 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -33,7 +33,6 @@ f16, aarch64_unstable_target_feature, target_feature_inline_always, - bigint_helper_methods, funnel_shifts, avx10_target_feature, const_trait_impl, diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2..f68121ad3171 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -47,6 +47,54 @@ types! { pub struct vector_float(4 x f32); } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.lvx"] @@ -129,8 +177,6 @@ unsafe extern "C" { b: vector_signed_short, c: vector_signed_int, ) -> vector_signed_int; - #[link_name = "llvm.ppc.altivec.vnmsubfp"] - fn vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float; #[link_name = "llvm.ppc.altivec.vsum2sws"] fn vsum2sws(a: vector_signed_int, b: vector_signed_int) -> vector_signed_int; #[link_name = "llvm.ppc.altivec.vsum4ubs"] @@ -1881,9 +1927,9 @@ mod sealed { #[inline] #[target_feature(enable = "altivec")] - #[cfg_attr(test, assert_instr(vnmsubfp))] - unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + #[cfg_attr(test, assert_instr(xvnmsubasp))] + pub unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { + simd_neg(simd_fma(a, b, simd_neg(c))) } #[inline] @@ -3249,7 +3295,7 @@ mod sealed { unsafe fn vec_round(self) -> Self; } - test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, xvrspic] } + test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, vrfin] } #[unstable(feature = "stdarch_powerpc", issue = "111145")] impl VectorRound for vector_float { @@ -4281,7 +4327,7 @@ pub unsafe fn vec_madd(a: vector_float, b: vector_float, c: vector_float) -> vec #[target_feature(enable = "altivec")] #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub unsafe fn vec_nmsub(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + sealed::vec_vnmsubfp(a, b, c) } /// Vector Select @@ -4653,22 +4699,22 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!($d, r); } } @@ -4677,11 +4723,11 @@ mod tests { macro_rules! test_vec_1 { { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); + fn $name() { + let a = vector_float::from(f32x4::new($($a),+)); - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); + let d = vector_float::from(f32x4::new($($d),+)); + let r = m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); } @@ -4691,18 +4737,18 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ld() { + fn test_vec_ld() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4711,14 +4757,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4729,7 +4775,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xl() { + fn test_vec_xl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4738,7 +4784,7 @@ mod tests { ]; for off in 0..16 { - let val: u8x16 = transmute(vec_xl(0, (pat.as_ptr() as *const u8).offset(off))); + let val = u8x16::from(unsafe { vec_xl(0, (pat.as_ptr() as *const u8).offset(off)) }); for i in 0..16 { let v = val.extract_dyn(i); assert_eq!(off as usize + i, v as usize); @@ -4747,14 +4793,16 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xst() { - let v: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_xst() { + let v = vector_unsigned_char::from(u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )); for off in 0..16 { let mut buf = [0u8; 32]; - vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + unsafe { + vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + } for i in 0..16 { assert_eq!(i as u8, buf[off as usize..][i]); } @@ -4762,7 +4810,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ldl() { + fn test_vec_ldl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4771,14 +4819,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4789,30 +4837,30 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u8() { + fn test_vec_lde_u8() { let pat = [u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )]; for off in 0..16 { - let v: u8x16 = transmute(vec_lde(off, pat.as_ptr() as *const u8)); + let v = u8x16::from(unsafe { vec_lde(off, pat.as_ptr() as *const u8) }); assert_eq!(off as u8, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u16() { + fn test_vec_lde_u16() { let pat = [u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)]; for off in 0..8 { - let v: u16x8 = transmute(vec_lde(off * 2, pat.as_ptr() as *const u16)); + let v = u16x8::from(unsafe { vec_lde(off * 2, pat.as_ptr() as *const u16) }); assert_eq!(off as u16, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u32() { + fn test_vec_lde_u32() { let pat = [u32x4::new(0, 1, 2, 3)]; for off in 0..4 { - let v: u32x4 = transmute(vec_lde(off * 4, pat.as_ptr() as *const u32)); + let v = u32x4::from(unsafe { vec_lde(off * 4, pat.as_ptr() as *const u32) }); assert_eq!(off as u32, v.extract_dyn(off as _)); } } @@ -5818,9 +5866,9 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cmpb() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); - let b: vector_float = transmute(f32x4::new(-0.1, 0.5, -0.6, 0.9)); + fn test_vec_cmpb() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); + let b = vector_float::from(f32x4::new(-0.1, 0.5, -0.6, 0.9)); let d = i32x4::new( -0b10000000000000000000000000000000, 0, @@ -5828,15 +5876,15 @@ mod tests { 0, ); - assert_eq!(d, transmute(vec_cmpb(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_cmpb(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ceil() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); + fn test_vec_ceil() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); let d = f32x4::new(1.0, 1.0, 1.0, 1.0); - assert_eq!(d, transmute(vec_ceil(a))); + assert_eq!(d, f32x4::from(unsafe { vec_ceil(a) })); } test_vec_2! { test_vec_andc, vec_andc, i32x4, @@ -5926,11 +5974,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5943,11 +5991,11 @@ mod tests { macro_rules! test_vec_abss { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abss(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abss(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5959,10 +6007,10 @@ mod tests { macro_rules! test_vec_splats { { $name: ident, $ty: ident, $a: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; let d = $ty::splat($a); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5978,10 +6026,10 @@ mod tests { macro_rules! test_vec_splat { { $name: ident, $fun: ident, $ty: ident, $a: expr, $b: expr} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = $fun::<$a>(); + fn $name() { + let a = unsafe { $fun::<$a>() }; let d = $ty::splat($b); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6073,12 +6121,12 @@ mod tests { macro_rules! test_vec_min { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_min(a, b)); + let r = $ty::from(unsafe { vec_min(a, b) }); assert_eq!(d, r); } } @@ -6117,12 +6165,12 @@ mod tests { macro_rules! test_vec_max { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_max(a, b)); + let r = $ty::from(unsafe { vec_max(a, b) }); assert_eq!(d, r); } } @@ -6163,13 +6211,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6249,8 +6297,8 @@ mod tests { [0.0, 1.0, 1.0, 1.1]} #[simd_test(enable = "altivec")] - unsafe fn test_vec_madds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_madds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6260,19 +6308,19 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, 21); - assert_eq!(d, transmute(vec_madds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_madds(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_madd_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_madd_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( 0.1 * 0.1 + 0.1, 0.2 * 0.2 + 0.2, @@ -6280,26 +6328,26 @@ mod tests { 0.4 * 0.4 + 0.4, ); - assert_eq!(d, transmute(vec_madd(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_madd(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_nmsub_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_nmsub_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( -(0.1 * 0.1 - 0.1), -(0.2 * 0.2 - 0.2), -(0.3 * 0.3 - 0.3), -(0.4 * 0.4 - 0.4), ); - assert_eq!(d, transmute(vec_nmsub(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_nmsub(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mradds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_mradds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6309,25 +6357,25 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, i16::MAX); - assert_eq!(d, transmute(vec_mradds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_mradds(a, b, c) })); } macro_rules! test_vec_mladd { {$name:ident, $sa:ident, $la:ident, $sbc:ident, $lbc:ident, $sd:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $la = transmute($sa::new($($a),+)); - let b: $lbc = transmute($sbc::new($($b),+)); - let c = transmute($sbc::new($($c),+)); + fn $name() { + let a = $la::from($sa::new($($a),+)); + let b = $lbc::from($sbc::new($($b),+)); + let c = $sbc::new($($c),+).into(); let d = $sd::new($($d),+); - assert_eq!(d, transmute(vec_mladd(a, b, c))); + assert_eq!(d, $sd::from(unsafe { vec_mladd(a, b, c) })); } } } @@ -6335,24 +6383,24 @@ mod tests { test_vec_mladd! { test_vec_mladd_u16x8_u16x8, u16x8, vector_unsigned_short, u16x8, vector_unsigned_short, u16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } test_vec_mladd! { test_vec_mladd_i16x8_u16x8, i16x8, vector_signed_short, u16x8, vector_unsigned_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_msum_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_char::from(u8x16::new( 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, )); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1 + 2 + 3) * 255 + 0, (4 + 5 + 6 + 7) * 255 + 1, @@ -6360,17 +6408,17 @@ mod tests { (4 + 5 + 6 + 7) * 255 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_msum_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, -1, 2, -3, 1, -1, 1, -1, 0, 1, 2, 3, 4, -5, -6, -7, )); - let b: vector_unsigned_char = - transmute(i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - let c: vector_signed_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = + vector_unsigned_char::from(u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1 + 2 - 3) + 0, (0) + 1, @@ -6378,11 +6426,12 @@ mod tests { (4 - 5 - 6 - 7) + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } + #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msum_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6392,9 +6441,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6402,12 +6450,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_short() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msum_signed_short() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6417,8 +6465,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6426,12 +6474,12 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_unsigned() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msums_unsigned() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6441,9 +6489,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6451,12 +6498,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_signed() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msums_signed() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6466,8 +6513,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6475,23 +6522,23 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum2s() { - let a: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum2s() { + let a = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0, 0 + 1 + 1, 0, 2 + 3 + 3); - assert_eq!(d, transmute(vec_sum2s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum2s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6499,13 +6546,13 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, u32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_char() { - let a: vector_signed_char = - transmute(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_char() { + let a = + vector_signed_char::from(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6513,109 +6560,110 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0 + 1 + 0, 2 + 3 + 1, 4 + 5 + 2, 6 + 7 + 3); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mule_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mule_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mulo_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mulo_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn vec_add_i32x4_i32x4() { + fn vec_add_i32x4_i32x4() { let x = i32x4::new(1, 2, 3, 4); let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + let x = vector_signed_int::from(x); + let y = vector_signed_int::from(y); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_u32() { - let v: vector_unsigned_int = transmute(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = transmute(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); + fn vec_ctf_u32() { + let v = vector_unsigned_int::from(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); }; @@ -6626,26 +6674,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ctu() { + fn test_vec_ctu() { let v = u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42); - let v2: u32x4 = transmute(vec_ctu::<1>(transmute(f32x4::new( - 0.0, - 2147483600.0, - 2147483600.0, - 21.0, - )))); - let v4: u32x4 = transmute(vec_ctu::<2>(transmute(f32x4::new( - 0.0, - 1073741800.0, - 1073741800.0, - 10.5, - )))); - let v8: u32x4 = transmute(vec_ctu::<3>(transmute(f32x4::new( - 0.0, - 536870900.0, - 536870900.0, - 5.25, - )))); + let v2 = u32x4::from(unsafe { + vec_ctu::<1>(vector_float::from(f32x4::new( + 0.0, + 2147483600.0, + 2147483600.0, + 21.0, + ))) + }); + let v4 = u32x4::from(unsafe { + vec_ctu::<2>(vector_float::from(f32x4::new( + 0.0, + 1073741800.0, + 1073741800.0, + 10.5, + ))) + }); + let v8 = u32x4::from(unsafe { + vec_ctu::<3>(vector_float::from(f32x4::new( + 0.0, + 536870900.0, + 536870900.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); @@ -6653,18 +6707,18 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_i32() { - let v: vector_signed_int = transmute(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = - transmute(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); + fn vec_ctf_i32() { + let v = vector_signed_int::from(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); println!("{:?} {:?}", a, b); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); @@ -6676,26 +6730,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cts() { + fn test_vec_cts() { let v = i32x4::new(i32::MIN, i32::MAX, i32::MAX, 42); - let v2: i32x4 = transmute(vec_cts::<1>(transmute(f32x4::new( - -1073741800.0, - 1073741800.0, - 1073741800.0, - 21.0, - )))); - let v4: i32x4 = transmute(vec_cts::<2>(transmute(f32x4::new( - -536870900.0, - 536870900.0, - 536870900.0, - 10.5, - )))); - let v8: i32x4 = transmute(vec_cts::<3>(transmute(f32x4::new( - -268435460.0, - 268435460.0, - 268435460.0, - 5.25, - )))); + let v2 = i32x4::from(unsafe { + vec_cts::<1>(transmute(f32x4::new( + -1073741800.0, + 1073741800.0, + 1073741800.0, + 21.0, + ))) + }); + let v4 = i32x4::from(unsafe { + vec_cts::<2>(transmute(f32x4::new( + -536870900.0, + 536870900.0, + 536870900.0, + 10.5, + ))) + }); + let v8 = i32x4::from(unsafe { + vec_cts::<3>(transmute(f32x4::new( + -268435460.0, + 268435460.0, + 268435460.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); diff --git a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs index ca9fcaabe8b2..0aac23617340 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs @@ -9,6 +9,7 @@ #![allow(non_camel_case_types)] use crate::core_arch::powerpc::*; +use crate::core_arch::simd::*; #[cfg(test)] use stdarch_test::assert_instr; @@ -34,6 +35,22 @@ types! { // pub struct vector_unsigned___int128 = i128x1; } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_long { + #[inline] + fn from(value: m64x2) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m64x2 { + #[inline] + fn from(value: vector_bool_long) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.vperm"] @@ -46,7 +63,6 @@ unsafe extern "C" { mod sealed { use super::*; - use crate::core_arch::simd::*; #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorPermDI { @@ -221,14 +237,16 @@ mod tests { macro_rules! test_vec_xxpermdi { {$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vsx")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+, $($b),+)); - let b = transmute($shorttype::new($($c),+, $($d),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+, $($b),+)); + let b = $longtype::from($shorttype::new($($c),+, $($d),+)); - assert_eq!($shorttype::new($($a),+, $($c),+), transmute(vec_xxpermdi::<_, 0>(a, b))); - assert_eq!($shorttype::new($($b),+, $($c),+), transmute(vec_xxpermdi::<_, 1>(a, b))); - assert_eq!($shorttype::new($($a),+, $($d),+), transmute(vec_xxpermdi::<_, 2>(a, b))); - assert_eq!($shorttype::new($($b),+, $($d),+), transmute(vec_xxpermdi::<_, 3>(a, b))); + unsafe { + assert_eq!($shorttype::new($($a),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 0>(a, b))); + assert_eq!($shorttype::new($($b),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 1>(a, b))); + assert_eq!($shorttype::new($($a),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 2>(a, b))); + assert_eq!($shorttype::new($($b),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 3>(a, b))); + } } } } diff --git a/library/stdarch/crates/core_arch/src/s390x/mod.rs b/library/stdarch/crates/core_arch/src/s390x/mod.rs index 7d3b3f2d99aa..5b85020072d8 100644 --- a/library/stdarch/crates/core_arch/src/s390x/mod.rs +++ b/library/stdarch/crates/core_arch/src/s390x/mod.rs @@ -2,6 +2,11 @@ pub(crate) mod macros; +/// the float and vector registers overlap therefore we cannot use any vector +/// extensions if softfloat is enabled. + +#[cfg(not(target_abi = "softfloat"))] mod vector; +#[cfg(not(target_abi = "softfloat"))] #[unstable(feature = "stdarch_s390x", issue = "130869")] pub use self::vector::*; diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index e1f841030c00..346cd674df66 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -51,6 +51,54 @@ types! { pub struct vector_double(2 x f64); } +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[repr(C, packed)] struct PackedTuple { x: T, @@ -6051,27 +6099,16 @@ mod tests { } macro_rules! test_vec_1 { - { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); - - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); - let e = m32x4::new(true, true, true, true); - assert_eq!(e, r); - } - }; { $name: ident, $fn:ident, $ty: ident, [$($a:expr),+], [$($d:expr),+] } => { test_vec_1! { $name, $fn, $ty -> $ty, [$($a),+], [$($d),+] } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } @@ -6086,35 +6123,23 @@ mod tests { }; { $name: ident, $fn:ident, $ty1: ident, $ty2: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty1) = transmute($ty1::new($($a),+)); - let b: s_t_l!($ty2) = transmute($ty2::new($($b),+)); + fn $name() { + let a: s_t_l!($ty1) = $ty1::new($($a),+).into(); + let b: s_t_l!($ty2) = $ty2::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; - { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); - - let r : $ty_out = transmute($fn(a, b)); - assert_eq!($d, r); - } - } } #[simd_test(enable = "vector")] - unsafe fn vec_add_i32x4_i32x4() { - let x = i32x4::new(1, 2, 3, 4); - let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + fn vec_add_i32x4_i32x4() { + let x = vector_signed_int::from(i32x4::new(1, 2, 3, 4)); + let y = vector_signed_int::from(i32x4::new(4, 3, 2, 1)); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } macro_rules! test_vec_sub { @@ -6232,11 +6257,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6386,7 +6411,7 @@ mod tests { [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } - test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> i32x4, + test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> u32x4, [0b1000, 0b1000, 0b1000, 0b1000], [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } @@ -6423,13 +6448,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6512,46 +6537,46 @@ mod tests { [core::f32::consts::PI, 1.0, 25.0, 2.0], [core::f32::consts::PI.sqrt(), 1.0, 5.0, core::f32::consts::SQRT_2] } - test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0, 0, 0xFFFFFFFF, 0] + [0, 0, !0, 0] } - test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0xFFFFFFFF, 0xFFFFFFFF, 0, 0xFFFFFFFF] + [!0, !0, 0, !0] } - test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 3, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 6, 7, 8], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 5, 3, 4], [0, 4, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 2, 3, 4], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [5, 6, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [1, 2, 3, 4], [0, 8, 0, 0] diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs index c864d6a516e0..e1a375496590 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs @@ -86,10 +86,6 @@ unsafe extern "unadjusted" { fn llvm_i8x16_all_true(x: simd::i8x16) -> i32; #[link_name = "llvm.wasm.bitmask.v16i8"] fn llvm_bitmask_i8x16(a: simd::i8x16) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v16i8.v8i16"] - fn llvm_narrow_i8x16_s(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; - #[link_name = "llvm.wasm.narrow.unsigned.v16i8.v8i16"] - fn llvm_narrow_i8x16_u(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; #[link_name = "llvm.wasm.avgr.unsigned.v16i8"] fn llvm_avgr_u_i8x16(a: simd::i8x16, b: simd::i8x16) -> simd::i8x16; @@ -103,10 +99,6 @@ unsafe extern "unadjusted" { fn llvm_i16x8_all_true(x: simd::i16x8) -> i32; #[link_name = "llvm.wasm.bitmask.v8i16"] fn llvm_bitmask_i16x8(a: simd::i16x8) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v8i16.v4i32"] - fn llvm_narrow_i16x8_s(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; - #[link_name = "llvm.wasm.narrow.unsigned.v8i16.v4i32"] - fn llvm_narrow_i16x8_u(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; #[link_name = "llvm.wasm.avgr.unsigned.v8i16"] fn llvm_avgr_u_i16x8(a: simd::i16x8, b: simd::i16x8) -> simd::i16x8; @@ -2281,7 +2273,23 @@ pub use i8x16_bitmask as u8x16_bitmask; #[doc(alias("i8x16.narrow_i16x8_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_s(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::i8x16 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2295,7 +2303,23 @@ pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { #[doc(alias("i8x16.narrow_i16x8_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_u(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::u8x16 = simd_cast(v); + + v.v128() + } } /// Shifts each lane to the left by the specified number of bits. @@ -2593,7 +2617,19 @@ pub use i16x8_bitmask as u16x8_bitmask; #[doc(alias("i16x8.narrow_i32x4_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_s(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::i16x8 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2607,7 +2643,19 @@ pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { #[doc(alias("i16x8.narrow_i32x4_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_u(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::u16x8 = simd_cast(v); + + v.v128() + } } /// Converts low half of the smaller lane vector to a larger lane diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index 7b4b210bacf4..74fc2db13dcd 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -2426,7 +2426,6 @@ pub const fn _mm256_setzero_si256() -> __m256i { #[inline] #[target_feature(enable = "avx")] // This intrinsic has no corresponding instruction. -#[cfg_attr(test, assert_instr(vinsertf128))] #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_set_pd(a: f64, b: f64, c: f64, d: f64) -> __m256d { diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 6a39a0aaf8fe..04a88e461f75 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -991,7 +991,21 @@ pub const fn _mm256_hadd_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hadds_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phaddsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_add(even, odd).as_m256i() + } } /// Horizontally subtract adjacent pairs of 16-bit integers in `a` and `b`. @@ -1047,7 +1061,21 @@ pub const fn _mm256_hsub_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hsubs_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phsubsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_sub(even, odd).as_m256i() + } } /// Returns values from `slice` at offsets determined by `offsets * scale`, @@ -3791,10 +3819,6 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.x86.avx2.phadd.sw"] - fn phaddsw(a: i16x16, b: i16x16) -> i16x16; - #[link_name = "llvm.x86.avx2.phsub.sw"] - fn phsubsw(a: i16x16, b: i16x16) -> i16x16; #[link_name = "llvm.x86.avx2.pmadd.wd"] fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] @@ -4653,6 +4677,26 @@ mod tests { assert_eq_m256i(r, e); } + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_mul_one(v: __m256i) -> __m256i { + // This is a trick used in the adler32 algorithm to get a widening addition. The + // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd + // instruction is no longer selected. The assert_instr verifies that this is the case. + let one_v = _mm256_set1_epi16(1); + _mm256_madd_epi16(v, one_v) + } + + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_shl(v: __m256i) -> __m256i { + // This is a trick used in the base64 algorithm to get a widening addition. Instead of a + // multiplication, a vector shl is used. In LLVM 22 that breaks the pattern recognition + // for the automatic optimization to vpmaddwd. + let shift_value = _mm256_set1_epi32(12i32); + _mm256_madd_epi16(v, shift_value) + } + #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8e074fdcfa48..3ba171c0fa50 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -12476,7 +12476,14 @@ pub unsafe fn _mm512_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32, #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovswb))] pub unsafe fn _mm256_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { - vpmovswbmem256(mem_addr, a.as_i16x16(), k); + let mask = simd_select_bitmask(k, i16x16::splat(!0), i16x16::ZERO); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_imax(simd_imin(a.as_i16x16(), max), min); + let truncated: i8x16 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12487,7 +12494,14 @@ pub unsafe fn _mm256_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovswb))] pub unsafe fn _mm_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { - vpmovswbmem128(mem_addr, a.as_i16x8(), k); + let mask = simd_select_bitmask(k, i16x8::splat(!0), i16x8::ZERO); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_imax(simd_imin(a.as_i16x8(), max), min); + let truncated: i8x8 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12555,7 +12569,12 @@ pub unsafe fn _mm512_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32 #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovuswb))] pub unsafe fn _mm256_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { - vpmovuswbmem256(mem_addr, a.as_i16x16(), k); + let mask = simd_select_bitmask(k, i16x16::splat(!0), i16x16::ZERO); + let mem_addr = mem_addr.cast::(); + let max = simd_splat(u16::from(u8::MAX)); + + let truncated: u8x16 = simd_cast(simd_imin(a.as_u16x16(), max)); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12566,7 +12585,15 @@ pub unsafe fn _mm256_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16 #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovuswb))] pub unsafe fn _mm_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { - vpmovuswbmem128(mem_addr, a.as_i16x8(), k); + let mask = simd_select_bitmask(k, i16x8::splat(!0), i16x8::ZERO); + let mem_addr = mem_addr.cast::(); + let max = simd_splat(u16::from(u8::MAX)); + + let v = a.as_u16x8(); + let v = simd_imin(v, max); + + let truncated: u8x8 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } #[allow(improper_ctypes)] @@ -12632,17 +12659,9 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.512"] fn vpmovswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); - #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.256"] - fn vpmovswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); - #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.128"] - fn vpmovswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.512"] fn vpmovuswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); - #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.256"] - fn vpmovuswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); - #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.128"] - fn vpmovuswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); } #[cfg(test)] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs index 27f06691c550..8ddc3d29a3a1 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs @@ -247,7 +247,7 @@ pub const fn _mm512_setr_ph( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_setzero_ph() -> __m128h { unsafe { transmute(f16x8::ZERO) } @@ -258,7 +258,7 @@ pub const fn _mm_setzero_ph() -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_setzero_ph() -> __m256h { f16x16::ZERO.as_m256h() @@ -269,7 +269,7 @@ pub const fn _mm256_setzero_ph() -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_setzero_ph() -> __m512h { f16x32::ZERO.as_m512h() @@ -283,7 +283,7 @@ pub const fn _mm512_setzero_ph() -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_undefined_ph() -> __m128h { f16x8::ZERO.as_m128h() @@ -297,7 +297,7 @@ pub const fn _mm_undefined_ph() -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_undefined_ph() -> __m256h { f16x16::ZERO.as_m256h() @@ -311,7 +311,7 @@ pub const fn _mm256_undefined_ph() -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_undefined_ph() -> __m512h { f16x32::ZERO.as_m512h() @@ -323,7 +323,7 @@ pub const fn _mm512_undefined_ph() -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castpd_ph(a: __m128d) -> __m128h { unsafe { transmute(a) } @@ -335,7 +335,7 @@ pub const fn _mm_castpd_ph(a: __m128d) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castpd_ph(a: __m256d) -> __m256h { unsafe { transmute(a) } @@ -347,7 +347,7 @@ pub const fn _mm256_castpd_ph(a: __m256d) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castpd_ph(a: __m512d) -> __m512h { unsafe { transmute(a) } @@ -359,7 +359,7 @@ pub const fn _mm512_castpd_ph(a: __m512d) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_pd(a: __m128h) -> __m128d { unsafe { transmute(a) } @@ -371,7 +371,7 @@ pub const fn _mm_castph_pd(a: __m128h) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_pd(a: __m256h) -> __m256d { unsafe { transmute(a) } @@ -383,7 +383,7 @@ pub const fn _mm256_castph_pd(a: __m256h) -> __m256d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_pd(a: __m512h) -> __m512d { unsafe { transmute(a) } @@ -395,7 +395,7 @@ pub const fn _mm512_castph_pd(a: __m512h) -> __m512d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castps_ph(a: __m128) -> __m128h { unsafe { transmute(a) } @@ -407,7 +407,7 @@ pub const fn _mm_castps_ph(a: __m128) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castps_ph(a: __m256) -> __m256h { unsafe { transmute(a) } @@ -419,7 +419,7 @@ pub const fn _mm256_castps_ph(a: __m256) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castps_ph(a: __m512) -> __m512h { unsafe { transmute(a) } @@ -431,7 +431,7 @@ pub const fn _mm512_castps_ph(a: __m512) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_ps(a: __m128h) -> __m128 { unsafe { transmute(a) } @@ -443,7 +443,7 @@ pub const fn _mm_castph_ps(a: __m128h) -> __m128 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_ps(a: __m256h) -> __m256 { unsafe { transmute(a) } @@ -455,7 +455,7 @@ pub const fn _mm256_castph_ps(a: __m256h) -> __m256 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_ps(a: __m512h) -> __m512 { unsafe { transmute(a) } @@ -467,7 +467,7 @@ pub const fn _mm512_castph_ps(a: __m512h) -> __m512 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castsi128_ph(a: __m128i) -> __m128h { unsafe { transmute(a) } @@ -479,7 +479,7 @@ pub const fn _mm_castsi128_ph(a: __m128i) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castsi256_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castsi256_ph(a: __m256i) -> __m256h { unsafe { transmute(a) } @@ -491,7 +491,7 @@ pub const fn _mm256_castsi256_ph(a: __m256i) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castsi512_ph(a: __m512i) -> __m512h { unsafe { transmute(a) } @@ -503,7 +503,7 @@ pub const fn _mm512_castsi512_ph(a: __m512i) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_si128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_si128(a: __m128h) -> __m128i { unsafe { transmute(a) } @@ -515,7 +515,7 @@ pub const fn _mm_castph_si128(a: __m128h) -> __m128i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_si256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_si256(a: __m256h) -> __m256i { unsafe { transmute(a) } @@ -527,7 +527,7 @@ pub const fn _mm256_castph_si256(a: __m256h) -> __m256i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_si512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_si512(a: __m512h) -> __m512i { unsafe { transmute(a) } @@ -539,7 +539,7 @@ pub const fn _mm512_castph_si512(a: __m512h) -> __m512i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph256_ph128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph256_ph128(a: __m256h) -> __m128h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -551,7 +551,7 @@ pub const fn _mm256_castph256_ph128(a: __m256h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph512_ph128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph512_ph128(a: __m512h) -> __m128h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -563,7 +563,7 @@ pub const fn _mm512_castph512_ph128(a: __m512h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph512_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph512_ph256(a: __m512h) -> __m256h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } @@ -576,7 +576,7 @@ pub const fn _mm512_castph512_ph256(a: __m512h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph128_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph128_ph256(a: __m128h) -> __m256h { unsafe { @@ -595,7 +595,7 @@ pub const fn _mm256_castph128_ph256(a: __m128h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph128_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph128_ph512(a: __m128h) -> __m512h { unsafe { @@ -617,7 +617,7 @@ pub const fn _mm512_castph128_ph512(a: __m128h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph256_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph256_ph512(a: __m256h) -> __m512h { unsafe { @@ -639,7 +639,7 @@ pub const fn _mm512_castph256_ph512(a: __m256h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_zextph128_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_zextph128_ph256(a: __m128h) -> __m256h { unsafe { @@ -658,7 +658,7 @@ pub const fn _mm256_zextph128_ph256(a: __m128h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextph256_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_zextph256_ph512(a: __m256h) -> __m512h { unsafe { @@ -680,7 +680,7 @@ pub const fn _mm512_zextph256_ph512(a: __m256h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextph128_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_zextph128_ph512(a: __m128h) -> __m512h { unsafe { @@ -730,7 +730,7 @@ macro_rules! cmp_asm { // FIXME: use LLVM intrinsics #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_ph_mask(a: __m128h, b: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -746,7 +746,7 @@ pub fn _mm_cmp_ph_mask(a: __m128h, b: __m128h) -> __mmask8 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_ph_mask(k1: __mmask8, a: __m128h, b: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -761,7 +761,7 @@ pub fn _mm_mask_cmp_ph_mask(k1: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cmp_ph_mask(a: __m256h, b: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -777,7 +777,7 @@ pub fn _mm256_cmp_ph_mask(a: __m256h, b: __m256h) -> __mmask16 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cmp_ph_mask( k1: __mmask16, a: __m256h, @@ -796,7 +796,7 @@ pub fn _mm256_mask_cmp_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmp_ph_mask(a: __m512h, b: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -812,7 +812,7 @@ pub fn _mm512_cmp_ph_mask(a: __m512h, b: __m512h) -> __mmask32 #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmp_ph_mask( k1: __mmask32, a: __m512h, @@ -833,7 +833,7 @@ pub fn _mm512_mask_cmp_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmp_round_ph_mask( a: __m512h, b: __m512h, @@ -868,7 +868,7 @@ pub fn _mm512_cmp_round_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmp_round_ph_mask( k1: __mmask32, a: __m512h, @@ -903,7 +903,7 @@ pub fn _mm512_mask_cmp_round_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_round_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); static_assert_sae!(SAE); @@ -918,7 +918,7 @@ pub fn _mm_cmp_round_sh_mask(a: __m128h, b: __m #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_round_sh_mask( k1: __mmask8, a: __m128h, @@ -938,7 +938,7 @@ pub fn _mm_mask_cmp_round_sh_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); _mm_cmp_round_sh_mask::(a, b) @@ -951,7 +951,7 @@ pub fn _mm_cmp_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_sh_mask(k1: __mmask8, a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); _mm_mask_cmp_round_sh_mask::(k1, a, b) @@ -965,7 +965,7 @@ pub fn _mm_mask_cmp_sh_mask(k1: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comi_round_sh(a: __m128h, b: __m128h) -> i32 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -981,7 +981,7 @@ pub fn _mm_comi_round_sh(a: __m128h, b: __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comi_sh(a: __m128h, b: __m128h) -> i32 { static_assert_uimm_bits!(IMM5, 5); _mm_comi_round_sh::(a, b) @@ -993,7 +993,7 @@ pub fn _mm_comi_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comieq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comieq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_EQ_OS>(a, b) } @@ -1004,7 +1004,7 @@ pub fn _mm_comieq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comige_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comige_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GE_OS>(a, b) } @@ -1015,7 +1015,7 @@ pub fn _mm_comige_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comigt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comigt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GT_OS>(a, b) } @@ -1026,7 +1026,7 @@ pub fn _mm_comigt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comile_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comile_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LE_OS>(a, b) } @@ -1037,7 +1037,7 @@ pub fn _mm_comile_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comilt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comilt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LT_OS>(a, b) } @@ -1048,7 +1048,7 @@ pub fn _mm_comilt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comineq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comineq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_NEQ_US>(a, b) } @@ -1059,7 +1059,7 @@ pub fn _mm_comineq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomieq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomieq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_EQ_OQ>(a, b) } @@ -1070,7 +1070,7 @@ pub fn _mm_ucomieq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomige_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomige_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GE_OQ>(a, b) } @@ -1081,7 +1081,7 @@ pub fn _mm_ucomige_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomigt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomigt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GT_OQ>(a, b) } @@ -1092,7 +1092,7 @@ pub fn _mm_ucomigt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomile_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomile_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LE_OQ>(a, b) } @@ -1103,7 +1103,7 @@ pub fn _mm_ucomile_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomilt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomilt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LT_OQ>(a, b) } @@ -1114,7 +1114,7 @@ pub fn _mm_ucomilt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomineq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomineq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_NEQ_UQ>(a, b) } @@ -1248,7 +1248,7 @@ pub const unsafe fn _mm512_loadu_ph(mem_addr: *const f16) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_move_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1267,7 +1267,7 @@ pub const fn _mm_mask_move_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_move_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1285,7 +1285,7 @@ pub const fn _mm_maskz_move_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_move_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1399,7 +1399,7 @@ pub const unsafe fn _mm512_storeu_ph(mem_addr: *mut f16, a: __m512h) { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_add_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_add(a, b) } @@ -1412,7 +1412,7 @@ pub const fn _mm_add_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_add_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1428,7 +1428,7 @@ pub const fn _mm_mask_add_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_add_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1443,7 +1443,7 @@ pub const fn _mm_maskz_add_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_add_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_add(a, b) } @@ -1456,7 +1456,7 @@ pub const fn _mm256_add_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_add_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1472,7 +1472,7 @@ pub const fn _mm256_mask_add_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_add_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1487,7 +1487,7 @@ pub const fn _mm256_maskz_add_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_add_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_add(a, b) } @@ -1500,7 +1500,7 @@ pub const fn _mm512_add_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_add_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1516,7 +1516,7 @@ pub const fn _mm512_mask_add_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_add_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1539,7 +1539,7 @@ pub const fn _mm512_maskz_add_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_add_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -1562,7 +1562,7 @@ pub fn _mm512_add_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_add_round_ph( src: __m512h, k: __mmask32, @@ -1590,7 +1590,7 @@ pub fn _mm512_mask_add_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_add_round_ph( k: __mmask32, a: __m512h, @@ -1618,7 +1618,7 @@ pub fn _mm512_maskz_add_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_add_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_add_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -1640,7 +1640,7 @@ pub fn _mm_add_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_add_round_sh( src: __m128h, k: __mmask8, @@ -1669,7 +1669,7 @@ pub fn _mm_mask_add_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_add_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_add_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -1682,7 +1682,7 @@ pub fn _mm_maskz_add_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_add_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) + _mm_cvtsh_h(b)) } @@ -1696,7 +1696,7 @@ pub const fn _mm_add_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_add_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1719,7 +1719,7 @@ pub const fn _mm_mask_add_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_add_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1739,7 +1739,7 @@ pub const fn _mm_maskz_add_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_sub_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_sub(a, b) } @@ -1752,7 +1752,7 @@ pub const fn _mm_sub_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_sub_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1768,7 +1768,7 @@ pub const fn _mm_mask_sub_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_sub_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1783,7 +1783,7 @@ pub const fn _mm_maskz_sub_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_sub_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_sub(a, b) } @@ -1796,7 +1796,7 @@ pub const fn _mm256_sub_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_sub_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1812,7 +1812,7 @@ pub const fn _mm256_mask_sub_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_sub_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1827,7 +1827,7 @@ pub const fn _mm256_maskz_sub_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_sub_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_sub(a, b) } @@ -1840,7 +1840,7 @@ pub const fn _mm512_sub_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_sub_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1856,7 +1856,7 @@ pub const fn _mm512_mask_sub_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_sub_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1879,7 +1879,7 @@ pub const fn _mm512_maskz_sub_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sub_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -1902,7 +1902,7 @@ pub fn _mm512_sub_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sub_round_ph( src: __m512h, k: __mmask32, @@ -1931,7 +1931,7 @@ pub fn _mm512_mask_sub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sub_round_ph( k: __mmask32, a: __m512h, @@ -1959,7 +1959,7 @@ pub fn _mm512_maskz_sub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sub_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sub_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -1981,7 +1981,7 @@ pub fn _mm_sub_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sub_round_sh( src: __m128h, k: __mmask8, @@ -2010,7 +2010,7 @@ pub fn _mm_mask_sub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sub_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sub_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2023,7 +2023,7 @@ pub fn _mm_maskz_sub_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_sub_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) - _mm_cvtsh_h(b)) } @@ -2037,7 +2037,7 @@ pub const fn _mm_sub_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_sub_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2060,7 +2060,7 @@ pub const fn _mm_mask_sub_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_sub_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2080,7 +2080,7 @@ pub const fn _mm_maskz_sub_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mul_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_mul(a, b) } @@ -2093,7 +2093,7 @@ pub const fn _mm_mul_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_mul_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2109,7 +2109,7 @@ pub const fn _mm_mask_mul_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_mul_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2124,7 +2124,7 @@ pub const fn _mm_maskz_mul_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mul_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_mul(a, b) } @@ -2137,7 +2137,7 @@ pub const fn _mm256_mul_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_mul_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2153,7 +2153,7 @@ pub const fn _mm256_mask_mul_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_mul_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2168,7 +2168,7 @@ pub const fn _mm256_maskz_mul_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mul_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_mul(a, b) } @@ -2181,7 +2181,7 @@ pub const fn _mm512_mul_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_mul_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2197,7 +2197,7 @@ pub const fn _mm512_mask_mul_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_mul_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2220,7 +2220,7 @@ pub const fn _mm512_maskz_mul_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -2243,7 +2243,7 @@ pub fn _mm512_mul_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_round_ph( src: __m512h, k: __mmask32, @@ -2272,7 +2272,7 @@ pub fn _mm512_mask_mul_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_round_ph( k: __mmask32, a: __m512h, @@ -2300,7 +2300,7 @@ pub fn _mm512_maskz_mul_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -2322,7 +2322,7 @@ pub fn _mm_mul_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_round_sh( src: __m128h, k: __mmask8, @@ -2351,7 +2351,7 @@ pub fn _mm_mask_mul_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2364,7 +2364,7 @@ pub fn _mm_maskz_mul_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mul_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) * _mm_cvtsh_h(b)) } @@ -2378,7 +2378,7 @@ pub const fn _mm_mul_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_mul_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2401,7 +2401,7 @@ pub const fn _mm_mask_mul_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_mul_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2421,7 +2421,7 @@ pub const fn _mm_maskz_mul_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_div_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_div(a, b) } @@ -2434,7 +2434,7 @@ pub const fn _mm_div_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_div_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2450,7 +2450,7 @@ pub const fn _mm_mask_div_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_div_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2465,7 +2465,7 @@ pub const fn _mm_maskz_div_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_div_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_div(a, b) } @@ -2478,7 +2478,7 @@ pub const fn _mm256_div_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_div_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2494,7 +2494,7 @@ pub const fn _mm256_mask_div_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_div_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2509,7 +2509,7 @@ pub const fn _mm256_maskz_div_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_div_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_div(a, b) } @@ -2522,7 +2522,7 @@ pub const fn _mm512_div_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_div_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2538,7 +2538,7 @@ pub const fn _mm512_mask_div_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_div_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2561,7 +2561,7 @@ pub const fn _mm512_maskz_div_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_div_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -2584,7 +2584,7 @@ pub fn _mm512_div_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_div_round_ph( src: __m512h, k: __mmask32, @@ -2613,7 +2613,7 @@ pub fn _mm512_mask_div_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_div_round_ph( k: __mmask32, a: __m512h, @@ -2641,7 +2641,7 @@ pub fn _mm512_maskz_div_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_div_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_div_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -2663,7 +2663,7 @@ pub fn _mm_div_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_div_round_sh( src: __m128h, k: __mmask8, @@ -2692,7 +2692,7 @@ pub fn _mm_mask_div_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_div_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_div_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2705,7 +2705,7 @@ pub fn _mm_maskz_div_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_div_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) / _mm_cvtsh_h(b)) } @@ -2719,7 +2719,7 @@ pub const fn _mm_div_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_div_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2742,7 +2742,7 @@ pub const fn _mm_mask_div_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_div_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2764,7 +2764,7 @@ pub const fn _mm_maskz_div_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(_mm_undefined_ph(), 0xff, a, b) } @@ -2777,7 +2777,7 @@ pub fn _mm_mul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { transmute(vfmulcph_128(transmute(a), transmute(b), transmute(src), k)) } } @@ -2790,7 +2790,7 @@ pub fn _mm_mask_mul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(_mm_setzero_ph(), k, a, b) } @@ -2803,7 +2803,7 @@ pub fn _mm_maskz_mul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(_mm256_undefined_ph(), 0xff, a, b) } @@ -2816,7 +2816,7 @@ pub fn _mm256_mul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_mul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { unsafe { transmute(vfmulcph_256(transmute(a), transmute(b), transmute(src), k)) } } @@ -2829,7 +2829,7 @@ pub fn _mm256_mask_mul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_mul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(_mm256_setzero_ph(), k, a, b) } @@ -2842,7 +2842,7 @@ pub fn _mm256_maskz_mul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(_mm512_undefined_ph(), 0xffff, a, b) } @@ -2855,7 +2855,7 @@ pub fn _mm512_mul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_round_pch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -2868,7 +2868,7 @@ pub fn _mm512_mask_mul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(_mm512_setzero_ph(), k, a, b) } @@ -2890,7 +2890,7 @@ pub fn _mm512_maskz_mul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_mul_round_pch::(_mm512_undefined_ph(), 0xffff, a, b) @@ -2913,7 +2913,7 @@ pub fn _mm512_mul_round_pch(a: __m512h, b: __m512h) -> __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_round_pch( src: __m512h, k: __mmask16, @@ -2949,7 +2949,7 @@ pub fn _mm512_mask_mul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_round_pch( k: __mmask16, a: __m512h, @@ -2968,7 +2968,7 @@ pub fn _mm512_maskz_mul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -2982,7 +2982,7 @@ pub fn _mm_mul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_round_sch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -2996,7 +2996,7 @@ pub fn _mm_mask_mul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(f16x8::ZERO.as_m128h(), k, a, b) } @@ -3019,7 +3019,7 @@ pub fn _mm_maskz_mul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sch::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -3043,7 +3043,7 @@ pub fn _mm_mul_round_sch(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_round_sch( src: __m128h, k: __mmask8, @@ -3080,7 +3080,7 @@ pub fn _mm_mask_mul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_round_sch( k: __mmask8, a: __m128h, @@ -3098,7 +3098,7 @@ pub fn _mm_maskz_mul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mul_pch(a, b) } @@ -3111,7 +3111,7 @@ pub fn _mm_fmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(src, k, a, b) } @@ -3124,7 +3124,7 @@ pub fn _mm_mask_fmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_mul_pch(k, a, b) } @@ -3137,7 +3137,7 @@ pub fn _mm_maskz_fmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mul_pch(a, b) } @@ -3150,7 +3150,7 @@ pub fn _mm256_fmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(src, k, a, b) } @@ -3163,7 +3163,7 @@ pub fn _mm256_mask_fmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_maskz_mul_pch(k, a, b) } @@ -3175,7 +3175,7 @@ pub fn _mm256_maskz_fmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mul_pch(a, b) } @@ -3188,7 +3188,7 @@ pub fn _mm512_fmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(src, k, a, b) } @@ -3201,7 +3201,7 @@ pub fn _mm512_mask_fmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_maskz_mul_pch(k, a, b) } @@ -3221,7 +3221,7 @@ pub fn _mm512_maskz_fmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mul_round_pch::(a, b) @@ -3243,7 +3243,7 @@ pub fn _mm512_fmul_round_pch(a: __m512h, b: __m512h) -> __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmul_round_pch( src: __m512h, k: __mmask16, @@ -3270,7 +3270,7 @@ pub fn _mm512_mask_fmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmul_round_pch( k: __mmask16, a: __m512h, @@ -3288,7 +3288,7 @@ pub fn _mm512_maskz_fmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mul_sch(a, b) } @@ -3301,7 +3301,7 @@ pub fn _mm_fmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(src, k, a, b) } @@ -3314,7 +3314,7 @@ pub fn _mm_mask_fmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_mul_sch(k, a, b) } @@ -3335,7 +3335,7 @@ pub fn _mm_maskz_fmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mul_round_sch::(a, b) @@ -3358,7 +3358,7 @@ pub fn _mm_fmul_round_sch(a: __m128h, b: __m128h) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_round_sch( src: __m128h, k: __mmask8, @@ -3386,7 +3386,7 @@ pub fn _mm_mask_fmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_round_sch( k: __mmask8, a: __m128h, @@ -3405,7 +3405,7 @@ pub fn _mm_maskz_fmul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(_mm_undefined_ph(), 0xff, a, b) } @@ -3419,7 +3419,7 @@ pub fn _mm_cmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { transmute(vfcmulcph_128(transmute(a), transmute(b), transmute(src), k)) } } @@ -3433,7 +3433,7 @@ pub fn _mm_mask_cmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(_mm_setzero_ph(), k, a, b) } @@ -3447,7 +3447,7 @@ pub fn _mm_maskz_cmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(_mm256_undefined_ph(), 0xff, a, b) } @@ -3461,7 +3461,7 @@ pub fn _mm256_cmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { unsafe { transmute(vfcmulcph_256(transmute(a), transmute(b), transmute(src), k)) } } @@ -3475,7 +3475,7 @@ pub fn _mm256_mask_cmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(_mm256_setzero_ph(), k, a, b) } @@ -3489,7 +3489,7 @@ pub fn _mm256_maskz_cmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(_mm512_undefined_ph(), 0xffff, a, b) } @@ -3503,7 +3503,7 @@ pub fn _mm512_cmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_round_pch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -3517,7 +3517,7 @@ pub fn _mm512_mask_cmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(_mm512_setzero_ph(), k, a, b) } @@ -3540,7 +3540,7 @@ pub fn _mm512_maskz_cmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cmul_round_pch::(_mm512_undefined_ph(), 0xffff, a, b) @@ -3564,7 +3564,7 @@ pub fn _mm512_cmul_round_pch(a: __m512h, b: __m512h) -> __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmul_round_pch( src: __m512h, k: __mmask16, @@ -3601,7 +3601,7 @@ pub fn _mm512_mask_cmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cmul_round_pch( k: __mmask16, a: __m512h, @@ -3619,7 +3619,7 @@ pub fn _mm512_maskz_cmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -3633,7 +3633,7 @@ pub fn _mm_cmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_round_sch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -3647,7 +3647,7 @@ pub fn _mm_mask_cmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(f16x8::ZERO.as_m128h(), k, a, b) } @@ -3669,7 +3669,7 @@ pub fn _mm_maskz_cmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cmul_round_sch::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -3693,7 +3693,7 @@ pub fn _mm_cmul_round_sch(a: __m128h, b: __m128h) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_round_sch( src: __m128h, k: __mmask8, @@ -3730,7 +3730,7 @@ pub fn _mm_mask_cmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_round_sch( k: __mmask8, a: __m128h, @@ -3749,7 +3749,7 @@ pub fn _mm_maskz_cmul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_cmul_pch(a, b) } @@ -3763,7 +3763,7 @@ pub fn _mm_fcmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(src, k, a, b) } @@ -3777,7 +3777,7 @@ pub fn _mm_mask_fcmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_cmul_pch(k, a, b) } @@ -3791,7 +3791,7 @@ pub fn _mm_maskz_fcmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fcmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_cmul_pch(a, b) } @@ -3805,7 +3805,7 @@ pub fn _mm256_fcmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fcmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(src, k, a, b) } @@ -3819,7 +3819,7 @@ pub fn _mm256_mask_fcmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fcmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_maskz_cmul_pch(k, a, b) } @@ -3833,7 +3833,7 @@ pub fn _mm256_maskz_fcmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_cmul_pch(a, b) } @@ -3847,7 +3847,7 @@ pub fn _mm512_fcmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(src, k, a, b) } @@ -3861,7 +3861,7 @@ pub fn _mm512_mask_fcmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_maskz_cmul_pch(k, a, b) } @@ -3883,7 +3883,7 @@ pub fn _mm512_maskz_fcmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_cmul_round_pch::(a, b) @@ -3907,7 +3907,7 @@ pub fn _mm512_fcmul_round_pch(a: __m512h, b: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmul_round_pch( src: __m512h, k: __mmask16, @@ -3936,7 +3936,7 @@ pub fn _mm512_mask_fcmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmul_round_pch( k: __mmask16, a: __m512h, @@ -3955,7 +3955,7 @@ pub fn _mm512_maskz_fcmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_cmul_sch(a, b) } @@ -3969,7 +3969,7 @@ pub fn _mm_fcmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(src, k, a, b) } @@ -3983,7 +3983,7 @@ pub fn _mm_mask_fcmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_cmul_sch(k, a, b) } @@ -4005,7 +4005,7 @@ pub fn _mm_maskz_fcmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_cmul_round_sch::(a, b) @@ -4029,7 +4029,7 @@ pub fn _mm_fcmul_round_sch(a: __m128h, b: __m128h) -> __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_round_sch( src: __m128h, k: __mmask8, @@ -4058,7 +4058,7 @@ pub fn _mm_mask_fcmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_round_sch( k: __mmask8, a: __m128h, @@ -4074,7 +4074,7 @@ pub fn _mm_maskz_fcmul_round_sch( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_abs_ph(v2: __m128h) -> __m128h { unsafe { transmute(_mm_and_si128(transmute(v2), _mm_set1_epi16(i16::MAX))) } @@ -4086,7 +4086,7 @@ pub const fn _mm_abs_ph(v2: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_abs_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_abs_ph(v2: __m256h) -> __m256h { unsafe { transmute(_mm256_and_si256(transmute(v2), _mm256_set1_epi16(i16::MAX))) } @@ -4098,7 +4098,7 @@ pub const fn _mm256_abs_ph(v2: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_abs_ph(v2: __m512h) -> __m512h { unsafe { transmute(_mm512_and_si512(transmute(v2), _mm512_set1_epi16(i16::MAX))) } @@ -4112,7 +4112,7 @@ pub const fn _mm512_abs_ph(v2: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_conj_pch(a: __m128h) -> __m128h { unsafe { transmute(_mm_xor_si128(transmute(a), _mm_set1_epi32(i32::MIN))) } @@ -4126,7 +4126,7 @@ pub const fn _mm_conj_pch(a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_conj_pch(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { @@ -4143,7 +4143,7 @@ pub const fn _mm_mask_conj_pch(src: __m128h, k: __mmask8, a: __m128h) -> __m128h /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_conj_pch(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_conj_pch(_mm_setzero_ph(), k, a) @@ -4156,7 +4156,7 @@ pub const fn _mm_maskz_conj_pch(k: __mmask8, a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_conj_pch(a: __m256h) -> __m256h { unsafe { transmute(_mm256_xor_si256(transmute(a), _mm256_set1_epi32(i32::MIN))) } @@ -4170,7 +4170,7 @@ pub const fn _mm256_conj_pch(a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_conj_pch(src: __m256h, k: __mmask8, a: __m256h) -> __m256h { unsafe { @@ -4187,7 +4187,7 @@ pub const fn _mm256_mask_conj_pch(src: __m256h, k: __mmask8, a: __m256h) -> __m2 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_conj_pch(k: __mmask8, a: __m256h) -> __m256h { _mm256_mask_conj_pch(_mm256_setzero_ph(), k, a) @@ -4200,7 +4200,7 @@ pub const fn _mm256_maskz_conj_pch(k: __mmask8, a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_conj_pch(a: __m512h) -> __m512h { unsafe { transmute(_mm512_xor_si512(transmute(a), _mm512_set1_epi32(i32::MIN))) } @@ -4214,7 +4214,7 @@ pub const fn _mm512_conj_pch(a: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_conj_pch(src: __m512h, k: __mmask16, a: __m512h) -> __m512h { unsafe { @@ -4231,7 +4231,7 @@ pub const fn _mm512_mask_conj_pch(src: __m512h, k: __mmask16, a: __m512h) -> __m /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_conj_pch(k: __mmask16, a: __m512h) -> __m512h { _mm512_mask_conj_pch(_mm512_setzero_ph(), k, a) @@ -4245,7 +4245,7 @@ pub const fn _mm512_maskz_conj_pch(k: __mmask16, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_mask3_fmadd_pch(a, b, c, 0xff) } @@ -4259,7 +4259,7 @@ pub fn _mm_fmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { let r: __m128 = transmute(_mm_mask3_fmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4276,7 +4276,7 @@ pub fn _mm_mask_fmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { transmute(vfmaddcph_mask3_128( @@ -4297,7 +4297,7 @@ pub fn _mm_mask3_fmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { transmute(vfmaddcph_maskz_128( @@ -4317,7 +4317,7 @@ pub fn _mm_maskz_fmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_mask3_fmadd_pch(a, b, c, 0xff) } @@ -4331,7 +4331,7 @@ pub fn _mm256_fmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> __m256h { unsafe { let r: __m256 = transmute(_mm256_mask3_fmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4348,7 +4348,7 @@ pub fn _mm256_mask_fmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask3_fmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) -> __m256h { unsafe { transmute(vfmaddcph_mask3_256( @@ -4369,7 +4369,7 @@ pub fn _mm256_mask3_fmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { transmute(vfmaddcph_maskz_256( @@ -4389,7 +4389,7 @@ pub fn _mm256_maskz_fmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4403,7 +4403,7 @@ pub fn _mm512_fmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) -> __m512h { _mm512_mask_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4417,7 +4417,7 @@ pub fn _mm512_mask_fmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) -> __m512h { _mm512_mask3_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4431,7 +4431,7 @@ pub fn _mm512_mask3_fmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_maskz_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4453,7 +4453,7 @@ pub fn _mm512_maskz_fmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_round_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask3_fmadd_round_pch::(a, b, c, 0xffff) @@ -4477,7 +4477,7 @@ pub fn _mm512_fmadd_round_pch(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_round_pch( a: __m512h, k: __mmask16, @@ -4509,7 +4509,7 @@ pub fn _mm512_mask_fmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_round_pch( a: __m512h, b: __m512h, @@ -4546,7 +4546,7 @@ pub fn _mm512_mask3_fmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_round_pch( k: __mmask16, a: __m512h, @@ -4574,7 +4574,7 @@ pub fn _mm512_maskz_fmadd_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4589,7 +4589,7 @@ pub fn _mm_fmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { _mm_mask_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4604,7 +4604,7 @@ pub fn _mm_mask_fmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { _mm_mask3_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4619,7 +4619,7 @@ pub fn _mm_mask3_fmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_maskz_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4641,7 +4641,7 @@ pub fn _mm_maskz_fmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_round_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -4674,7 +4674,7 @@ pub fn _mm_fmadd_round_sch(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_round_sch( a: __m128h, k: __mmask8, @@ -4708,7 +4708,7 @@ pub fn _mm_mask_fmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_round_sch( a: __m128h, b: __m128h, @@ -4742,7 +4742,7 @@ pub fn _mm_mask3_fmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_round_sch( k: __mmask8, a: __m128h, @@ -4770,7 +4770,7 @@ pub fn _mm_maskz_fmadd_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_mask3_fcmadd_pch(a, b, c, 0xff) } @@ -4785,7 +4785,7 @@ pub fn _mm_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { let r: __m128 = transmute(_mm_mask3_fcmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4803,7 +4803,7 @@ pub fn _mm_mask_fcmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { transmute(vfcmaddcph_mask3_128( @@ -4825,7 +4825,7 @@ pub fn _mm_mask3_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { transmute(vfcmaddcph_maskz_128( @@ -4846,7 +4846,7 @@ pub fn _mm_maskz_fcmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_mask3_fcmadd_pch(a, b, c, 0xff) } @@ -4861,7 +4861,7 @@ pub fn _mm256_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fcmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> __m256h { unsafe { let r: __m256 = transmute(_mm256_mask3_fcmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4879,7 +4879,7 @@ pub fn _mm256_mask_fcmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask3_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) -> __m256h { unsafe { transmute(vfcmaddcph_mask3_256( @@ -4901,7 +4901,7 @@ pub fn _mm256_mask3_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fcmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { transmute(vfcmaddcph_maskz_256( @@ -4922,7 +4922,7 @@ pub fn _mm256_maskz_fcmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4937,7 +4937,7 @@ pub fn _mm512_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) -> __m512h { _mm512_mask_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4952,7 +4952,7 @@ pub fn _mm512_mask_fcmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) -> __m512h { _mm512_mask3_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4967,7 +4967,7 @@ pub fn _mm512_mask3_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_maskz_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4990,7 +4990,7 @@ pub fn _mm512_maskz_fcmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmadd_round_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask3_fcmadd_round_pch::(a, b, c, 0xffff) @@ -5015,7 +5015,7 @@ pub fn _mm512_fcmadd_round_pch(a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmadd_round_pch( a: __m512h, k: __mmask16, @@ -5048,7 +5048,7 @@ pub fn _mm512_mask_fcmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fcmadd_round_pch( a: __m512h, b: __m512h, @@ -5086,7 +5086,7 @@ pub fn _mm512_mask3_fcmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmadd_round_pch( k: __mmask16, a: __m512h, @@ -5115,7 +5115,7 @@ pub fn _mm512_maskz_fcmadd_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -5131,7 +5131,7 @@ pub fn _mm_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { _mm_mask_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -5147,7 +5147,7 @@ pub fn _mm_mask_fcmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { _mm_mask3_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -5163,7 +5163,7 @@ pub fn _mm_mask3_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_maskz_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -5187,7 +5187,7 @@ pub fn _mm_maskz_fcmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_round_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -5221,7 +5221,7 @@ pub fn _mm_fcmadd_round_sch(a: __m128h, b: __m128h, c: __m1 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_round_sch( a: __m128h, k: __mmask8, @@ -5256,7 +5256,7 @@ pub fn _mm_mask_fcmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_round_sch( a: __m128h, b: __m128h, @@ -5291,7 +5291,7 @@ pub fn _mm_mask3_fcmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_round_sch( k: __mmask8, a: __m128h, @@ -5317,7 +5317,7 @@ pub fn _mm_maskz_fcmadd_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(a, b, c) } @@ -5331,7 +5331,7 @@ pub const fn _mm_fmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), a) } @@ -5345,7 +5345,7 @@ pub const fn _mm_mask_fmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), c) } @@ -5359,7 +5359,7 @@ pub const fn _mm_mask3_fmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), _mm_setzero_ph()) } @@ -5372,7 +5372,7 @@ pub const fn _mm_maskz_fmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(a, b, c) } @@ -5386,7 +5386,7 @@ pub const fn _mm256_fmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), a) } @@ -5400,7 +5400,7 @@ pub const fn _mm256_mask_fmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), c) } @@ -5414,7 +5414,7 @@ pub const fn _mm256_mask3_fmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -5427,7 +5427,7 @@ pub const fn _mm256_maskz_fmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(a, b, c) } @@ -5441,7 +5441,7 @@ pub const fn _mm512_fmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), a) } @@ -5455,7 +5455,7 @@ pub const fn _mm512_mask_fmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), c) } @@ -5469,7 +5469,7 @@ pub const fn _mm512_mask3_fmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -5491,7 +5491,7 @@ pub const fn _mm512_maskz_fmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -5516,7 +5516,7 @@ pub fn _mm512_fmadd_round_ph(a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_round_ph( a: __m512h, k: __mmask32, @@ -5546,7 +5546,7 @@ pub fn _mm512_mask_fmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_round_ph( a: __m512h, b: __m512h, @@ -5576,7 +5576,7 @@ pub fn _mm512_mask3_fmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_round_ph( k: __mmask32, a: __m512h, @@ -5601,7 +5601,7 @@ pub fn _mm512_maskz_fmadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5622,7 +5622,7 @@ pub const fn _mm_fmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5645,7 +5645,7 @@ pub const fn _mm_mask_fmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -5668,7 +5668,7 @@ pub const fn _mm_mask3_fmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5700,7 +5700,7 @@ pub const fn _mm_maskz_fmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -5730,7 +5730,7 @@ pub fn _mm_fmadd_round_sh(a: __m128h, b: __m128h, c: __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_round_sh( a: __m128h, k: __mmask8, @@ -5767,7 +5767,7 @@ pub fn _mm_mask_fmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_round_sh( a: __m128h, b: __m128h, @@ -5804,7 +5804,7 @@ pub fn _mm_mask3_fmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_round_sh( k: __mmask8, a: __m128h, @@ -5832,7 +5832,7 @@ pub fn _mm_maskz_fmadd_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5846,7 +5846,7 @@ pub const fn _mm_fmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), a) } @@ -5860,7 +5860,7 @@ pub const fn _mm_mask_fmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), c) } @@ -5874,7 +5874,7 @@ pub const fn _mm_mask3_fmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), _mm_setzero_ph()) } @@ -5887,7 +5887,7 @@ pub const fn _mm_maskz_fmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5901,7 +5901,7 @@ pub const fn _mm256_fmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), a) } @@ -5915,7 +5915,7 @@ pub const fn _mm256_mask_fmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), c) } @@ -5929,7 +5929,7 @@ pub const fn _mm256_mask3_fmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -5942,7 +5942,7 @@ pub const fn _mm256_maskz_fmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5956,7 +5956,7 @@ pub const fn _mm512_fmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), a) } @@ -5970,7 +5970,7 @@ pub const fn _mm512_mask_fmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), c) } @@ -5984,7 +5984,7 @@ pub const fn _mm512_mask3_fmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -6006,7 +6006,7 @@ pub const fn _mm512_maskz_fmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmsub_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -6031,7 +6031,7 @@ pub fn _mm512_fmsub_round_ph(a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmsub_round_ph( a: __m512h, k: __mmask32, @@ -6061,7 +6061,7 @@ pub fn _mm512_mask_fmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmsub_round_ph( a: __m512h, b: __m512h, @@ -6091,7 +6091,7 @@ pub fn _mm512_mask3_fmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmsub_round_ph( k: __mmask32, a: __m512h, @@ -6116,7 +6116,7 @@ pub fn _mm512_maskz_fmsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6137,7 +6137,7 @@ pub const fn _mm_fmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6160,7 +6160,7 @@ pub const fn _mm_mask_fmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -6183,7 +6183,7 @@ pub const fn _mm_mask3_fmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6215,7 +6215,7 @@ pub const fn _mm_maskz_fmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmsub_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -6245,7 +6245,7 @@ pub fn _mm_fmsub_round_sh(a: __m128h, b: __m128h, c: __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmsub_round_sh( a: __m128h, k: __mmask8, @@ -6282,7 +6282,7 @@ pub fn _mm_mask_fmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmsub_round_sh( a: __m128h, b: __m128h, @@ -6311,7 +6311,7 @@ pub fn _mm_mask3_fmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmsub_round_sh( k: __mmask8, a: __m128h, @@ -6338,7 +6338,7 @@ pub fn _mm_maskz_fmsub_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6352,7 +6352,7 @@ pub const fn _mm_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), a) } @@ -6366,7 +6366,7 @@ pub const fn _mm_mask_fnmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), c) } @@ -6380,7 +6380,7 @@ pub const fn _mm_mask3_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), _mm_setzero_ph()) } @@ -6393,7 +6393,7 @@ pub const fn _mm_maskz_fnmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6407,7 +6407,7 @@ pub const fn _mm256_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fnmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), a) } @@ -6421,7 +6421,7 @@ pub const fn _mm256_mask_fnmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), c) } @@ -6435,7 +6435,7 @@ pub const fn _mm256_mask3_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mma #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fnmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -6448,7 +6448,7 @@ pub const fn _mm256_maskz_fnmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6462,7 +6462,7 @@ pub const fn _mm512_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fnmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), a) } @@ -6476,7 +6476,7 @@ pub const fn _mm512_mask_fnmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), c) } @@ -6490,7 +6490,7 @@ pub const fn _mm512_mask3_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mma #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fnmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -6512,7 +6512,7 @@ pub const fn _mm512_maskz_fnmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fnmadd_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -6537,7 +6537,7 @@ pub fn _mm512_fnmadd_round_ph(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fnmadd_round_ph( a: __m512h, k: __mmask32, @@ -6567,7 +6567,7 @@ pub fn _mm512_mask_fnmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fnmadd_round_ph( a: __m512h, b: __m512h, @@ -6597,7 +6597,7 @@ pub fn _mm512_mask3_fnmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fnmadd_round_ph( k: __mmask32, a: __m512h, @@ -6622,7 +6622,7 @@ pub fn _mm512_maskz_fnmadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6643,7 +6643,7 @@ pub const fn _mm_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6666,7 +6666,7 @@ pub const fn _mm_mask_fnmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -6689,7 +6689,7 @@ pub const fn _mm_mask3_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6721,7 +6721,7 @@ pub const fn _mm_maskz_fnmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fnmadd_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -6751,7 +6751,7 @@ pub fn _mm_fnmadd_round_sh(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fnmadd_round_sh( a: __m128h, k: __mmask8, @@ -6788,7 +6788,7 @@ pub fn _mm_mask_fnmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fnmadd_round_sh( a: __m128h, b: __m128h, @@ -6825,7 +6825,7 @@ pub fn _mm_mask3_fnmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fnmadd_round_sh( k: __mmask8, a: __m128h, @@ -6852,7 +6852,7 @@ pub fn _mm_maskz_fnmadd_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6866,7 +6866,7 @@ pub const fn _mm_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), a) } @@ -6880,7 +6880,7 @@ pub const fn _mm_mask_fnmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), c) } @@ -6894,7 +6894,7 @@ pub const fn _mm_mask3_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), _mm_setzero_ph()) } @@ -6907,7 +6907,7 @@ pub const fn _mm_maskz_fnmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6921,7 +6921,7 @@ pub const fn _mm256_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fnmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), a) } @@ -6935,7 +6935,7 @@ pub const fn _mm256_mask_fnmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), c) } @@ -6949,7 +6949,7 @@ pub const fn _mm256_mask3_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mma #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fnmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -6962,7 +6962,7 @@ pub const fn _mm256_maskz_fnmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6976,7 +6976,7 @@ pub const fn _mm512_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fnmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), a) } @@ -6990,7 +6990,7 @@ pub const fn _mm512_mask_fnmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), c) } @@ -7004,7 +7004,7 @@ pub const fn _mm512_mask3_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mma #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fnmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -7026,7 +7026,7 @@ pub const fn _mm512_maskz_fnmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fnmsub_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -7051,7 +7051,7 @@ pub fn _mm512_fnmsub_round_ph(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fnmsub_round_ph( a: __m512h, k: __mmask32, @@ -7081,7 +7081,7 @@ pub fn _mm512_mask_fnmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fnmsub_round_ph( a: __m512h, b: __m512h, @@ -7111,7 +7111,7 @@ pub fn _mm512_mask3_fnmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fnmsub_round_ph( k: __mmask32, a: __m512h, @@ -7136,7 +7136,7 @@ pub fn _mm512_maskz_fnmsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7157,7 +7157,7 @@ pub const fn _mm_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7180,7 +7180,7 @@ pub const fn _mm_mask_fnmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -7203,7 +7203,7 @@ pub const fn _mm_mask3_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7235,7 +7235,7 @@ pub const fn _mm_maskz_fnmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fnmsub_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -7265,7 +7265,7 @@ pub fn _mm_fnmsub_round_sh(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fnmsub_round_sh( a: __m128h, k: __mmask8, @@ -7302,7 +7302,7 @@ pub fn _mm_mask_fnmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fnmsub_round_sh( a: __m128h, b: __m128h, @@ -7339,7 +7339,7 @@ pub fn _mm_mask3_fnmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fnmsub_round_sh( k: __mmask8, a: __m128h, @@ -7366,7 +7366,7 @@ pub fn _mm_maskz_fnmsub_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7384,7 +7384,7 @@ pub const fn _mm_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmaddsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), a) } @@ -7398,7 +7398,7 @@ pub const fn _mm_mask_fmaddsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), c) } @@ -7412,7 +7412,7 @@ pub const fn _mm_mask3_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmaddsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), _mm_setzero_ph()) } @@ -7425,7 +7425,7 @@ pub const fn _mm_maskz_fmaddsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { @@ -7447,7 +7447,7 @@ pub const fn _mm256_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmaddsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), a) } @@ -7461,7 +7461,7 @@ pub const fn _mm256_mask_fmaddsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), c) } @@ -7475,7 +7475,7 @@ pub const fn _mm256_mask3_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmaddsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -7488,7 +7488,7 @@ pub const fn _mm256_maskz_fmaddsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { @@ -7513,7 +7513,7 @@ pub const fn _mm512_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmaddsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), a) } @@ -7527,7 +7527,7 @@ pub const fn _mm512_mask_fmaddsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), c) } @@ -7541,7 +7541,7 @@ pub const fn _mm512_mask3_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmaddsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -7563,7 +7563,7 @@ pub const fn _mm512_maskz_fmaddsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmaddsub_round_ph( a: __m512h, b: __m512h, @@ -7592,7 +7592,7 @@ pub fn _mm512_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmaddsub_round_ph( a: __m512h, k: __mmask32, @@ -7622,7 +7622,7 @@ pub fn _mm512_mask_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmaddsub_round_ph( a: __m512h, b: __m512h, @@ -7652,7 +7652,7 @@ pub fn _mm512_mask3_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmaddsub_round_ph( k: __mmask32, a: __m512h, @@ -7676,7 +7676,7 @@ pub fn _mm512_maskz_fmaddsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7690,7 +7690,7 @@ pub const fn _mm_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsubadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), a) } @@ -7704,7 +7704,7 @@ pub const fn _mm_mask_fmsubadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), c) } @@ -7718,7 +7718,7 @@ pub const fn _mm_mask3_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsubadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), _mm_setzero_ph()) } @@ -7731,7 +7731,7 @@ pub const fn _mm_maskz_fmsubadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7745,7 +7745,7 @@ pub const fn _mm256_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmsubadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), a) } @@ -7759,7 +7759,7 @@ pub const fn _mm256_mask_fmsubadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), c) } @@ -7773,7 +7773,7 @@ pub const fn _mm256_mask3_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmsubadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -7786,7 +7786,7 @@ pub const fn _mm256_maskz_fmsubadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7800,7 +7800,7 @@ pub const fn _mm512_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmsubadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), a) } @@ -7814,7 +7814,7 @@ pub const fn _mm512_mask_fmsubadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), c) } @@ -7828,7 +7828,7 @@ pub const fn _mm512_mask3_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmsubadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -7850,7 +7850,7 @@ pub const fn _mm512_maskz_fmsubadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmsubadd_round_ph( a: __m512h, b: __m512h, @@ -7879,7 +7879,7 @@ pub fn _mm512_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmsubadd_round_ph( a: __m512h, k: __mmask32, @@ -7909,7 +7909,7 @@ pub fn _mm512_mask_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmsubadd_round_ph( a: __m512h, b: __m512h, @@ -7939,7 +7939,7 @@ pub fn _mm512_mask3_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmsubadd_round_ph( k: __mmask32, a: __m512h, @@ -7963,7 +7963,7 @@ pub fn _mm512_maskz_fmsubadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rcp_ph(a: __m128h) -> __m128h { _mm_mask_rcp_ph(_mm_undefined_ph(), 0xff, a) } @@ -7976,7 +7976,7 @@ pub fn _mm_rcp_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rcp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vrcpph_128(a, src, k) } } @@ -7989,7 +7989,7 @@ pub fn _mm_mask_rcp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rcp_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_rcp_ph(_mm_setzero_ph(), k, a) } @@ -8001,7 +8001,7 @@ pub fn _mm_maskz_rcp_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_rcp_ph(a: __m256h) -> __m256h { _mm256_mask_rcp_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -8014,7 +8014,7 @@ pub fn _mm256_rcp_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_rcp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vrcpph_256(a, src, k) } } @@ -8027,7 +8027,7 @@ pub fn _mm256_mask_rcp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_rcp_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_rcp_ph(_mm256_setzero_ph(), k, a) } @@ -8039,7 +8039,7 @@ pub fn _mm256_maskz_rcp_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_rcp_ph(a: __m512h) -> __m512h { _mm512_mask_rcp_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -8052,7 +8052,7 @@ pub fn _mm512_rcp_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_rcp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { vrcpph_512(a, src, k) } } @@ -8065,7 +8065,7 @@ pub fn _mm512_mask_rcp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_rcp_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_rcp_ph(_mm512_setzero_ph(), k, a) } @@ -8079,7 +8079,7 @@ pub fn _mm512_maskz_rcp_ph(k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rcp_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_rcp_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8093,7 +8093,7 @@ pub fn _mm_rcp_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rcp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vrcpsh(a, b, src, k) } } @@ -8107,7 +8107,7 @@ pub fn _mm_mask_rcp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rcp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_rcp_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8120,7 +8120,7 @@ pub fn _mm_maskz_rcp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rsqrt_ph(a: __m128h) -> __m128h { _mm_mask_rsqrt_ph(_mm_undefined_ph(), 0xff, a) } @@ -8134,7 +8134,7 @@ pub fn _mm_rsqrt_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rsqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vrsqrtph_128(a, src, k) } } @@ -8148,7 +8148,7 @@ pub fn _mm_mask_rsqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rsqrt_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_rsqrt_ph(_mm_setzero_ph(), k, a) } @@ -8161,7 +8161,7 @@ pub fn _mm_maskz_rsqrt_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_rsqrt_ph(a: __m256h) -> __m256h { _mm256_mask_rsqrt_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -8175,7 +8175,7 @@ pub fn _mm256_rsqrt_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_rsqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vrsqrtph_256(a, src, k) } } @@ -8189,7 +8189,7 @@ pub fn _mm256_mask_rsqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_rsqrt_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_rsqrt_ph(_mm256_setzero_ph(), k, a) } @@ -8202,7 +8202,7 @@ pub fn _mm256_maskz_rsqrt_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_rsqrt_ph(a: __m512h) -> __m512h { _mm512_mask_rsqrt_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -8216,7 +8216,7 @@ pub fn _mm512_rsqrt_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_rsqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { vrsqrtph_512(a, src, k) } } @@ -8230,7 +8230,7 @@ pub fn _mm512_mask_rsqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_rsqrt_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_rsqrt_ph(_mm512_setzero_ph(), k, a) } @@ -8244,7 +8244,7 @@ pub fn _mm512_maskz_rsqrt_ph(k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rsqrt_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_rsqrt_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8258,7 +8258,7 @@ pub fn _mm_rsqrt_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rsqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vrsqrtsh(a, b, src, k) } } @@ -8272,7 +8272,7 @@ pub fn _mm_mask_rsqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rsqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_rsqrt_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8284,7 +8284,7 @@ pub fn _mm_maskz_rsqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_ph(a: __m128h) -> __m128h { unsafe { simd_fsqrt(a) } } @@ -8296,7 +8296,7 @@ pub fn _mm_sqrt_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_sqrt_ph(a), src) } } @@ -8308,7 +8308,7 @@ pub fn _mm_mask_sqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_ph(k: __mmask8, a: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_sqrt_ph(a), _mm_setzero_ph()) } } @@ -8320,7 +8320,7 @@ pub fn _mm_maskz_sqrt_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_sqrt_ph(a: __m256h) -> __m256h { unsafe { simd_fsqrt(a) } } @@ -8332,7 +8332,7 @@ pub fn _mm256_sqrt_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_sqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_sqrt_ph(a), src) } } @@ -8344,7 +8344,7 @@ pub fn _mm256_mask_sqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_sqrt_ph(k: __mmask16, a: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_sqrt_ph(a), _mm256_setzero_ph()) } } @@ -8356,7 +8356,7 @@ pub fn _mm256_maskz_sqrt_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sqrt_ph(a: __m512h) -> __m512h { unsafe { simd_fsqrt(a) } } @@ -8368,7 +8368,7 @@ pub fn _mm512_sqrt_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_sqrt_ph(a), src) } } @@ -8380,7 +8380,7 @@ pub fn _mm512_mask_sqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sqrt_ph(k: __mmask32, a: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_sqrt_ph(a), _mm512_setzero_ph()) } } @@ -8400,7 +8400,7 @@ pub fn _mm512_maskz_sqrt_ph(k: __mmask32, a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sqrt_round_ph(a: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -8423,7 +8423,7 @@ pub fn _mm512_sqrt_round_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sqrt_round_ph( src: __m512h, k: __mmask32, @@ -8450,7 +8450,7 @@ pub fn _mm512_mask_sqrt_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sqrt_round_ph(k: __mmask32, a: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -8466,7 +8466,7 @@ pub fn _mm512_maskz_sqrt_round_ph(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8479,7 +8479,7 @@ pub fn _mm_sqrt_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -8492,7 +8492,7 @@ pub fn _mm_mask_sqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8513,7 +8513,7 @@ pub fn _mm_maskz_sqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sqrt_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -8535,7 +8535,7 @@ pub fn _mm_sqrt_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_round_sh( src: __m128h, k: __mmask8, @@ -8564,7 +8564,7 @@ pub fn _mm_mask_sqrt_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_round_sh( k: __mmask8, a: __m128h, @@ -8582,7 +8582,7 @@ pub fn _mm_maskz_sqrt_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { vmaxph_128(a, b) } } @@ -8596,7 +8596,7 @@ pub fn _mm_max_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_max_ph(a, b), src) } } @@ -8610,7 +8610,7 @@ pub fn _mm_mask_max_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_max_ph(a, b), _mm_setzero_ph()) } } @@ -8623,7 +8623,7 @@ pub fn _mm_maskz_max_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_max_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { vmaxph_256(a, b) } } @@ -8637,7 +8637,7 @@ pub fn _mm256_max_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_max_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_max_ph(a, b), src) } } @@ -8651,7 +8651,7 @@ pub fn _mm256_mask_max_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_max_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_max_ph(a, b), _mm256_setzero_ph()) } } @@ -8664,7 +8664,7 @@ pub fn _mm256_maskz_max_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_max_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_max_round_ph::<_MM_FROUND_CUR_DIRECTION>(a, b) } @@ -8678,7 +8678,7 @@ pub fn _mm512_max_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_max_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_max_ph(a, b), src) } } @@ -8692,7 +8692,7 @@ pub fn _mm512_mask_max_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_max_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_max_ph(a, b), _mm512_setzero_ph()) } } @@ -8707,7 +8707,7 @@ pub fn _mm512_maskz_max_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_max_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -8725,7 +8725,7 @@ pub fn _mm512_max_round_ph(a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_max_round_ph( src: __m512h, k: __mmask32, @@ -8748,7 +8748,7 @@ pub fn _mm512_mask_max_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_max_round_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -8765,7 +8765,7 @@ pub fn _mm512_maskz_max_round_ph(k: __mmask32, a: __m512h, b: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_sh(_mm_undefined_ph(), 0xff, a, b) } @@ -8779,7 +8779,7 @@ pub fn _mm_max_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -8793,7 +8793,7 @@ pub fn _mm_mask_max_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8808,7 +8808,7 @@ pub fn _mm_maskz_max_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_max_round_sh::(_mm_undefined_ph(), 0xff, a, b) @@ -8825,7 +8825,7 @@ pub fn _mm_max_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_round_sh( src: __m128h, k: __mmask8, @@ -8849,7 +8849,7 @@ pub fn _mm_mask_max_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_max_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -8863,7 +8863,7 @@ pub fn _mm_maskz_max_round_sh(k: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { vminph_128(a, b) } } @@ -8877,7 +8877,7 @@ pub fn _mm_min_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_min_ph(a, b), src) } } @@ -8891,7 +8891,7 @@ pub fn _mm_mask_min_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_min_ph(a, b), _mm_setzero_ph()) } } @@ -8904,7 +8904,7 @@ pub fn _mm_maskz_min_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_min_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { vminph_256(a, b) } } @@ -8918,7 +8918,7 @@ pub fn _mm256_min_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_min_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_min_ph(a, b), src) } } @@ -8932,7 +8932,7 @@ pub fn _mm256_mask_min_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_min_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_min_ph(a, b), _mm256_setzero_ph()) } } @@ -8945,7 +8945,7 @@ pub fn _mm256_maskz_min_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_min_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_min_round_ph::<_MM_FROUND_CUR_DIRECTION>(a, b) } @@ -8959,7 +8959,7 @@ pub fn _mm512_min_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_min_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_min_ph(a, b), src) } } @@ -8973,7 +8973,7 @@ pub fn _mm512_mask_min_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_min_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_min_ph(a, b), _mm512_setzero_ph()) } } @@ -8987,7 +8987,7 @@ pub fn _mm512_maskz_min_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_min_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -9005,7 +9005,7 @@ pub fn _mm512_min_round_ph(a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_min_round_ph( src: __m512h, k: __mmask32, @@ -9028,7 +9028,7 @@ pub fn _mm512_mask_min_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_min_round_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -9045,7 +9045,7 @@ pub fn _mm512_maskz_min_round_ph(k: __mmask32, a: __m512h, b: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_sh(_mm_undefined_ph(), 0xff, a, b) } @@ -9059,7 +9059,7 @@ pub fn _mm_min_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -9073,7 +9073,7 @@ pub fn _mm_mask_min_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -9088,7 +9088,7 @@ pub fn _mm_maskz_min_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_min_round_sh::(_mm_undefined_ph(), 0xff, a, b) @@ -9105,7 +9105,7 @@ pub fn _mm_min_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_round_sh( src: __m128h, k: __mmask8, @@ -9129,7 +9129,7 @@ pub fn _mm_mask_min_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_min_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -9143,7 +9143,7 @@ pub fn _mm_maskz_min_round_sh(k: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_ph(a: __m128h) -> __m128h { _mm_mask_getexp_ph(_mm_undefined_ph(), 0xff, a) } @@ -9157,7 +9157,7 @@ pub fn _mm_getexp_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vgetexpph_128(a, src, k) } } @@ -9171,7 +9171,7 @@ pub fn _mm_mask_getexp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_getexp_ph(_mm_setzero_ph(), k, a) } @@ -9184,7 +9184,7 @@ pub fn _mm_maskz_getexp_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_getexp_ph(a: __m256h) -> __m256h { _mm256_mask_getexp_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -9198,7 +9198,7 @@ pub fn _mm256_getexp_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_getexp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vgetexpph_256(a, src, k) } } @@ -9212,7 +9212,7 @@ pub fn _mm256_mask_getexp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_getexp_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_getexp_ph(_mm256_setzero_ph(), k, a) } @@ -9225,7 +9225,7 @@ pub fn _mm256_maskz_getexp_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_getexp_ph(a: __m512h) -> __m512h { _mm512_mask_getexp_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -9239,7 +9239,7 @@ pub fn _mm512_getexp_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_getexp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_getexp_round_ph::<_MM_FROUND_CUR_DIRECTION>(src, k, a) } @@ -9253,7 +9253,7 @@ pub fn _mm512_mask_getexp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_getexp_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_getexp_ph(_mm512_setzero_ph(), k, a) } @@ -9268,7 +9268,7 @@ pub fn _mm512_maskz_getexp_ph(k: __mmask32, a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_getexp_round_ph(a: __m512h) -> __m512h { static_assert_sae!(SAE); _mm512_mask_getexp_round_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -9284,7 +9284,7 @@ pub fn _mm512_getexp_round_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_getexp_round_ph( src: __m512h, k: __mmask32, @@ -9306,7 +9306,7 @@ pub fn _mm512_mask_getexp_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_getexp_round_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_sae!(SAE); _mm512_mask_getexp_round_ph::(_mm512_setzero_ph(), k, a) @@ -9321,7 +9321,7 @@ pub fn _mm512_maskz_getexp_round_ph(k: __mmask32, a: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -9336,7 +9336,7 @@ pub fn _mm_getexp_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -9351,7 +9351,7 @@ pub fn _mm_mask_getexp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -9367,7 +9367,7 @@ pub fn _mm_maskz_getexp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_getexp_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -9384,7 +9384,7 @@ pub fn _mm_getexp_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_round_sh( src: __m128h, k: __mmask8, @@ -9408,7 +9408,7 @@ pub fn _mm_mask_getexp_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_getexp_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -9436,7 +9436,7 @@ pub fn _mm_maskz_getexp_round_sh(k: __mmask8, a: __m128h, b: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetmantph, NORM = 0, SIGN = 0))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getmant_ph( a: __m128h, ) -> __m128h { @@ -9468,7 +9468,7 @@ pub fn _mm_getmant_ph( a: __m256h, ) -> __m256h { @@ -9574,7 +9574,7 @@ pub fn _mm256_getmant_ph( a: __m512h, ) -> __m512h { @@ -9680,7 +9680,7 @@ pub fn _mm512_getmant_ph( a: __m128h, b: __m128h, @@ -9911,7 +9911,7 @@ pub fn _mm_getmant_sh(a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_ph::(_mm_undefined_ph(), 0xff, a) @@ -10131,7 +10131,7 @@ pub fn _mm_roundscale_ph(a: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10156,7 +10156,7 @@ pub fn _mm_mask_roundscale_ph(src: __m128h, k: __mmask8, a: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_ph(k: __mmask8, a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_ph::(_mm_setzero_ph(), k, a) @@ -10178,7 +10178,7 @@ pub fn _mm_maskz_roundscale_ph(k: __mmask8, a: __m128h) -> __m1 #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_roundscale_ph(a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_roundscale_ph::(_mm256_undefined_ph(), 0xffff, a) @@ -10201,7 +10201,7 @@ pub fn _mm256_roundscale_ph(a: __m256h) -> __m256h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_roundscale_ph( src: __m256h, k: __mmask16, @@ -10230,7 +10230,7 @@ pub fn _mm256_mask_roundscale_ph( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_roundscale_ph(k: __mmask16, a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_roundscale_ph::(_mm256_setzero_ph(), k, a) @@ -10252,7 +10252,7 @@ pub fn _mm256_maskz_roundscale_ph(k: __mmask16, a: __m256h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_roundscale_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_roundscale_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -10275,7 +10275,7 @@ pub fn _mm512_roundscale_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_roundscale_ph( src: __m512h, k: __mmask32, @@ -10302,7 +10302,7 @@ pub fn _mm512_mask_roundscale_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_roundscale_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_roundscale_ph::(_mm512_setzero_ph(), k, a) @@ -10325,7 +10325,7 @@ pub fn _mm512_maskz_roundscale_ph(k: __mmask32, a: __m512h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_roundscale_round_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -10350,7 +10350,7 @@ pub fn _mm512_roundscale_round_ph(a: __m512h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_roundscale_round_ph( src: __m512h, k: __mmask32, @@ -10380,7 +10380,7 @@ pub fn _mm512_mask_roundscale_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_roundscale_round_ph( k: __mmask32, a: __m512h, @@ -10407,7 +10407,7 @@ pub fn _mm512_maskz_roundscale_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_roundscale_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -10430,7 +10430,7 @@ pub fn _mm_roundscale_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_sh( src: __m128h, k: __mmask8, @@ -10458,7 +10458,7 @@ pub fn _mm_mask_roundscale_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -10483,7 +10483,7 @@ pub fn _mm_maskz_roundscale_sh(k: __mmask8, a: __m128h, b: __m1 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_roundscale_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -10509,7 +10509,7 @@ pub fn _mm_roundscale_round_sh(a: __m128h, b: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(4, 5)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_round_sh( src: __m128h, k: __mmask8, @@ -10542,7 +10542,7 @@ pub fn _mm_mask_roundscale_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_round_sh( k: __mmask8, a: __m128h, @@ -10560,7 +10560,7 @@ pub fn _mm_maskz_roundscale_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_ph(a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_ph(_mm_undefined_ph(), 0xff, a, b) } @@ -10572,7 +10572,7 @@ pub fn _mm_scalef_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vscalefph_128(a, b, src, k) } } @@ -10584,7 +10584,7 @@ pub fn _mm_mask_scalef_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_ph(_mm_setzero_ph(), k, a, b) } @@ -10596,7 +10596,7 @@ pub fn _mm_maskz_scalef_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_scalef_ph(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_scalef_ph(_mm256_undefined_ph(), 0xffff, a, b) } @@ -10608,7 +10608,7 @@ pub fn _mm256_scalef_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_scalef_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { vscalefph_256(a, b, src, k) } } @@ -10620,7 +10620,7 @@ pub fn _mm256_mask_scalef_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_scalef_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_scalef_ph(_mm256_setzero_ph(), k, a, b) } @@ -10632,7 +10632,7 @@ pub fn _mm256_maskz_scalef_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_scalef_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_ph(_mm512_undefined_ph(), 0xffffffff, a, b) } @@ -10644,7 +10644,7 @@ pub fn _mm512_scalef_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_scalef_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_round_ph::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -10656,7 +10656,7 @@ pub fn _mm512_mask_scalef_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_scalef_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_ph(_mm512_setzero_ph(), k, a, b) } @@ -10677,7 +10677,7 @@ pub fn _mm512_maskz_scalef_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_scalef_round_ph(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_scalef_round_ph::(_mm512_undefined_ph(), 0xffffffff, a, b) @@ -10699,7 +10699,7 @@ pub fn _mm512_scalef_round_ph(a: __m512h, b: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_scalef_round_ph( src: __m512h, k: __mmask32, @@ -10728,7 +10728,7 @@ pub fn _mm512_mask_scalef_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_scalef_round_ph( k: __mmask32, a: __m512h, @@ -10746,7 +10746,7 @@ pub fn _mm512_maskz_scalef_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -10759,7 +10759,7 @@ pub fn _mm_scalef_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -10772,7 +10772,7 @@ pub fn _mm_mask_scalef_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -10794,7 +10794,7 @@ pub fn _mm_maskz_scalef_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_scalef_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -10817,7 +10817,7 @@ pub fn _mm_scalef_round_sh(a: __m128h, b: __m128h) -> __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_round_sh( src: __m128h, k: __mmask8, @@ -10847,7 +10847,7 @@ pub fn _mm_mask_scalef_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_round_sh( k: __mmask8, a: __m128h, @@ -10873,7 +10873,7 @@ pub fn _mm_maskz_scalef_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_ph(a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_ph::(_mm_undefined_ph(), 0xff, a) @@ -10896,7 +10896,7 @@ pub fn _mm_reduce_ph(a: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10921,7 +10921,7 @@ pub fn _mm_mask_reduce_ph(src: __m128h, k: __mmask8, a: __m128h #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_ph(k: __mmask8, a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_ph::(_mm_setzero_ph(), k, a) @@ -10943,7 +10943,7 @@ pub fn _mm_maskz_reduce_ph(k: __mmask8, a: __m128h) -> __m128h #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_reduce_ph(a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_reduce_ph::(_mm256_undefined_ph(), 0xffff, a) @@ -10966,7 +10966,7 @@ pub fn _mm256_reduce_ph(a: __m256h) -> __m256h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_reduce_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10991,7 +10991,7 @@ pub fn _mm256_mask_reduce_ph(src: __m256h, k: __mmask16, a: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_reduce_ph(k: __mmask16, a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_reduce_ph::(_mm256_setzero_ph(), k, a) @@ -11013,7 +11013,7 @@ pub fn _mm256_maskz_reduce_ph(k: __mmask16, a: __m256h) -> __m2 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_reduce_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -11036,7 +11036,7 @@ pub fn _mm512_reduce_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_reduce_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_round_ph::(src, k, a) @@ -11059,7 +11059,7 @@ pub fn _mm512_mask_reduce_ph(src: __m512h, k: __mmask32, a: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_reduce_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_ph::(_mm512_setzero_ph(), k, a) @@ -11083,7 +11083,7 @@ pub fn _mm512_maskz_reduce_ph(k: __mmask32, a: __m512h) -> __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_reduce_round_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -11109,7 +11109,7 @@ pub fn _mm512_reduce_round_ph(a: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_reduce_round_ph( src: __m512h, k: __mmask32, @@ -11141,7 +11141,7 @@ pub fn _mm512_mask_reduce_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_reduce_round_ph( k: __mmask32, a: __m512h, @@ -11168,7 +11168,7 @@ pub fn _mm512_maskz_reduce_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -11192,7 +11192,7 @@ pub fn _mm_reduce_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_sh( src: __m128h, k: __mmask8, @@ -11221,7 +11221,7 @@ pub fn _mm_mask_reduce_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -11246,7 +11246,7 @@ pub fn _mm_maskz_reduce_sh(k: __mmask8, a: __m128h, b: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -11273,7 +11273,7 @@ pub fn _mm_reduce_round_sh(a: __m128h, b: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(4, 5)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_round_sh( src: __m128h, k: __mmask8, @@ -11307,7 +11307,7 @@ pub fn _mm_mask_reduce_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_round_sh( k: __mmask8, a: __m128h, @@ -11582,7 +11582,7 @@ macro_rules! fpclass_asm { // FIXME: use LLVM intrinsics #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fpclass_ph_mask(a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11609,7 +11609,7 @@ pub fn _mm_fpclass_ph_mask(a: __m128h) -> __mmask8 { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fpclass_ph_mask(k1: __mmask8, a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11635,7 +11635,7 @@ pub fn _mm_mask_fpclass_ph_mask(k1: __mmask8, a: __m128h) -> __ #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fpclass_ph_mask(a: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11662,7 +11662,7 @@ pub fn _mm256_fpclass_ph_mask(a: __m256h) -> __mmask16 { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fpclass_ph_mask(k1: __mmask16, a: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11688,7 +11688,7 @@ pub fn _mm256_mask_fpclass_ph_mask(k1: __mmask16, a: __m256h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fpclass_ph_mask(a: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11715,7 +11715,7 @@ pub fn _mm512_fpclass_ph_mask(a: __m512h) -> __mmask32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fpclass_ph_mask(k1: __mmask32, a: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11741,7 +11741,7 @@ pub fn _mm512_mask_fpclass_ph_mask(k1: __mmask32, a: __m512h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclasssh, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fpclass_sh_mask(a: __m128h) -> __mmask8 { _mm_mask_fpclass_sh_mask::(0xff, a) } @@ -11765,7 +11765,7 @@ pub fn _mm_fpclass_sh_mask(a: __m128h) -> __mmask8 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclasssh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fpclass_sh_mask(k1: __mmask8, a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11779,7 +11779,7 @@ pub fn _mm_mask_fpclass_sh_mask(k1: __mmask8, a: __m128h) -> __ /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_blend_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, b, a) } @@ -11791,7 +11791,7 @@ pub const fn _mm_mask_blend_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_blend_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, b, a) } @@ -11803,7 +11803,7 @@ pub const fn _mm256_mask_blend_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m25 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_blend_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, b, a) } @@ -11815,7 +11815,7 @@ pub const fn _mm512_mask_blend_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m51 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_permutex2var_ph(a: __m128h, idx: __m128i, b: __m128h) -> __m128h { _mm_castsi128_ph(_mm_permutex2var_epi16( _mm_castph_si128(a), @@ -11830,7 +11830,7 @@ pub fn _mm_permutex2var_ph(a: __m128h, idx: __m128i, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_permutex2var_ph(a: __m256h, idx: __m256i, b: __m256h) -> __m256h { _mm256_castsi256_ph(_mm256_permutex2var_epi16( _mm256_castph_si256(a), @@ -11845,7 +11845,7 @@ pub fn _mm256_permutex2var_ph(a: __m256h, idx: __m256i, b: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_permutex2var_ph(a: __m512h, idx: __m512i, b: __m512h) -> __m512h { _mm512_castsi512_ph(_mm512_permutex2var_epi16( _mm512_castph_si512(a), @@ -11860,7 +11860,7 @@ pub fn _mm512_permutex2var_ph(a: __m512h, idx: __m512i, b: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_permutexvar_ph(idx: __m128i, a: __m128h) -> __m128h { _mm_castsi128_ph(_mm_permutexvar_epi16(idx, _mm_castph_si128(a))) } @@ -11871,7 +11871,7 @@ pub fn _mm_permutexvar_ph(idx: __m128i, a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_permutexvar_ph(idx: __m256i, a: __m256h) -> __m256h { _mm256_castsi256_ph(_mm256_permutexvar_epi16(idx, _mm256_castph_si256(a))) } @@ -11882,7 +11882,7 @@ pub fn _mm256_permutexvar_ph(idx: __m256i, a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_permutexvar_ph(idx: __m512i, a: __m512h) -> __m512h { _mm512_castsi512_ph(_mm512_permutexvar_epi16(idx, _mm512_castph_si512(a))) } @@ -11894,7 +11894,7 @@ pub fn _mm512_permutexvar_ph(idx: __m512i, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi16_ph(a: __m128i) -> __m128h { unsafe { vcvtw2ph_128(a.as_i16x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -11907,7 +11907,7 @@ pub fn _mm_cvtepi16_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { simd_select_bitmask(k, _mm_cvtepi16_ph(a), src) } } @@ -11919,7 +11919,7 @@ pub fn _mm_mask_cvtepi16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi16_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi16_ph(_mm_setzero_ph(), k, a) } @@ -11931,7 +11931,7 @@ pub fn _mm_maskz_cvtepi16_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi16_ph(a: __m256i) -> __m256h { unsafe { vcvtw2ph_256(a.as_i16x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -11944,7 +11944,7 @@ pub fn _mm256_cvtepi16_ph(a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_cvtepi16_ph(a), src) } } @@ -11956,7 +11956,7 @@ pub fn _mm256_mask_cvtepi16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi16_ph(k: __mmask16, a: __m256i) -> __m256h { _mm256_mask_cvtepi16_ph(_mm256_setzero_ph(), k, a) } @@ -11968,7 +11968,7 @@ pub fn _mm256_maskz_cvtepi16_ph(k: __mmask16, a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi16_ph(a: __m512i) -> __m512h { unsafe { vcvtw2ph_512(a.as_i16x32(), _MM_FROUND_CUR_DIRECTION) } } @@ -11981,7 +11981,7 @@ pub fn _mm512_cvtepi16_ph(a: __m512i) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_cvtepi16_ph(a), src) } } @@ -11993,7 +11993,7 @@ pub fn _mm512_mask_cvtepi16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi16_ph(k: __mmask32, a: __m512i) -> __m512h { _mm512_mask_cvtepi16_ph(_mm512_setzero_ph(), k, a) } @@ -12014,7 +12014,7 @@ pub fn _mm512_maskz_cvtepi16_ph(k: __mmask32, a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi16_ph(a: __m512i) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -12039,7 +12039,7 @@ pub fn _mm512_cvt_roundepi16_ph(a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi16_ph( src: __m512h, k: __mmask32, @@ -12067,7 +12067,7 @@ pub fn _mm512_mask_cvt_roundepi16_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi16_ph(k: __mmask32, a: __m512i) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi16_ph::(_mm512_setzero_ph(), k, a) @@ -12080,7 +12080,7 @@ pub fn _mm512_maskz_cvt_roundepi16_ph(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu16_ph(a: __m128i) -> __m128h { unsafe { vcvtuw2ph_128(a.as_u16x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12093,7 +12093,7 @@ pub fn _mm_cvtepu16_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { simd_select_bitmask(k, _mm_cvtepu16_ph(a), src) } } @@ -12105,7 +12105,7 @@ pub fn _mm_mask_cvtepu16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu16_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu16_ph(_mm_setzero_ph(), k, a) } @@ -12117,7 +12117,7 @@ pub fn _mm_maskz_cvtepu16_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu16_ph(a: __m256i) -> __m256h { unsafe { vcvtuw2ph_256(a.as_u16x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12130,7 +12130,7 @@ pub fn _mm256_cvtepu16_ph(a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_cvtepu16_ph(a), src) } } @@ -12142,7 +12142,7 @@ pub fn _mm256_mask_cvtepu16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu16_ph(k: __mmask16, a: __m256i) -> __m256h { _mm256_mask_cvtepu16_ph(_mm256_setzero_ph(), k, a) } @@ -12154,7 +12154,7 @@ pub fn _mm256_maskz_cvtepu16_ph(k: __mmask16, a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu16_ph(a: __m512i) -> __m512h { unsafe { vcvtuw2ph_512(a.as_u16x32(), _MM_FROUND_CUR_DIRECTION) } } @@ -12167,7 +12167,7 @@ pub fn _mm512_cvtepu16_ph(a: __m512i) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_cvtepu16_ph(a), src) } } @@ -12179,7 +12179,7 @@ pub fn _mm512_mask_cvtepu16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu16_ph(k: __mmask32, a: __m512i) -> __m512h { _mm512_mask_cvtepu16_ph(_mm512_setzero_ph(), k, a) } @@ -12200,7 +12200,7 @@ pub fn _mm512_maskz_cvtepu16_ph(k: __mmask32, a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu16_ph(a: __m512i) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -12225,7 +12225,7 @@ pub fn _mm512_cvt_roundepu16_ph(a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu16_ph( src: __m512h, k: __mmask32, @@ -12253,7 +12253,7 @@ pub fn _mm512_mask_cvt_roundepu16_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu16_ph(k: __mmask32, a: __m512i) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu16_ph::(_mm512_setzero_ph(), k, a) @@ -12266,7 +12266,7 @@ pub fn _mm512_maskz_cvt_roundepu16_ph(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi32_ph(a: __m128i) -> __m128h { _mm_mask_cvtepi32_ph(_mm_setzero_ph(), 0xff, a) } @@ -12279,7 +12279,7 @@ pub fn _mm_cvtepi32_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtdq2ph_128(a.as_i32x4(), src, k) } } @@ -12292,7 +12292,7 @@ pub fn _mm_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi32_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi32_ph(_mm_setzero_ph(), k, a) } @@ -12304,7 +12304,7 @@ pub fn _mm_maskz_cvtepi32_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi32_ph(a: __m256i) -> __m128h { unsafe { vcvtdq2ph_256(a.as_i32x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12317,7 +12317,7 @@ pub fn _mm256_cvtepi32_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { simd_select_bitmask(k, _mm256_cvtepi32_ph(a), src) } } @@ -12329,7 +12329,7 @@ pub fn _mm256_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi32_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepi32_ph(_mm_setzero_ph(), k, a) } @@ -12341,7 +12341,7 @@ pub fn _mm256_maskz_cvtepi32_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi32_ph(a: __m512i) -> __m256h { unsafe { vcvtdq2ph_512(a.as_i32x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12354,7 +12354,7 @@ pub fn _mm512_cvtepi32_ph(a: __m512i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256h { unsafe { simd_select_bitmask(k, _mm512_cvtepi32_ph(a), src) } } @@ -12366,7 +12366,7 @@ pub fn _mm512_mask_cvtepi32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi32_ph(k: __mmask16, a: __m512i) -> __m256h { _mm512_mask_cvtepi32_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -12387,7 +12387,7 @@ pub fn _mm512_maskz_cvtepi32_ph(k: __mmask16, a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi32_ph(a: __m512i) -> __m256h { unsafe { static_assert_rounding!(ROUNDING); @@ -12412,7 +12412,7 @@ pub fn _mm512_cvt_roundepi32_ph(a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi32_ph( src: __m256h, k: __mmask16, @@ -12440,7 +12440,7 @@ pub fn _mm512_mask_cvt_roundepi32_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi32_ph(k: __mmask16, a: __m512i) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi32_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -12454,7 +12454,7 @@ pub fn _mm512_maskz_cvt_roundepi32_ph(k: __mmask16, a: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvti32_sh(a: __m128h, b: i32) -> __m128h { unsafe { vcvtsi2sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -12476,7 +12476,7 @@ pub fn _mm_cvti32_sh(a: __m128h, b: i32) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundi32_sh(a: __m128h, b: i32) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12491,7 +12491,7 @@ pub fn _mm_cvt_roundi32_sh(a: __m128h, b: i32) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu32_ph(a: __m128i) -> __m128h { _mm_mask_cvtepu32_ph(_mm_setzero_ph(), 0xff, a) } @@ -12504,7 +12504,7 @@ pub fn _mm_cvtepu32_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtudq2ph_128(a.as_u32x4(), src, k) } } @@ -12517,7 +12517,7 @@ pub fn _mm_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu32_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu32_ph(_mm_setzero_ph(), k, a) } @@ -12529,7 +12529,7 @@ pub fn _mm_maskz_cvtepu32_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu32_ph(a: __m256i) -> __m128h { unsafe { vcvtudq2ph_256(a.as_u32x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12542,7 +12542,7 @@ pub fn _mm256_cvtepu32_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { simd_select_bitmask(k, _mm256_cvtepu32_ph(a), src) } } @@ -12554,7 +12554,7 @@ pub fn _mm256_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu32_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepu32_ph(_mm_setzero_ph(), k, a) } @@ -12566,7 +12566,7 @@ pub fn _mm256_maskz_cvtepu32_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu32_ph(a: __m512i) -> __m256h { unsafe { vcvtudq2ph_512(a.as_u32x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12579,7 +12579,7 @@ pub fn _mm512_cvtepu32_ph(a: __m512i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256h { unsafe { simd_select_bitmask(k, _mm512_cvtepu32_ph(a), src) } } @@ -12591,7 +12591,7 @@ pub fn _mm512_mask_cvtepu32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu32_ph(k: __mmask16, a: __m512i) -> __m256h { _mm512_mask_cvtepu32_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -12612,7 +12612,7 @@ pub fn _mm512_maskz_cvtepu32_ph(k: __mmask16, a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu32_ph(a: __m512i) -> __m256h { unsafe { static_assert_rounding!(ROUNDING); @@ -12637,7 +12637,7 @@ pub fn _mm512_cvt_roundepu32_ph(a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu32_ph( src: __m256h, k: __mmask16, @@ -12665,7 +12665,7 @@ pub fn _mm512_mask_cvt_roundepu32_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu32_ph(k: __mmask16, a: __m512i) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu32_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -12679,7 +12679,7 @@ pub fn _mm512_maskz_cvt_roundepu32_ph(k: __mmask16, a: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtu32_sh(a: __m128h, b: u32) -> __m128h { unsafe { vcvtusi2sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -12701,7 +12701,7 @@ pub fn _mm_cvtu32_sh(a: __m128h, b: u32) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundu32_sh(a: __m128h, b: u32) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12716,7 +12716,7 @@ pub fn _mm_cvt_roundu32_sh(a: __m128h, b: u32) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi64_ph(a: __m128i) -> __m128h { _mm_mask_cvtepi64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12729,7 +12729,7 @@ pub fn _mm_cvtepi64_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtqq2ph_128(a.as_i64x2(), src, k) } } @@ -12742,7 +12742,7 @@ pub fn _mm_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi64_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi64_ph(_mm_setzero_ph(), k, a) } @@ -12754,7 +12754,7 @@ pub fn _mm_maskz_cvtepi64_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi64_ph(a: __m256i) -> __m128h { _mm256_mask_cvtepi64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12767,7 +12767,7 @@ pub fn _mm256_cvtepi64_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { vcvtqq2ph_256(a.as_i64x4(), src, k) } } @@ -12780,7 +12780,7 @@ pub fn _mm256_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi64_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepi64_ph(_mm_setzero_ph(), k, a) } @@ -12792,7 +12792,7 @@ pub fn _mm256_maskz_cvtepi64_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi64_ph(a: __m512i) -> __m128h { unsafe { vcvtqq2ph_512(a.as_i64x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12805,7 +12805,7 @@ pub fn _mm512_cvtepi64_ph(a: __m512i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h { unsafe { simd_select_bitmask(k, _mm512_cvtepi64_ph(a), src) } } @@ -12817,7 +12817,7 @@ pub fn _mm512_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi64_ph(k: __mmask8, a: __m512i) -> __m128h { _mm512_mask_cvtepi64_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -12838,7 +12838,7 @@ pub fn _mm512_maskz_cvtepi64_ph(k: __mmask8, a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi64_ph(a: __m512i) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12863,7 +12863,7 @@ pub fn _mm512_cvt_roundepi64_ph(a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi64_ph( src: __m128h, k: __mmask8, @@ -12891,7 +12891,7 @@ pub fn _mm512_mask_cvt_roundepi64_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi64_ph(k: __mmask8, a: __m512i) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi64_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -12904,7 +12904,7 @@ pub fn _mm512_maskz_cvt_roundepi64_ph(k: __mmask8, a: __m51 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu64_ph(a: __m128i) -> __m128h { _mm_mask_cvtepu64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12917,7 +12917,7 @@ pub fn _mm_cvtepu64_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtuqq2ph_128(a.as_u64x2(), src, k) } } @@ -12930,7 +12930,7 @@ pub fn _mm_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu64_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu64_ph(_mm_setzero_ph(), k, a) } @@ -12942,7 +12942,7 @@ pub fn _mm_maskz_cvtepu64_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu64_ph(a: __m256i) -> __m128h { _mm256_mask_cvtepu64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12955,7 +12955,7 @@ pub fn _mm256_cvtepu64_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { vcvtuqq2ph_256(a.as_u64x4(), src, k) } } @@ -12968,7 +12968,7 @@ pub fn _mm256_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu64_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepu64_ph(_mm_setzero_ph(), k, a) } @@ -12980,7 +12980,7 @@ pub fn _mm256_maskz_cvtepu64_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu64_ph(a: __m512i) -> __m128h { unsafe { vcvtuqq2ph_512(a.as_u64x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12993,7 +12993,7 @@ pub fn _mm512_cvtepu64_ph(a: __m512i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h { unsafe { simd_select_bitmask(k, _mm512_cvtepu64_ph(a), src) } } @@ -13005,7 +13005,7 @@ pub fn _mm512_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu64_ph(k: __mmask8, a: __m512i) -> __m128h { _mm512_mask_cvtepu64_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -13026,7 +13026,7 @@ pub fn _mm512_maskz_cvtepu64_ph(k: __mmask8, a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu64_ph(a: __m512i) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -13051,7 +13051,7 @@ pub fn _mm512_cvt_roundepu64_ph(a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu64_ph( src: __m128h, k: __mmask8, @@ -13079,7 +13079,7 @@ pub fn _mm512_mask_cvt_roundepu64_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu64_ph(k: __mmask8, a: __m512i) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu64_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -13092,7 +13092,7 @@ pub fn _mm512_maskz_cvt_roundepu64_ph(k: __mmask8, a: __m51 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtxps_ph(a: __m128) -> __m128h { _mm_mask_cvtxps_ph(_mm_setzero_ph(), 0xff, a) } @@ -13105,7 +13105,7 @@ pub fn _mm_cvtxps_ph(a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m128) -> __m128h { unsafe { vcvtps2phx_128(a, src, k) } } @@ -13118,7 +13118,7 @@ pub fn _mm_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtxps_ph(k: __mmask8, a: __m128) -> __m128h { _mm_mask_cvtxps_ph(_mm_setzero_ph(), k, a) } @@ -13130,7 +13130,7 @@ pub fn _mm_maskz_cvtxps_ph(k: __mmask8, a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtxps_ph(a: __m256) -> __m128h { _mm256_mask_cvtxps_ph(_mm_setzero_ph(), 0xff, a) } @@ -13143,7 +13143,7 @@ pub fn _mm256_cvtxps_ph(a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m256) -> __m128h { unsafe { vcvtps2phx_256(a, src, k) } } @@ -13156,7 +13156,7 @@ pub fn _mm256_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtxps_ph(k: __mmask8, a: __m256) -> __m128h { _mm256_mask_cvtxps_ph(_mm_setzero_ph(), k, a) } @@ -13168,7 +13168,7 @@ pub fn _mm256_maskz_cvtxps_ph(k: __mmask8, a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtxps_ph(a: __m512) -> __m256h { _mm512_mask_cvtxps_ph(f16x16::ZERO.as_m256h(), 0xffff, a) } @@ -13181,7 +13181,7 @@ pub fn _mm512_cvtxps_ph(a: __m512) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtxps_ph(src: __m256h, k: __mmask16, a: __m512) -> __m256h { unsafe { vcvtps2phx_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13194,7 +13194,7 @@ pub fn _mm512_mask_cvtxps_ph(src: __m256h, k: __mmask16, a: __m512) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtxps_ph(k: __mmask16, a: __m512) -> __m256h { _mm512_mask_cvtxps_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -13215,7 +13215,7 @@ pub fn _mm512_maskz_cvtxps_ph(k: __mmask16, a: __m512) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtx_roundps_ph(a: __m512) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvtx_roundps_ph::(f16x16::ZERO.as_m256h(), 0xffff, a) @@ -13238,7 +13238,7 @@ pub fn _mm512_cvtx_roundps_ph(a: __m512) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtx_roundps_ph( src: __m256h, k: __mmask16, @@ -13267,7 +13267,7 @@ pub fn _mm512_mask_cvtx_roundps_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtx_roundps_ph(k: __mmask16, a: __m512) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvtx_roundps_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -13281,7 +13281,7 @@ pub fn _mm512_maskz_cvtx_roundps_ph(k: __mmask16, a: __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtss_sh(a: __m128h, b: __m128) -> __m128h { _mm_mask_cvtss_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -13295,7 +13295,7 @@ pub fn _mm_cvtss_sh(a: __m128h, b: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtss_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128) -> __m128h { unsafe { vcvtss2sh(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13309,7 +13309,7 @@ pub fn _mm_mask_cvtss_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtss_sh(k: __mmask8, a: __m128h, b: __m128) -> __m128h { _mm_mask_cvtss_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -13331,7 +13331,7 @@ pub fn _mm_maskz_cvtss_sh(k: __mmask8, a: __m128h, b: __m128) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundss_sh(a: __m128h, b: __m128) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cvt_roundss_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -13355,7 +13355,7 @@ pub fn _mm_cvt_roundss_sh(a: __m128h, b: __m128) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundss_sh( src: __m128h, k: __mmask8, @@ -13386,7 +13386,7 @@ pub fn _mm_mask_cvt_roundss_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundss_sh( k: __mmask8, a: __m128h, @@ -13403,7 +13403,7 @@ pub fn _mm_maskz_cvt_roundss_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtpd_ph(a: __m128d) -> __m128h { _mm_mask_cvtpd_ph(_mm_setzero_ph(), 0xff, a) } @@ -13416,7 +13416,7 @@ pub fn _mm_cvtpd_ph(a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m128d) -> __m128h { unsafe { vcvtpd2ph_128(a, src, k) } } @@ -13429,7 +13429,7 @@ pub fn _mm_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtpd_ph(k: __mmask8, a: __m128d) -> __m128h { _mm_mask_cvtpd_ph(_mm_setzero_ph(), k, a) } @@ -13441,7 +13441,7 @@ pub fn _mm_maskz_cvtpd_ph(k: __mmask8, a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtpd_ph(a: __m256d) -> __m128h { _mm256_mask_cvtpd_ph(_mm_setzero_ph(), 0xff, a) } @@ -13454,7 +13454,7 @@ pub fn _mm256_cvtpd_ph(a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m256d) -> __m128h { unsafe { vcvtpd2ph_256(a, src, k) } } @@ -13467,7 +13467,7 @@ pub fn _mm256_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtpd_ph(k: __mmask8, a: __m256d) -> __m128h { _mm256_mask_cvtpd_ph(_mm_setzero_ph(), k, a) } @@ -13479,7 +13479,7 @@ pub fn _mm256_maskz_cvtpd_ph(k: __mmask8, a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtpd_ph(a: __m512d) -> __m128h { _mm512_mask_cvtpd_ph(f16x8::ZERO.as_m128h(), 0xff, a) } @@ -13492,7 +13492,7 @@ pub fn _mm512_cvtpd_ph(a: __m512d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m512d) -> __m128h { unsafe { vcvtpd2ph_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13505,7 +13505,7 @@ pub fn _mm512_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m512d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtpd_ph(k: __mmask8, a: __m512d) -> __m128h { _mm512_mask_cvtpd_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -13526,7 +13526,7 @@ pub fn _mm512_maskz_cvtpd_ph(k: __mmask8, a: __m512d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundpd_ph(a: __m512d) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundpd_ph::(f16x8::ZERO.as_m128h(), 0xff, a) @@ -13549,7 +13549,7 @@ pub fn _mm512_cvt_roundpd_ph(a: __m512d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundpd_ph( src: __m128h, k: __mmask8, @@ -13578,7 +13578,7 @@ pub fn _mm512_mask_cvt_roundpd_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundpd_ph(k: __mmask8, a: __m512d) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundpd_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -13592,7 +13592,7 @@ pub fn _mm512_maskz_cvt_roundpd_ph(k: __mmask8, a: __m512d) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsd_sh(a: __m128h, b: __m128d) -> __m128h { _mm_mask_cvtsd_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -13606,7 +13606,7 @@ pub fn _mm_cvtsd_sh(a: __m128h, b: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsd_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128d) -> __m128h { unsafe { vcvtsd2sh(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13620,7 +13620,7 @@ pub fn _mm_mask_cvtsd_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128d) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsd_sh(k: __mmask8, a: __m128h, b: __m128d) -> __m128h { _mm_mask_cvtsd_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -13642,7 +13642,7 @@ pub fn _mm_maskz_cvtsd_sh(k: __mmask8, a: __m128h, b: __m128d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsd_sh(a: __m128h, b: __m128d) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cvt_roundsd_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -13666,7 +13666,7 @@ pub fn _mm_cvt_roundsd_sh(a: __m128h, b: __m128d) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsd_sh( src: __m128h, k: __mmask8, @@ -13697,7 +13697,7 @@ pub fn _mm_mask_cvt_roundsd_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsd_sh( k: __mmask8, a: __m128h, @@ -13714,7 +13714,7 @@ pub fn _mm_maskz_cvt_roundsd_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi16(a: __m128h) -> __m128i { _mm_mask_cvtph_epi16(_mm_undefined_si128(), 0xff, a) } @@ -13727,7 +13727,7 @@ pub fn _mm_cvtph_epi16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2w_128(a, src.as_i16x8(), k)) } } @@ -13739,7 +13739,7 @@ pub fn _mm_mask_cvtph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi16(_mm_setzero_si128(), k, a) } @@ -13751,7 +13751,7 @@ pub fn _mm_maskz_cvtph_epi16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi16(a: __m256h) -> __m256i { _mm256_mask_cvtph_epi16(_mm256_undefined_si256(), 0xffff, a) } @@ -13764,7 +13764,7 @@ pub fn _mm256_cvtph_epi16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvtph2w_256(a, src.as_i16x16(), k)) } } @@ -13776,7 +13776,7 @@ pub fn _mm256_mask_cvtph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvtph_epi16(_mm256_setzero_si256(), k, a) } @@ -13788,7 +13788,7 @@ pub fn _mm256_maskz_cvtph_epi16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi16(a: __m512h) -> __m512i { _mm512_mask_cvtph_epi16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -13801,7 +13801,7 @@ pub fn _mm512_cvtph_epi16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvtph2w_512( @@ -13820,7 +13820,7 @@ pub fn _mm512_mask_cvtph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvtph_epi16(_mm512_setzero_si512(), k, a) } @@ -13841,7 +13841,7 @@ pub fn _mm512_maskz_cvtph_epi16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi16(a: __m512h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -13864,7 +13864,7 @@ pub fn _mm512_cvt_roundph_epi16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi16( src: __m512i, k: __mmask32, @@ -13892,7 +13892,7 @@ pub fn _mm512_mask_cvt_roundph_epi16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi16(k: __mmask32, a: __m512h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi16::(_mm512_setzero_si512(), k, a) @@ -13905,7 +13905,7 @@ pub fn _mm512_maskz_cvt_roundph_epi16(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu16(a: __m128h) -> __m128i { _mm_mask_cvtph_epu16(_mm_undefined_si128(), 0xff, a) } @@ -13918,7 +13918,7 @@ pub fn _mm_cvtph_epu16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2uw_128(a, src.as_u16x8(), k)) } } @@ -13930,7 +13930,7 @@ pub fn _mm_mask_cvtph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu16(_mm_setzero_si128(), k, a) } @@ -13942,7 +13942,7 @@ pub fn _mm_maskz_cvtph_epu16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu16(a: __m256h) -> __m256i { _mm256_mask_cvtph_epu16(_mm256_undefined_si256(), 0xffff, a) } @@ -13955,7 +13955,7 @@ pub fn _mm256_cvtph_epu16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvtph2uw_256(a, src.as_u16x16(), k)) } } @@ -13967,7 +13967,7 @@ pub fn _mm256_mask_cvtph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvtph_epu16(_mm256_setzero_si256(), k, a) } @@ -13979,7 +13979,7 @@ pub fn _mm256_maskz_cvtph_epu16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu16(a: __m512h) -> __m512i { _mm512_mask_cvtph_epu16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -13992,7 +13992,7 @@ pub fn _mm512_cvtph_epu16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvtph2uw_512( @@ -14011,7 +14011,7 @@ pub fn _mm512_mask_cvtph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvtph_epu16(_mm512_setzero_si512(), k, a) } @@ -14026,7 +14026,7 @@ pub fn _mm512_maskz_cvtph_epu16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_epu16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14043,7 +14043,7 @@ pub fn _mm512_cvt_roundph_epu16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu16( src: __m512i, k: __mmask32, @@ -14065,7 +14065,7 @@ pub fn _mm512_mask_cvt_roundph_epu16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_epu16::(_mm512_setzero_si512(), k, a) @@ -14078,7 +14078,7 @@ pub fn _mm512_maskz_cvt_roundph_epu16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi16(a: __m128h) -> __m128i { _mm_mask_cvttph_epi16(_mm_undefined_si128(), 0xff, a) } @@ -14091,7 +14091,7 @@ pub fn _mm_cvttph_epi16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2w_128(a, src.as_i16x8(), k)) } } @@ -14104,7 +14104,7 @@ pub fn _mm_mask_cvttph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi16(_mm_setzero_si128(), k, a) } @@ -14116,7 +14116,7 @@ pub fn _mm_maskz_cvttph_epi16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi16(a: __m256h) -> __m256i { _mm256_mask_cvttph_epi16(_mm256_undefined_si256(), 0xffff, a) } @@ -14129,7 +14129,7 @@ pub fn _mm256_cvttph_epi16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvttph2w_256(a, src.as_i16x16(), k)) } } @@ -14142,7 +14142,7 @@ pub fn _mm256_mask_cvttph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvttph_epi16(_mm256_setzero_si256(), k, a) } @@ -14154,7 +14154,7 @@ pub fn _mm256_maskz_cvttph_epi16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi16(a: __m512h) -> __m512i { _mm512_mask_cvttph_epi16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -14167,7 +14167,7 @@ pub fn _mm512_cvttph_epi16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvttph2w_512( @@ -14187,7 +14187,7 @@ pub fn _mm512_mask_cvttph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvttph_epi16(_mm512_setzero_si512(), k, a) } @@ -14202,7 +14202,7 @@ pub fn _mm512_maskz_cvttph_epi16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14219,7 +14219,7 @@ pub fn _mm512_cvtt_roundph_epi16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi16( src: __m512i, k: __mmask32, @@ -14242,7 +14242,7 @@ pub fn _mm512_mask_cvtt_roundph_epi16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi16::(_mm512_setzero_si512(), k, a) @@ -14255,7 +14255,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu16(a: __m128h) -> __m128i { _mm_mask_cvttph_epu16(_mm_undefined_si128(), 0xff, a) } @@ -14268,7 +14268,7 @@ pub fn _mm_cvttph_epu16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2uw_128(a, src.as_u16x8(), k)) } } @@ -14281,7 +14281,7 @@ pub fn _mm_mask_cvttph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu16(_mm_setzero_si128(), k, a) } @@ -14293,7 +14293,7 @@ pub fn _mm_maskz_cvttph_epu16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu16(a: __m256h) -> __m256i { _mm256_mask_cvttph_epu16(_mm256_undefined_si256(), 0xffff, a) } @@ -14306,7 +14306,7 @@ pub fn _mm256_cvttph_epu16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvttph2uw_256(a, src.as_u16x16(), k)) } } @@ -14319,7 +14319,7 @@ pub fn _mm256_mask_cvttph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvttph_epu16(_mm256_setzero_si256(), k, a) } @@ -14331,7 +14331,7 @@ pub fn _mm256_maskz_cvttph_epu16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu16(a: __m512h) -> __m512i { _mm512_mask_cvttph_epu16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -14344,7 +14344,7 @@ pub fn _mm512_cvttph_epu16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvttph2uw_512( @@ -14364,7 +14364,7 @@ pub fn _mm512_mask_cvttph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvttph_epu16(_mm512_setzero_si512(), k, a) } @@ -14379,7 +14379,7 @@ pub fn _mm512_maskz_cvttph_epu16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14396,7 +14396,7 @@ pub fn _mm512_cvtt_roundph_epu16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu16( src: __m512i, k: __mmask32, @@ -14419,7 +14419,7 @@ pub fn _mm512_mask_cvtt_roundph_epu16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu16::(_mm512_setzero_si512(), k, a) @@ -14432,7 +14432,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi32(a: __m128h) -> __m128i { _mm_mask_cvtph_epi32(_mm_undefined_si128(), 0xff, a) } @@ -14444,7 +14444,7 @@ pub fn _mm_cvtph_epi32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2dq_128(a, src.as_i32x4(), k)) } } @@ -14456,7 +14456,7 @@ pub fn _mm_mask_cvtph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi32(_mm_setzero_si128(), k, a) } @@ -14468,7 +14468,7 @@ pub fn _mm_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi32(a: __m128h) -> __m256i { _mm256_mask_cvtph_epi32(_mm256_undefined_si256(), 0xff, a) } @@ -14480,7 +14480,7 @@ pub fn _mm256_cvtph_epi32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2dq_256(a, src.as_i32x8(), k)) } } @@ -14492,7 +14492,7 @@ pub fn _mm256_mask_cvtph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epi32(_mm256_setzero_si256(), k, a) } @@ -14504,7 +14504,7 @@ pub fn _mm256_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi32(a: __m256h) -> __m512i { _mm512_mask_cvtph_epi32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14516,7 +14516,7 @@ pub fn _mm512_cvtph_epi32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvtph2dq_512( @@ -14535,7 +14535,7 @@ pub fn _mm512_mask_cvtph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvtph_epi32(_mm512_setzero_si512(), k, a) } @@ -14556,7 +14556,7 @@ pub fn _mm512_maskz_cvtph_epi32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi32(a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi32::(_mm512_undefined_epi32(), 0xffff, a) @@ -14578,7 +14578,7 @@ pub fn _mm512_cvt_roundph_epi32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi32( src: __m512i, k: __mmask16, @@ -14606,7 +14606,7 @@ pub fn _mm512_mask_cvt_roundph_epi32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi32(k: __mmask16, a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi32::(_mm512_setzero_si512(), k, a) @@ -14619,7 +14619,7 @@ pub fn _mm512_maskz_cvt_roundph_epi32(k: __mmask16, a: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_i32(a: __m128h) -> i32 { unsafe { vcvtsh2si32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -14640,7 +14640,7 @@ pub fn _mm_cvtsh_i32(a: __m128h) -> i32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_i32(a: __m128h) -> i32 { unsafe { static_assert_rounding!(ROUNDING); @@ -14655,7 +14655,7 @@ pub fn _mm_cvt_roundsh_i32(a: __m128h) -> i32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu32(a: __m128h) -> __m128i { _mm_mask_cvtph_epu32(_mm_undefined_si128(), 0xff, a) } @@ -14667,7 +14667,7 @@ pub fn _mm_cvtph_epu32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2udq_128(a, src.as_u32x4(), k)) } } @@ -14679,7 +14679,7 @@ pub fn _mm_mask_cvtph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu32(_mm_setzero_si128(), k, a) } @@ -14691,7 +14691,7 @@ pub fn _mm_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu32(a: __m128h) -> __m256i { _mm256_mask_cvtph_epu32(_mm256_undefined_si256(), 0xff, a) } @@ -14703,7 +14703,7 @@ pub fn _mm256_cvtph_epu32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2udq_256(a, src.as_u32x8(), k)) } } @@ -14715,7 +14715,7 @@ pub fn _mm256_mask_cvtph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epu32(_mm256_setzero_si256(), k, a) } @@ -14727,7 +14727,7 @@ pub fn _mm256_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu32(a: __m256h) -> __m512i { _mm512_mask_cvtph_epu32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14739,7 +14739,7 @@ pub fn _mm512_cvtph_epu32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvtph2udq_512( @@ -14758,7 +14758,7 @@ pub fn _mm512_mask_cvtph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvtph_epu32(_mm512_setzero_si512(), k, a) } @@ -14779,7 +14779,7 @@ pub fn _mm512_maskz_cvtph_epu32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu32(a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu32::(_mm512_undefined_epi32(), 0xffff, a) @@ -14801,7 +14801,7 @@ pub fn _mm512_cvt_roundph_epu32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu32( src: __m512i, k: __mmask16, @@ -14829,7 +14829,7 @@ pub fn _mm512_mask_cvt_roundph_epu32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu32(k: __mmask16, a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu32::(_mm512_setzero_si512(), k, a) @@ -14842,7 +14842,7 @@ pub fn _mm512_maskz_cvt_roundph_epu32(k: __mmask16, a: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_u32(a: __m128h) -> u32 { unsafe { vcvtsh2usi32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -14857,7 +14857,7 @@ pub fn _mm_cvtsh_u32(a: __m128h) -> u32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_u32(a: __m128h) -> u32 { unsafe { static_assert_rounding!(SAE); @@ -14872,7 +14872,7 @@ pub fn _mm_cvt_roundsh_u32(a: __m128h) -> u32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi32(a: __m128h) -> __m128i { _mm_mask_cvttph_epi32(_mm_undefined_si128(), 0xff, a) } @@ -14884,7 +14884,7 @@ pub fn _mm_cvttph_epi32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2dq_128(a, src.as_i32x4(), k)) } } @@ -14896,7 +14896,7 @@ pub fn _mm_mask_cvttph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi32(_mm_setzero_si128(), k, a) } @@ -14908,7 +14908,7 @@ pub fn _mm_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi32(a: __m128h) -> __m256i { _mm256_mask_cvttph_epi32(_mm256_undefined_si256(), 0xff, a) } @@ -14920,7 +14920,7 @@ pub fn _mm256_cvttph_epi32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2dq_256(a, src.as_i32x8(), k)) } } @@ -14932,7 +14932,7 @@ pub fn _mm256_mask_cvttph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epi32(_mm256_setzero_si256(), k, a) } @@ -14944,7 +14944,7 @@ pub fn _mm256_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi32(a: __m256h) -> __m512i { _mm512_mask_cvttph_epi32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14956,7 +14956,7 @@ pub fn _mm512_cvttph_epi32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvttph2dq_512( @@ -14975,7 +14975,7 @@ pub fn _mm512_mask_cvttph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvttph_epi32(_mm512_setzero_si512(), k, a) } @@ -14990,7 +14990,7 @@ pub fn _mm512_maskz_cvttph_epi32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi32(a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi32::(_mm512_undefined_epi32(), 0xffff, a) @@ -15006,7 +15006,7 @@ pub fn _mm512_cvtt_roundph_epi32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi32( src: __m512i, k: __mmask16, @@ -15028,7 +15028,7 @@ pub fn _mm512_mask_cvtt_roundph_epi32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi32(k: __mmask16, a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi32::(_mm512_setzero_si512(), k, a) @@ -15041,7 +15041,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi32(k: __mmask16, a: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_i32(a: __m128h) -> i32 { unsafe { vcvttsh2si32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -15056,7 +15056,7 @@ pub fn _mm_cvttsh_i32(a: __m128h) -> i32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_i32(a: __m128h) -> i32 { unsafe { static_assert_sae!(SAE); @@ -15071,7 +15071,7 @@ pub fn _mm_cvtt_roundsh_i32(a: __m128h) -> i32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu32(a: __m128h) -> __m128i { _mm_mask_cvttph_epu32(_mm_undefined_si128(), 0xff, a) } @@ -15083,7 +15083,7 @@ pub fn _mm_cvttph_epu32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2udq_128(a, src.as_u32x4(), k)) } } @@ -15095,7 +15095,7 @@ pub fn _mm_mask_cvttph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu32(_mm_setzero_si128(), k, a) } @@ -15107,7 +15107,7 @@ pub fn _mm_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu32(a: __m128h) -> __m256i { _mm256_mask_cvttph_epu32(_mm256_undefined_si256(), 0xff, a) } @@ -15119,7 +15119,7 @@ pub fn _mm256_cvttph_epu32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2udq_256(a, src.as_u32x8(), k)) } } @@ -15131,7 +15131,7 @@ pub fn _mm256_mask_cvttph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epu32(_mm256_setzero_si256(), k, a) } @@ -15143,7 +15143,7 @@ pub fn _mm256_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu32(a: __m256h) -> __m512i { _mm512_mask_cvttph_epu32(_mm512_undefined_epi32(), 0xffff, a) } @@ -15155,7 +15155,7 @@ pub fn _mm512_cvttph_epu32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvttph2udq_512( @@ -15174,7 +15174,7 @@ pub fn _mm512_mask_cvttph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvttph_epu32(_mm512_setzero_si512(), k, a) } @@ -15189,7 +15189,7 @@ pub fn _mm512_maskz_cvttph_epu32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu32(a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu32::(_mm512_undefined_epi32(), 0xffff, a) @@ -15205,7 +15205,7 @@ pub fn _mm512_cvtt_roundph_epu32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu32( src: __m512i, k: __mmask16, @@ -15227,7 +15227,7 @@ pub fn _mm512_mask_cvtt_roundph_epu32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu32(k: __mmask16, a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu32::(_mm512_setzero_si512(), k, a) @@ -15240,7 +15240,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu32(k: __mmask16, a: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_u32(a: __m128h) -> u32 { unsafe { vcvttsh2usi32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -15255,7 +15255,7 @@ pub fn _mm_cvttsh_u32(a: __m128h) -> u32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_u32(a: __m128h) -> u32 { unsafe { static_assert_sae!(SAE); @@ -15270,7 +15270,7 @@ pub fn _mm_cvtt_roundsh_u32(a: __m128h) -> u32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi64(a: __m128h) -> __m128i { _mm_mask_cvtph_epi64(_mm_undefined_si128(), 0xff, a) } @@ -15282,7 +15282,7 @@ pub fn _mm_cvtph_epi64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2qq_128(a, src.as_i64x2(), k)) } } @@ -15294,7 +15294,7 @@ pub fn _mm_mask_cvtph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi64(_mm_setzero_si128(), k, a) } @@ -15306,7 +15306,7 @@ pub fn _mm_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi64(a: __m128h) -> __m256i { _mm256_mask_cvtph_epi64(_mm256_undefined_si256(), 0xff, a) } @@ -15318,7 +15318,7 @@ pub fn _mm256_cvtph_epi64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2qq_256(a, src.as_i64x4(), k)) } } @@ -15330,7 +15330,7 @@ pub fn _mm256_mask_cvtph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epi64(_mm256_setzero_si256(), k, a) } @@ -15342,7 +15342,7 @@ pub fn _mm256_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi64(a: __m128h) -> __m512i { _mm512_mask_cvtph_epi64(_mm512_undefined_epi32(), 0xff, a) } @@ -15354,7 +15354,7 @@ pub fn _mm512_cvtph_epi64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvtph2qq_512( @@ -15373,7 +15373,7 @@ pub fn _mm512_mask_cvtph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvtph_epi64(_mm512_setzero_si512(), k, a) } @@ -15394,7 +15394,7 @@ pub fn _mm512_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi64(a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi64::(_mm512_undefined_epi32(), 0xff, a) @@ -15416,7 +15416,7 @@ pub fn _mm512_cvt_roundph_epi64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi64( src: __m512i, k: __mmask8, @@ -15444,7 +15444,7 @@ pub fn _mm512_mask_cvt_roundph_epi64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi64(k: __mmask8, a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi64::(_mm512_setzero_si512(), k, a) @@ -15457,7 +15457,7 @@ pub fn _mm512_maskz_cvt_roundph_epi64(k: __mmask8, a: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu64(a: __m128h) -> __m128i { _mm_mask_cvtph_epu64(_mm_undefined_si128(), 0xff, a) } @@ -15469,7 +15469,7 @@ pub fn _mm_cvtph_epu64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2uqq_128(a, src.as_u64x2(), k)) } } @@ -15481,7 +15481,7 @@ pub fn _mm_mask_cvtph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu64(_mm_setzero_si128(), k, a) } @@ -15493,7 +15493,7 @@ pub fn _mm_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu64(a: __m128h) -> __m256i { _mm256_mask_cvtph_epu64(_mm256_undefined_si256(), 0xff, a) } @@ -15505,7 +15505,7 @@ pub fn _mm256_cvtph_epu64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2uqq_256(a, src.as_u64x4(), k)) } } @@ -15517,7 +15517,7 @@ pub fn _mm256_mask_cvtph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epu64(_mm256_setzero_si256(), k, a) } @@ -15529,7 +15529,7 @@ pub fn _mm256_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu64(a: __m128h) -> __m512i { _mm512_mask_cvtph_epu64(_mm512_undefined_epi32(), 0xff, a) } @@ -15541,7 +15541,7 @@ pub fn _mm512_cvtph_epu64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvtph2uqq_512( @@ -15560,7 +15560,7 @@ pub fn _mm512_mask_cvtph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvtph_epu64(_mm512_setzero_si512(), k, a) } @@ -15581,7 +15581,7 @@ pub fn _mm512_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu64(a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu64::(_mm512_undefined_epi32(), 0xff, a) @@ -15603,7 +15603,7 @@ pub fn _mm512_cvt_roundph_epu64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu64( src: __m512i, k: __mmask8, @@ -15631,7 +15631,7 @@ pub fn _mm512_mask_cvt_roundph_epu64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu64(k: __mmask8, a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu64::(_mm512_setzero_si512(), k, a) @@ -15644,7 +15644,7 @@ pub fn _mm512_maskz_cvt_roundph_epu64(k: __mmask8, a: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi64(a: __m128h) -> __m128i { _mm_mask_cvttph_epi64(_mm_undefined_si128(), 0xff, a) } @@ -15656,7 +15656,7 @@ pub fn _mm_cvttph_epi64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2qq_128(a, src.as_i64x2(), k)) } } @@ -15668,7 +15668,7 @@ pub fn _mm_mask_cvttph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi64(_mm_setzero_si128(), k, a) } @@ -15680,7 +15680,7 @@ pub fn _mm_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi64(a: __m128h) -> __m256i { _mm256_mask_cvttph_epi64(_mm256_undefined_si256(), 0xff, a) } @@ -15692,7 +15692,7 @@ pub fn _mm256_cvttph_epi64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2qq_256(a, src.as_i64x4(), k)) } } @@ -15704,7 +15704,7 @@ pub fn _mm256_mask_cvttph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epi64(_mm256_setzero_si256(), k, a) } @@ -15716,7 +15716,7 @@ pub fn _mm256_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi64(a: __m128h) -> __m512i { _mm512_mask_cvttph_epi64(_mm512_undefined_epi32(), 0xff, a) } @@ -15728,7 +15728,7 @@ pub fn _mm512_cvttph_epi64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvttph2qq_512( @@ -15747,7 +15747,7 @@ pub fn _mm512_mask_cvttph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvttph_epi64(_mm512_setzero_si512(), k, a) } @@ -15762,7 +15762,7 @@ pub fn _mm512_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi64(a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi64::(_mm512_undefined_epi32(), 0xff, a) @@ -15778,7 +15778,7 @@ pub fn _mm512_cvtt_roundph_epi64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi64( src: __m512i, k: __mmask8, @@ -15800,7 +15800,7 @@ pub fn _mm512_mask_cvtt_roundph_epi64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi64(k: __mmask8, a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi64::(_mm512_setzero_si512(), k, a) @@ -15813,7 +15813,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi64(k: __mmask8, a: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu64(a: __m128h) -> __m128i { _mm_mask_cvttph_epu64(_mm_undefined_si128(), 0xff, a) } @@ -15825,7 +15825,7 @@ pub fn _mm_cvttph_epu64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2uqq_128(a, src.as_u64x2(), k)) } } @@ -15837,7 +15837,7 @@ pub fn _mm_mask_cvttph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu64(_mm_setzero_si128(), k, a) } @@ -15849,7 +15849,7 @@ pub fn _mm_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu64(a: __m128h) -> __m256i { _mm256_mask_cvttph_epu64(_mm256_undefined_si256(), 0xff, a) } @@ -15861,7 +15861,7 @@ pub fn _mm256_cvttph_epu64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2uqq_256(a, src.as_u64x4(), k)) } } @@ -15873,7 +15873,7 @@ pub fn _mm256_mask_cvttph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epu64(_mm256_setzero_si256(), k, a) } @@ -15885,7 +15885,7 @@ pub fn _mm256_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu64(a: __m128h) -> __m512i { _mm512_mask_cvttph_epu64(_mm512_undefined_epi32(), 0xff, a) } @@ -15897,7 +15897,7 @@ pub fn _mm512_cvttph_epu64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvttph2uqq_512( @@ -15916,7 +15916,7 @@ pub fn _mm512_mask_cvttph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvttph_epu64(_mm512_setzero_si512(), k, a) } @@ -15931,7 +15931,7 @@ pub fn _mm512_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu64(a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu64::(_mm512_undefined_epi32(), 0xff, a) @@ -15947,7 +15947,7 @@ pub fn _mm512_cvtt_roundph_epu64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu64( src: __m512i, k: __mmask8, @@ -15969,7 +15969,7 @@ pub fn _mm512_mask_cvtt_roundph_epu64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu64(k: __mmask8, a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu64::(_mm512_setzero_si512(), k, a) @@ -15982,7 +15982,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu64(k: __mmask8, a: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtxph_ps(a: __m128h) -> __m128 { _mm_mask_cvtxph_ps(_mm_setzero_ps(), 0xff, a) } @@ -15995,7 +15995,7 @@ pub fn _mm_cvtxph_ps(a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtxph_ps(src: __m128, k: __mmask8, a: __m128h) -> __m128 { unsafe { vcvtph2psx_128(a, src, k) } } @@ -16008,7 +16008,7 @@ pub fn _mm_mask_cvtxph_ps(src: __m128, k: __mmask8, a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m128 { _mm_mask_cvtxph_ps(_mm_setzero_ps(), k, a) } @@ -16020,7 +16020,7 @@ pub fn _mm_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtxph_ps(a: __m128h) -> __m256 { _mm256_mask_cvtxph_ps(_mm256_setzero_ps(), 0xff, a) } @@ -16033,7 +16033,7 @@ pub fn _mm256_cvtxph_ps(a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtxph_ps(src: __m256, k: __mmask8, a: __m128h) -> __m256 { unsafe { vcvtph2psx_256(a, src, k) } } @@ -16046,7 +16046,7 @@ pub fn _mm256_mask_cvtxph_ps(src: __m256, k: __mmask8, a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m256 { _mm256_mask_cvtxph_ps(_mm256_setzero_ps(), k, a) } @@ -16058,7 +16058,7 @@ pub fn _mm256_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtxph_ps(a: __m256h) -> __m512 { _mm512_mask_cvtxph_ps(_mm512_setzero_ps(), 0xffff, a) } @@ -16071,7 +16071,7 @@ pub fn _mm512_cvtxph_ps(a: __m256h) -> __m512 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtxph_ps(src: __m512, k: __mmask16, a: __m256h) -> __m512 { unsafe { vcvtph2psx_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16084,7 +16084,7 @@ pub fn _mm512_mask_cvtxph_ps(src: __m512, k: __mmask16, a: __m256h) -> __m512 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtxph_ps(k: __mmask16, a: __m256h) -> __m512 { _mm512_mask_cvtxph_ps(_mm512_setzero_ps(), k, a) } @@ -16099,7 +16099,7 @@ pub fn _mm512_maskz_cvtxph_ps(k: __mmask16, a: __m256h) -> __m512 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtx_roundph_ps(a: __m256h) -> __m512 { static_assert_sae!(SAE); _mm512_mask_cvtx_roundph_ps::(_mm512_setzero_ps(), 0xffff, a) @@ -16116,7 +16116,7 @@ pub fn _mm512_cvtx_roundph_ps(a: __m256h) -> __m512 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtx_roundph_ps( src: __m512, k: __mmask16, @@ -16139,7 +16139,7 @@ pub fn _mm512_mask_cvtx_roundph_ps( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtx_roundph_ps(k: __mmask16, a: __m256h) -> __m512 { static_assert_sae!(SAE); _mm512_mask_cvtx_roundph_ps::(_mm512_setzero_ps(), k, a) @@ -16153,7 +16153,7 @@ pub fn _mm512_maskz_cvtx_roundph_ps(k: __mmask16, a: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_ss(a: __m128, b: __m128h) -> __m128 { _mm_mask_cvtsh_ss(a, 0xff, a, b) } @@ -16167,7 +16167,7 @@ pub fn _mm_cvtsh_ss(a: __m128, b: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsh_ss(src: __m128, k: __mmask8, a: __m128, b: __m128h) -> __m128 { unsafe { vcvtsh2ss(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16181,7 +16181,7 @@ pub fn _mm_mask_cvtsh_ss(src: __m128, k: __mmask8, a: __m128, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { _mm_mask_cvtsh_ss(_mm_set_ss(0.0), k, a, b) } @@ -16197,7 +16197,7 @@ pub fn _mm_maskz_cvtsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_ss(a: __m128, b: __m128h) -> __m128 { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_ss::(_mm_undefined_ps(), 0xff, a, b) @@ -16215,7 +16215,7 @@ pub fn _mm_cvt_roundsh_ss(a: __m128, b: __m128h) -> __m128 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsh_ss( src: __m128, k: __mmask8, @@ -16240,7 +16240,7 @@ pub fn _mm_mask_cvt_roundsh_ss( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_ss::(_mm_set_ss(0.0), k, a, b) @@ -16253,7 +16253,7 @@ pub fn _mm_maskz_cvt_roundsh_ss(k: __mmask8, a: __m128, b: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_pd(a: __m128h) -> __m128d { _mm_mask_cvtph_pd(_mm_setzero_pd(), 0xff, a) } @@ -16266,7 +16266,7 @@ pub fn _mm_cvtph_pd(a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_pd(src: __m128d, k: __mmask8, a: __m128h) -> __m128d { unsafe { vcvtph2pd_128(a, src, k) } } @@ -16279,7 +16279,7 @@ pub fn _mm_mask_cvtph_pd(src: __m128d, k: __mmask8, a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m128d { _mm_mask_cvtph_pd(_mm_setzero_pd(), k, a) } @@ -16291,7 +16291,7 @@ pub fn _mm_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_pd(a: __m128h) -> __m256d { _mm256_mask_cvtph_pd(_mm256_setzero_pd(), 0xff, a) } @@ -16304,7 +16304,7 @@ pub fn _mm256_cvtph_pd(a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_pd(src: __m256d, k: __mmask8, a: __m128h) -> __m256d { unsafe { vcvtph2pd_256(a, src, k) } } @@ -16317,7 +16317,7 @@ pub fn _mm256_mask_cvtph_pd(src: __m256d, k: __mmask8, a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m256d { _mm256_mask_cvtph_pd(_mm256_setzero_pd(), k, a) } @@ -16329,7 +16329,7 @@ pub fn _mm256_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_pd(a: __m128h) -> __m512d { _mm512_mask_cvtph_pd(_mm512_setzero_pd(), 0xff, a) } @@ -16342,7 +16342,7 @@ pub fn _mm512_cvtph_pd(a: __m128h) -> __m512d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_pd(src: __m512d, k: __mmask8, a: __m128h) -> __m512d { unsafe { vcvtph2pd_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16355,7 +16355,7 @@ pub fn _mm512_mask_cvtph_pd(src: __m512d, k: __mmask8, a: __m128h) -> __m512d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m512d { _mm512_mask_cvtph_pd(_mm512_setzero_pd(), k, a) } @@ -16370,7 +16370,7 @@ pub fn _mm512_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m512d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_pd(a: __m128h) -> __m512d { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_pd::(_mm512_setzero_pd(), 0xff, a) @@ -16387,7 +16387,7 @@ pub fn _mm512_cvt_roundph_pd(a: __m128h) -> __m512d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_pd( src: __m512d, k: __mmask8, @@ -16410,7 +16410,7 @@ pub fn _mm512_mask_cvt_roundph_pd( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_pd(k: __mmask8, a: __m128h) -> __m512d { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_pd::(_mm512_setzero_pd(), k, a) @@ -16424,7 +16424,7 @@ pub fn _mm512_maskz_cvt_roundph_pd(k: __mmask8, a: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_sd(a: __m128d, b: __m128h) -> __m128d { _mm_mask_cvtsh_sd(a, 0xff, a, b) } @@ -16438,7 +16438,7 @@ pub fn _mm_cvtsh_sd(a: __m128d, b: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsh_sd(src: __m128d, k: __mmask8, a: __m128d, b: __m128h) -> __m128d { unsafe { vcvtsh2sd(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16451,7 +16451,7 @@ pub fn _mm_mask_cvtsh_sd(src: __m128d, k: __mmask8, a: __m128d, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { _mm_mask_cvtsh_sd(_mm_set_sd(0.0), k, a, b) } @@ -16467,7 +16467,7 @@ pub fn _mm_maskz_cvtsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_sd(a: __m128d, b: __m128h) -> __m128d { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_sd::(a, 0xff, a, b) @@ -16485,7 +16485,7 @@ pub fn _mm_cvt_roundsh_sd(a: __m128d, b: __m128h) -> __m128d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsh_sd( src: __m128d, k: __mmask8, @@ -16509,7 +16509,7 @@ pub fn _mm_mask_cvt_roundsh_sd( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_sd::(_mm_set_sd(0.0), k, a, b) @@ -16553,7 +16553,7 @@ pub const fn _mm512_cvtsh_h(a: __m512h) -> f16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si16) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtsi128_si16(a: __m128i) -> i16 { unsafe { simd_extract!(a.as_i16x8(), 0) } @@ -16564,7 +16564,7 @@ pub const fn _mm_cvtsi128_si16(a: __m128i) -> i16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi16_si128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtsi16_si128(a: i16) -> __m128i { unsafe { transmute(simd_insert!(i16x8::ZERO, 0, a)) } diff --git a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs index 91b6be2b09d7..b8a3b9473af9 100644 --- a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs +++ b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs @@ -87,7 +87,7 @@ pub unsafe fn _mm256_cvtneebf16_ps(a: *const __m256bh) -> __m256 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneeph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm_cvtneeph_ps(a: *const __m128h) -> __m128 { transmute(cvtneeph2ps_128(a)) } @@ -99,7 +99,7 @@ pub unsafe fn _mm_cvtneeph_ps(a: *const __m128h) -> __m128 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneeph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm256_cvtneeph_ps(a: *const __m256h) -> __m256 { transmute(cvtneeph2ps_256(a)) } @@ -135,7 +135,7 @@ pub unsafe fn _mm256_cvtneobf16_ps(a: *const __m256bh) -> __m256 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneoph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm_cvtneoph_ps(a: *const __m128h) -> __m128 { transmute(cvtneoph2ps_128(a)) } @@ -147,7 +147,7 @@ pub unsafe fn _mm_cvtneoph_ps(a: *const __m128h) -> __m128 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneoph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm256_cvtneoph_ps(a: *const __m256h) -> __m256 { transmute(cvtneoph2ps_256(a)) } diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index c40fbd3ca317..9396507f0804 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -401,7 +401,7 @@ types! { } types! { - #![stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] + #![stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] /// 128-bit wide set of 8 `f16` types, x86-specific /// @@ -768,7 +768,7 @@ mod avxneconvert; pub use self::avxneconvert::*; mod avx512fp16; -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub use self::avx512fp16::*; mod kl; diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index b83274e60e72..2c4439a3f3a5 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -968,7 +968,7 @@ pub const fn _mm_set_ps1(a: f32) -> __m128 { /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_ps) #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(test, assert_instr(unpcklps))] +// This intrinsic has no corresponding instruction. #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_set_ps(a: f32, b: f32, c: f32, d: f32) -> __m128 { diff --git a/library/stdarch/crates/core_arch/src/x86/ssse3.rs b/library/stdarch/crates/core_arch/src/x86/ssse3.rs index 4426a3274c38..1d7a97944a37 100644 --- a/library/stdarch/crates/core_arch/src/x86/ssse3.rs +++ b/library/stdarch/crates/core_arch/src/x86/ssse3.rs @@ -188,7 +188,13 @@ pub const fn _mm_hadd_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hadds_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phaddsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_add(even, odd).as_m128i() + } } /// Horizontally adds the adjacent pairs of values contained in 2 packed @@ -240,7 +246,13 @@ pub const fn _mm_hsub_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hsubs_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phsubsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_sub(even, odd).as_m128i() + } } /// Horizontally subtract the adjacent pairs of values contained in 2 @@ -337,12 +349,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.ssse3.pshuf.b.128"] fn pshufb128(a: u8x16, b: u8x16) -> u8x16; - #[link_name = "llvm.x86.ssse3.phadd.sw.128"] - fn phaddsw128(a: i16x8, b: i16x8) -> i16x8; - - #[link_name = "llvm.x86.ssse3.phsub.sw.128"] - fn phsubsw128(a: i16x8, b: i16x8) -> i16x8; - #[link_name = "llvm.x86.ssse3.pmadd.ub.sw.128"] fn pmaddubsw128(a: u8x16, b: i8x16) -> i16x8; diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs index 87e3651ba744..2a511328bb38 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs @@ -10,7 +10,7 @@ use stdarch_test::assert_instr; #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvti64_sh(a: __m128h, b: i64) -> __m128h { unsafe { vcvtsi642sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -32,7 +32,7 @@ pub fn _mm_cvti64_sh(a: __m128h, b: i64) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundi64_sh(a: __m128h, b: i64) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -48,7 +48,7 @@ pub fn _mm_cvt_roundi64_sh(a: __m128h, b: i64) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtu64_sh(a: __m128h, b: u64) -> __m128h { unsafe { vcvtusi642sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -70,7 +70,7 @@ pub fn _mm_cvtu64_sh(a: __m128h, b: u64) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundu64_sh(a: __m128h, b: u64) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -85,7 +85,7 @@ pub fn _mm_cvt_roundu64_sh(a: __m128h, b: u64) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_i64(a: __m128h) -> i64 { unsafe { vcvtsh2si64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -106,7 +106,7 @@ pub fn _mm_cvtsh_i64(a: __m128h) -> i64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_i64(a: __m128h) -> i64 { unsafe { static_assert_rounding!(ROUNDING); @@ -121,7 +121,7 @@ pub fn _mm_cvt_roundsh_i64(a: __m128h) -> i64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_u64(a: __m128h) -> u64 { unsafe { vcvtsh2usi64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -142,7 +142,7 @@ pub fn _mm_cvtsh_u64(a: __m128h) -> u64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_u64(a: __m128h) -> u64 { unsafe { static_assert_rounding!(ROUNDING); @@ -157,7 +157,7 @@ pub fn _mm_cvt_roundsh_u64(a: __m128h) -> u64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_i64(a: __m128h) -> i64 { unsafe { vcvttsh2si64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -172,7 +172,7 @@ pub fn _mm_cvttsh_i64(a: __m128h) -> i64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_i64(a: __m128h) -> i64 { unsafe { static_assert_sae!(SAE); @@ -187,7 +187,7 @@ pub fn _mm_cvtt_roundsh_i64(a: __m128h) -> i64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_u64(a: __m128h) -> u64 { unsafe { vcvttsh2usi64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -202,7 +202,7 @@ pub fn _mm_cvttsh_u64(a: __m128h) -> u64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_u64(a: __m128h) -> u64 { unsafe { static_assert_sae!(SAE); diff --git a/library/stdarch/crates/core_arch/src/x86_64/mod.rs b/library/stdarch/crates/core_arch/src/x86_64/mod.rs index c6dc7a85e785..9caab44e46cd 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/mod.rs @@ -75,7 +75,7 @@ mod bt; pub use self::bt::*; mod avx512fp16; -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub use self::avx512fp16::*; mod amx; diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index a9bc377924dd..d74d85ba9eb1 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -13,9 +13,9 @@ auto_llvm_sign_conversion: false neon-stable: &neon-stable FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] -# #[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +# #[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] neon-stable-fp16: &neon-stable-fp16 - FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']] + FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']] # #[cfg(not(target_arch = "arm64ec"))] target-not-arm64ec: &target-not-arm64ec @@ -70,6 +70,10 @@ aarch64-stable-jscvt: &aarch64-stable-jscvt neon-unstable-feat-lrcpc3: &neon-unstable-feat-lrcpc3 FnCall: [unstable, ['feature = "stdarch_neon_feat_lrcpc3"', 'issue = "none"']] +# #[cfg(target_has_atomic = "64")] +cfg-target-has-atomic-64: &cfg-target-has-atomic-64 + FnCall: [cfg, ['target_has_atomic = "64"']] + # #[unstable(feature = "stdarch_neon_fp8", issue = "none")] neon-unstable-fp8: &neon-unstable-fp8 FnCall: [unstable, ['feature = "stdarch_neon_fp8"', 'issue = "none"']] @@ -4418,6 +4422,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [ldap1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*const i64', int64x1_t, 'static_assert!', 'LANE == 0'] - ['*const i64', int64x2_t,'static_assert_uimm_bits!', 'LANE, 1'] @@ -4448,6 +4453,7 @@ intrinsics: - FnCall: [target_feature, ['enable = "neon,rcpc3"']] - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [ldap1, 'LANE = 0']]}]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*const u64', uint64x1_t,'static_assert!', 'LANE == 0',''] #- ['*const f64', float64x1_t,'static_assert!', 'LANE == 0',''] # Fails due to bad IR gen from rust @@ -4474,6 +4480,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [stl1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*mut i64', int64x1_t,'static_assert!', 'LANE == 0'] - ['*mut i64', int64x2_t,'static_assert_uimm_bits!', 'LANE, 1'] @@ -4502,6 +4509,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [stl1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*mut u64', uint64x1_t, 'static_assert!', 'LANE == 0',''] - ['*mut f64', float64x1_t,'static_assert!', 'LANE == 0',''] @@ -8958,7 +8966,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -8983,7 +8991,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9008,7 +9016,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9037,7 +9045,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 52748a4cc056..2dd2fb0d3f1d 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -10,9 +10,9 @@ auto_big_endian: true neon-stable: &neon-stable FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] -# #[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +# #[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] neon-stable-fp16: &neon-stable-fp16 - FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']] + FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']] # #[cfg_attr(target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800"))] neon-cfg-arm-unstable: &neon-cfg-arm-unstable @@ -55,9 +55,9 @@ neon-target-aarch64-arm64ec: &neon-target-aarch64-arm64ec neon-not-arm-stable: &neon-not-arm-stable FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']]}]] -# #[cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION"))] +# #[cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "1.94.0"))] neon-not-arm-stable-fp16: &neon-not-arm-stable-fp16 - FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']]}]] + FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']]}]] # #[cfg_attr(all(test, not(target_env = "msvc"))] msvc-disabled: &msvc-disabled @@ -2603,8 +2603,8 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2617,13 +2617,12 @@ intrinsics: - ["*const f32", float32x2x4_t] - ["*const f32", float32x4x4_t] compose: - - LLVMLink: - name: "vld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2631,8 +2630,8 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2663,13 +2662,12 @@ intrinsics: - ["*const i64", int64x2x3_t] - ["*const i64", int64x2x4_t] compose: - - LLVMLink: - name: "ld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}i{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}i{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2677,10 +2675,11 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: @@ -2722,12 +2721,11 @@ intrinsics: - ["*const p16", poly16x8x4_t, int16x8x4_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2737,9 +2735,10 @@ intrinsics: - *neon-aes - *neon-v8 - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [nop]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: @@ -2750,12 +2749,11 @@ intrinsics: - ["*const p64", poly64x2x4_t, int64x2x4_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2764,8 +2762,8 @@ intrinsics: attr: - *neon-aes - *neon-v8 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2774,12 +2772,11 @@ intrinsics: - ["*const p64", poly64x1x2_t, int64x1x2_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2788,7 +2785,7 @@ intrinsics: attr: - *neon-v7 - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *arm-fp16 - *neon-unstable-f16 - *target-not-arm64ec @@ -2802,13 +2799,12 @@ intrinsics: - ["*const f16", float16x4x4_t] - ["*const f16", float16x8x4_t] compose: - - LLVMLink: - name: "vld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{type[2]}_{neon_type[1]}" doc: "Load one single-element structure to one lane of one register" diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index 9bf7d0981deb..e14e2782485b 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -139,6 +139,7 @@ fn parse_args() -> Vec<(PathBuf, Option)> { .into_iter() .filter_map(Result::ok) .filter(|f| f.file_type().is_file()) + .filter(|f| f.file_name().to_string_lossy().ends_with(".yml")) .map(|f| (f.into_path(), out_dir.clone())) .collect() } diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index ccc0b55d4dc5..aa3876b14a22 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -873d4682c7d285540b8f28bfe637006cef8918a6 +db3e99bbab28c6ca778b13222becdea54533d908 diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index d554807bbde7..f3dbd3d0556a 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -24,7 +24,7 @@ #![feature(staged_api)] #![feature(process_exitcode_internals)] #![feature(panic_can_unwind)] -#![feature(test)] +#![cfg_attr(test, feature(test))] #![feature(thread_spawn_hook)] #![allow(internal_features)] #![warn(rustdoc::unescaped_backticks)] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index cff2aa7b08b9..f2e0cfd32ed6 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -4,12 +4,12 @@ #![feature(cfg_select)] #![feature(link_cfg)] #![feature(staged_api)] -#![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr( all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)), feature(link_llvm_intrinsics, simd_wasm64) )] #![allow(internal_features)] +#![allow(unused_features)] #![deny(unsafe_op_in_unsafe_fn)] // Force libc to be included even if unused. This is required by many platforms. diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs index 2bff306af293..cb6e90ba180b 100644 --- a/library/unwind/src/wasm.rs +++ b/library/unwind/src/wasm.rs @@ -73,7 +73,7 @@ pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwi // corresponds with llvm::WebAssembly::Tag::CPP_EXCEPTION // in llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h const CPP_EXCEPTION_TAG: i32 = 0; - wasm_throw(CPP_EXCEPTION_TAG, exception.cast()) + unsafe { wasm_throw(CPP_EXCEPTION_TAG, exception.cast()) } } _ => { let _ = exception; diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index e46fed7c426a..ef2de9b37ed0 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -175,8 +175,8 @@ When you use bootstrap, you'll call it through the entry point script (`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. `bootstrap` has a difficult problem: it is written in Rust, but yet it is run before the Rust compiler is built! To work around this, there are two components -of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py` -is what gets run by entry point script. It takes care of downloading the prebuilt +of bootstrap: the main one written in Rust, and `bootstrap.py`. `bootstrap.py` +is what gets run by the entry point script. It takes care of downloading the prebuilt stage 0 compiler, std and Cargo binaries, which are then used to build the bootstrap binary. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2e16f2cf27e7..db7c7b69cba9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -479,7 +479,7 @@ def default_build_triple(verbose): @contextlib.contextmanager def output(filepath): tmp = filepath + ".tmp" - with open(tmp, "w") as f: + with open(tmp, "w", encoding="utf-8") as f: yield f try: if os.path.exists(filepath): @@ -778,7 +778,7 @@ class RustBuild(object): # Use `/etc/os-release` instead of `/etc/NIXOS`. # The latter one does not exist on NixOS when using tmpfs as root. try: - with open("/etc/os-release", "r") as f: + with open("/etc/os-release", "r", encoding="utf-8") as f: is_nixos = any( ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f @@ -863,7 +863,8 @@ class RustBuild(object): if ".so" not in fname: # Finally, set the correct .interp for binaries with open( - "{}/nix-support/dynamic-linker".format(nix_deps_dir) + "{}/nix-support/dynamic-linker".format(nix_deps_dir), + encoding="utf-8", ) as dynamic_linker: patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()] @@ -888,7 +889,7 @@ class RustBuild(object): """Check if the given program stamp is out of date""" if not os.path.exists(stamp_path) or self.clean: return True - with open(stamp_path, "r") as stamp: + with open(stamp_path, "r", encoding="utf-8") as stamp: return key != stamp.read() def bin_root(self): @@ -1276,7 +1277,7 @@ def parse_args(args): def parse_stage0_file(path): result = {} - with open(path, "r") as file: + with open(path, "r", encoding="utf-8") as file: for line in file: line = line.strip() if line and not line.startswith("#"): @@ -1316,7 +1317,7 @@ def bootstrap(args): # Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, # but not if `bootstrap.toml` hasn't been created. if not using_default_path or os.path.exists(toml_path): - with open(toml_path) as config: + with open(toml_path, encoding="utf-8") as config: config_toml = config.read() else: config_toml = "" @@ -1346,7 +1347,7 @@ def bootstrap(args): # HACK: This works because `self.get_toml()` returns the first match it finds for a # specific key, so appending our defaults at the end allows the user to override them - with open(include_path) as included_toml: + with open(include_path, encoding="utf-8") as included_toml: config_toml += os.linesep + included_toml.read() # Configure initial bootstrap @@ -1384,7 +1385,9 @@ def main(): if len(sys.argv) == 1 or sys.argv[1] in ["-h", "--help"]: try: with open( - os.path.join(os.path.dirname(__file__), "../etc/xhelp"), "r" + os.path.join(os.path.dirname(__file__), "../etc/xhelp"), + "r", + encoding="utf-8", ) as f: # The file from bootstrap func already has newline. print(f.read(), end="") diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 8bbd03ac3afa..55426bfffc73 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -706,7 +706,7 @@ macro_rules! tool_check_step { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&[ $path, $( $alt_path ),* ]) + run.path($path) $( .path( $alt_path ) )* } fn is_default_step(_builder: &Builder<'_>) -> bool { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 405ab9f6eaa2..adba8f19894a 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1378,6 +1378,9 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS } } + // The host this new compiler will *run* on. + cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); + if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a918ae929d2e..325f54d78a50 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -953,6 +953,13 @@ impl Step for Rustc { cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); + // Point std library crate links to local docs for offline usage. + for krate in STD_PUBLIC_CRATES { + cargo.rustdocflag("--extern-html-root-url"); + cargo.rustdocflag(&format!("{krate}=../")); + } + cargo.rustdocflag("--extern-html-root-takes-precedence"); + let mut to_open = None; let out_dir = builder.stage_out(build_compiler, Mode::Rustc).join(target).join("doc"); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index dbd4f1c81405..c04a8cd6b7ab 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1008,33 +1008,9 @@ impl Step for OmpOffload { t!(fs::create_dir_all(&out_dir)); builder.config.update_submodule("src/llvm-project"); - let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/runtimes/")); - // If we use an external clang as opposed to building our own llvm_clang, than that clang will - // come with it's own set of default include directories, which are based on a potentially older - // LLVM. This can cause issues, so we overwrite it to include headers based on our - // `src/llvm-project` submodule instead. - // FIXME(offload): With LLVM-22 we hopefully won't need an external clang anymore. - let mut cflags = CcFlags::default(); - if !builder.config.llvm_clang { - let base = builder.llvm_out(target).join("include"); - let inc_dir = base.display(); - cflags.push_all(format!(" -I {inc_dir}")); - } - - configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), cflags, &[]); - - // Re-use the same flags as llvm to control the level of debug information - // generated for offload. - let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { - (false, _) => "Debug", - (true, false) => "Release", - (true, true) => "RelWithDebInfo", - }; - trace!(?profile); - - // OpenMP/Offload builds currently (LLVM-21) still depend on Clang, although there are - // intentions to loosen this requirement for LLVM-22. If we were to + // OpenMP/Offload builds currently (LLVM-22) still depend on Clang, although there are + // intentions to loosen this requirement over time. FIXME(offload): re-evaluate on LLVM 23 let clang_dir = if !builder.config.llvm_clang { // We must have an external clang to use. assert!(&builder.build.config.llvm_clang_dir.is_some()); @@ -1044,23 +1020,66 @@ impl Step for OmpOffload { None }; - // FIXME(offload): Once we move from OMP to Offload (Ol) APIs, we should drop the openmp - // runtime to simplify our build. We should also re-evaluate the LLVM_Root and try to get - // rid of the Clang_DIR, once we upgrade to LLVM-22. - cfg.out_dir(&out_dir) - .profile(profile) - .env("LLVM_CONFIG_REAL", &host_llvm_config) - .define("LLVM_ENABLE_ASSERTIONS", "ON") - .define("LLVM_ENABLE_RUNTIMES", "openmp;offload") - .define("LLVM_INCLUDE_TESTS", "OFF") - .define("OFFLOAD_INCLUDE_TESTS", "OFF") - .define("OPENMP_STANDALONE_BUILD", "ON") - .define("LLVM_ROOT", builder.llvm_out(target).join("build")) - .define("LLVM_DIR", llvm_cmake_dir); - if let Some(p) = clang_dir { - cfg.define("Clang_DIR", p); + // In the context of OpenMP offload, some libraries must be compiled for the gpu target, + // some for the host, and others for both. We do not perform a full cross-compilation, since + // we don't want to run rustc on a GPU. + let omp_targets = vec![target.triple.as_ref(), "amdgcn-amd-amdhsa", "nvptx64-nvidia-cuda"]; + for omp_target in omp_targets { + let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/runtimes/")); + + // If we use an external clang as opposed to building our own llvm_clang, than that clang will + // come with it's own set of default include directories, which are based on a potentially older + // LLVM. This can cause issues, so we overwrite it to include headers based on our + // `src/llvm-project` submodule instead. + // FIXME(offload): With LLVM-22 we hopefully won't need an external clang anymore. + let mut cflags = CcFlags::default(); + if !builder.config.llvm_clang { + let base = builder.llvm_out(target).join("include"); + let inc_dir = base.display(); + cflags.push_all(format!(" -I {inc_dir}")); + } + + configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), cflags, &[]); + + // Re-use the same flags as llvm to control the level of debug information + // generated for offload. + let profile = + match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { + (false, _) => "Debug", + (true, false) => "Release", + (true, true) => "RelWithDebInfo", + }; + trace!(?profile); + + // FIXME(offload): Once we move from OMP to Offload (Ol) APIs, we should drop the openmp + // runtime to simplify our build. So far, these are still under development. + cfg.out_dir(&out_dir) + .profile(profile) + .env("LLVM_CONFIG_REAL", &host_llvm_config) + .define("LLVM_ENABLE_ASSERTIONS", "ON") + .define("LLVM_INCLUDE_TESTS", "OFF") + .define("OFFLOAD_INCLUDE_TESTS", "OFF") + .define("LLVM_ROOT", builder.llvm_out(target).join("build")) + .define("LLVM_DIR", llvm_cmake_dir.clone()) + .define("LLVM_DEFAULT_TARGET_TRIPLE", omp_target); + if let Some(p) = clang_dir.clone() { + cfg.define("Clang_DIR", p); + } + + // We don't perform a full cross-compilation of rustc, therefore our target.triple + // will still be a CPU target. + if *omp_target == *target.triple { + // The offload library provides functionality which only makes sense on the host. + cfg.define("LLVM_ENABLE_RUNTIMES", "openmp;offload"); + } else { + // OpenMP provides some device libraries, so we also compile it for all gpu targets. + cfg.define("LLVM_USE_LINKER", "lld"); + cfg.define("LLVM_ENABLE_RUNTIMES", "openmp"); + cfg.define("CMAKE_C_COMPILER_TARGET", omp_target); + cfg.define("CMAKE_CXX_COMPILER_TARGET", omp_target); + } + cfg.build(); } - cfg.build(); t!(stamp.write()); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 844251f2c64d..fda9f3bbba3a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -513,6 +513,7 @@ impl Step for RustAnalyzer { // This builds a proc macro against the bootstrap libproc_macro, which is not ABI // compatible with the ABI proc-macro-srv expects to load. cargo.arg("--exclude=proc-macro-srv"); + cargo.arg("--exclude=proc-macro-srv-cli"); } let mut skip_tests = vec![]; @@ -1299,19 +1300,19 @@ impl Step for Tidy { /// for the `dev` or `nightly` channels. fn run(self, builder: &Builder<'_>) { let mut cmd = builder.tool_cmd(Tool::Tidy); - cmd.arg(&builder.src); - cmd.arg(&builder.initial_cargo); - cmd.arg(&builder.out); + cmd.arg(format!("--root-path={}", &builder.src.display())); + cmd.arg(format!("--cargo-path={}", &builder.initial_cargo.display())); + cmd.arg(format!("--output-dir={}", &builder.out.display())); // Tidy is heavily IO constrained. Still respect `-j`, but use a higher limit if `jobs` hasn't been configured. let jobs = builder.config.jobs.unwrap_or_else(|| { 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32 }); - cmd.arg(jobs.to_string()); + cmd.arg(format!("--concurrency={jobs}")); // pass the path to the yarn command used for installing js deps. if let Some(yarn) = &builder.config.yarn { - cmd.arg(yarn); + cmd.arg(format!("--npm-path={}", yarn.display())); } else { - cmd.arg("yarn"); + cmd.arg("--npm-path=yarn"); } if builder.is_verbose() { cmd.arg("--verbose"); @@ -2183,6 +2184,9 @@ Please disable assertions with `rust.debug-assertions = false`. for flag in targetflags { cmd.arg("--target-rustcflags").arg(flag); } + if target.is_synthetic() { + cmd.arg("--target-rustcflags").arg("-Zunstable-options"); + } cmd.arg("--python").arg( builder.config.python.as_ref().expect("python is required for running rustdoc tests"), @@ -3155,7 +3159,7 @@ impl Step for CrateRustdoc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["src/librustdoc", "src/tools/rustdoc"]) + run.path("src/librustdoc").path("src/tools/rustdoc") } fn is_default_step(_builder: &Builder<'_>) -> bool { @@ -3816,7 +3820,7 @@ impl Step for CodegenCranelift { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["compiler/rustc_codegen_cranelift"]) + run.path("compiler/rustc_codegen_cranelift") } fn is_default_step(_builder: &Builder<'_>) -> bool { @@ -3937,7 +3941,7 @@ impl Step for CodegenGCC { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["compiler/rustc_codegen_gcc"]) + run.path("compiler/rustc_codegen_gcc") } fn is_default_step(_builder: &Builder<'_>) -> bool { diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 7150b2b0d59f..e3fa826c45af 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -10,7 +10,7 @@ use crate::core::build_steps::tool::SourceType; use crate::core::config::SplitDebuginfo; use crate::core::config::flags::Color; use crate::utils::build_stamp; -use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags}; +use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_flags}; use crate::{ BootstrapCommand, CLang, Compiler, Config, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode, RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t, @@ -310,7 +310,15 @@ impl Cargo { } } - for arg in linker_args(builder, compiler.host, LldThreads::Yes) { + // We need to set host linker flags for compiling build scripts and proc-macros. + // This is done the same way as the target linker flags below, so cargo won't see + // any fingerprint difference between host==target versus cross-compiled targets + // when it comes to those host build artifacts. + if let Some(host_linker) = builder.linker(compiler.host) { + let host = crate::envify(&compiler.host.triple); + self.command.env(format!("CARGO_TARGET_{host}_LINKER"), host_linker); + } + for arg in linker_flags(builder, compiler.host, LldThreads::Yes) { self.hostflags.arg(&arg); } @@ -319,11 +327,11 @@ impl Cargo { self.command.env(format!("CARGO_TARGET_{target}_LINKER"), target_linker); } // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not - // `linker_args` here. + // `linker_args` here. Cargo will pass that to both rustc and rustdoc invocations. for flag in linker_flags(builder, target, LldThreads::Yes) { self.rustflags.arg(&flag); } - for arg in linker_args(builder, target, LldThreads::Yes) { + for arg in linker_flags(builder, target, LldThreads::Yes) { self.rustdocflags.arg(&arg); } @@ -331,10 +339,6 @@ impl Cargo { self.rustflags.arg("-Clink-arg=-gz"); } - // Ignore linker warnings for now. These are complicated to fix and don't affect the build. - // FIXME: we should really investigate these... - self.rustflags.arg("-Alinker-messages"); - // Throughout the build Cargo can execute a number of build scripts // compiling C/C++ code and we need to pass compilers, archivers, flags, etc // obtained previously to those build scripts. @@ -1256,13 +1260,7 @@ impl Builder<'_> { // when compiling the standard library, since this might be linked into the final outputs // produced by rustc. Since this mitigation is only available on Windows, only enable it // for the standard library in case the compiler is run on a non-Windows platform. - // This is not needed for stage 0 artifacts because these will only be used for building - // the stage 1 compiler. - if cfg!(windows) - && mode == Mode::Std - && self.config.control_flow_guard - && compiler.stage >= 1 - { + if cfg!(windows) && mode == Mode::Std && self.config.control_flow_guard { rustflags.arg("-Ccontrol-flow-guard"); } @@ -1270,9 +1268,7 @@ impl Builder<'_> { // standard library, since this might be linked into the final outputs produced by rustc. // Since this mitigation is only available on Windows, only enable it for the standard // library in case the compiler is run on a non-Windows platform. - // This is not needed for stage 0 artifacts because these will only be used for building - // the stage 1 compiler. - if cfg!(windows) && mode == Mode::Std && self.config.ehcont_guard && compiler.stage >= 1 { + if cfg!(windows) && mode == Mode::Std && self.config.ehcont_guard { rustflags.arg("-Zehcont-guard"); } @@ -1289,52 +1285,13 @@ impl Builder<'_> { rustdocflags.arg("--crate-version").arg(&rust_version); // Environment variables *required* throughout the build - // - // FIXME: should update code to not require this env var - // The host this new compiler will *run* on. - cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); // The host this new compiler is being *built* on. cargo.env("CFG_COMPILER_BUILD_TRIPLE", compiler.host.triple); // Set this for all builds to make sure doc builds also get it. cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel); - // This one's a bit tricky. As of the time of this writing the compiler - // links to the `winapi` crate on crates.io. This crate provides raw - // bindings to Windows system functions, sort of like libc does for - // Unix. This crate also, however, provides "import libraries" for the - // MinGW targets. There's an import library per dll in the windows - // distribution which is what's linked to. These custom import libraries - // are used because the winapi crate can reference Windows functions not - // present in the MinGW import libraries. - // - // For example MinGW may ship libdbghelp.a, but it may not have - // references to all the functions in the dbghelp dll. Instead the - // custom import library for dbghelp in the winapi crates has all this - // information. - // - // Unfortunately for us though the import libraries are linked by - // default via `-ldylib=winapi_foo`. That is, they're linked with the - // `dylib` type with a `winapi_` prefix (so the winapi ones don't - // conflict with the system MinGW ones). This consequently means that - // the binaries we ship of things like rustc_codegen_llvm (aka the rustc_codegen_llvm - // DLL) when linked against *again*, for example with procedural macros - // or plugins, will trigger the propagation logic of `-ldylib`, passing - // `-lwinapi_foo` to the linker again. This isn't actually available in - // our distribution, however, so the link fails. - // - // To solve this problem we tell winapi to not use its bundled import - // libraries. This means that it will link to the system MinGW import - // libraries by default, and the `-ldylib=foo` directives will still get - // passed to the final linker, but they'll look like `-lfoo` which can - // be resolved because MinGW has the import library. The downside is we - // don't get newer functions from Windows, but we don't use any of them - // anyway. - if !mode.is_tool() { - cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); - } - // verbose cargo output is very noisy, so only enable it with -vv for _ in 0..self.verbosity.saturating_sub(1) { cargo.arg("--verbose"); diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap index 8a7815487913..3adf952d66e0 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap @@ -44,7 +44,6 @@ expression: bench - Set({bench::compiler/rustc_errors}) - Set({bench::compiler/rustc_expand}) - Set({bench::compiler/rustc_feature}) - - Set({bench::compiler/rustc_fluent_macro}) - Set({bench::compiler/rustc_fs_util}) - Set({bench::compiler/rustc_graphviz}) - Set({bench::compiler/rustc_hashes}) @@ -98,4 +97,5 @@ expression: bench - Set({bench::compiler/rustc_windows_rc}) [Bench] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({bench::src/librustdoc, bench::src/tools/rustdoc}) + - Set({bench::src/librustdoc}) + - Set({bench::src/tools/rustdoc}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap index 721ecaf4c487..1d6e63696b06 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap @@ -26,7 +26,6 @@ expression: build compiler - Set({build::compiler/rustc_errors}) - Set({build::compiler/rustc_expand}) - Set({build::compiler/rustc_feature}) - - Set({build::compiler/rustc_fluent_macro}) - Set({build::compiler/rustc_fs_util}) - Set({build::compiler/rustc_graphviz}) - Set({build::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap index 0fe26fac57fc..6fc2e190290e 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap @@ -28,7 +28,6 @@ expression: check - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) @@ -82,7 +81,8 @@ expression: check - Set({check::compiler/rustc_windows_rc}) [Check] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({check::src/librustdoc, check::src/tools/rustdoc}) + - Set({check::src/librustdoc}) + - Set({check::src/tools/rustdoc}) [Check] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({check::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap index 71d9c0fafb80..c0456f7f84d3 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap @@ -28,7 +28,6 @@ expression: check compiler - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap index dae515c67ec6..10f36ffa6748 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap @@ -28,7 +28,6 @@ expression: check compiletest --include-default-paths - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) @@ -82,7 +81,8 @@ expression: check compiletest --include-default-paths - Set({check::compiler/rustc_windows_rc}) [Check] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({check::src/librustdoc, check::src/tools/rustdoc}) + - Set({check::src/librustdoc}) + - Set({check::src/tools/rustdoc}) [Check] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({check::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap index fe8334641285..492a10d3862a 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap @@ -43,7 +43,6 @@ expression: clippy - Set({clippy::compiler/rustc_errors}) - Set({clippy::compiler/rustc_expand}) - Set({clippy::compiler/rustc_feature}) - - Set({clippy::compiler/rustc_fluent_macro}) - Set({clippy::compiler/rustc_fs_util}) - Set({clippy::compiler/rustc_graphviz}) - Set({clippy::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap index 222c0ffb4050..41889cd12480 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap @@ -28,7 +28,6 @@ expression: fix - Set({fix::compiler/rustc_errors}) - Set({fix::compiler/rustc_expand}) - Set({fix::compiler/rustc_feature}) - - Set({fix::compiler/rustc_fluent_macro}) - Set({fix::compiler/rustc_fs_util}) - Set({fix::compiler/rustc_graphviz}) - Set({fix::compiler/rustc_hashes}) @@ -82,7 +81,8 @@ expression: fix - Set({fix::compiler/rustc_windows_rc}) [Fix] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({fix::src/librustdoc, fix::src/tools/rustdoc}) + - Set({fix::src/librustdoc}) + - Set({fix::src/tools/rustdoc}) [Fix] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({fix::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 4ab84c3cabc1..51e2c270e3ba 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -94,7 +94,6 @@ expression: test - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) @@ -148,7 +147,8 @@ expression: test - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap index c8eee72aec42..8dcdce0c17ab 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap @@ -4,7 +4,8 @@ expression: test librustdoc rustdoc --- [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::RustdocBook targets: [x86_64-unknown-linux-gnu] - Set({test::src/doc/rustdoc}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index 2a4805e4fd68..bc828c162bb0 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -93,7 +93,6 @@ expression: test --skip=coverage - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) @@ -147,7 +146,8 @@ expression: test --skip=coverage - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap index 1468964c7818..ceb910e4cb36 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap @@ -1,6 +1,5 @@ --- source: src/bootstrap/src/core/builder/cli_paths/tests.rs -assertion_line: 68 expression: test --skip=tests --- [Test] test::Tidy @@ -58,7 +57,6 @@ expression: test --skip=tests - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) @@ -112,7 +110,8 @@ expression: test --skip=tests - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap index 7ff6a201e77a..f0e8f1aee2c7 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap @@ -1,6 +1,5 @@ --- source: src/bootstrap/src/core/builder/cli_paths/tests.rs -assertion_line: 68 expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest --- [Test] test::Tidy @@ -38,7 +37,6 @@ expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=lib - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) @@ -92,7 +90,8 @@ expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=lib - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index a995f5c8a219..ae91b2040629 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -558,38 +558,19 @@ impl<'a> ShouldRun<'a> { /// single, non-aliased path /// /// Must be an on-disk path; use `alias` for names that do not correspond to on-disk paths. - pub fn path(self, path: &str) -> Self { - self.paths(&[path]) - } - - /// Multiple aliases for the same job. - /// - /// This differs from [`path`] in that multiple calls to path will end up calling `make_run` - /// multiple times, whereas a single call to `paths` will only ever generate a single call to - /// `make_run`. - /// - /// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible. - /// - /// [`path`]: ShouldRun::path - pub fn paths(mut self, paths: &[&str]) -> Self { + pub fn path(mut self, path: &str) -> Self { let submodules_paths = self.builder.submodule_paths(); - self.paths.insert(PathSet::Set( - paths - .iter() - .map(|p| { - // assert only if `p` isn't submodule - if !submodules_paths.iter().any(|sm_p| p.contains(sm_p)) { - assert!( - self.builder.src.join(p).exists(), - "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {p}" - ); - } + // assert only if `p` isn't submodule + if !submodules_paths.iter().any(|sm_p| path.contains(sm_p)) { + assert!( + self.builder.src.join(path).exists(), + "`should_run.path` should correspond to a real on-disk path - use `alias` if there is no relevant path: {path}" + ); + } - TaskPath { path: p.into(), kind: Some(self.kind) } - }) - .collect(), - )); + let task = TaskPath { path: path.into(), kind: Some(self.kind) }; + self.paths.insert(PathSet::Set(BTreeSet::from_iter([task]))); self } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index af26c2f87d02..61db494c8c18 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1815,7 +1815,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("compiler") - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] @@ -1841,7 +1841,7 @@ mod snapshot { ctx.config("check") .path("compiler") .stage(1) - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] @@ -1855,7 +1855,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (75 crates) + [check] rustc 1 -> rustc 2 (74 crates) "); } @@ -1871,7 +1871,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [check] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (75 crates) + [check] rustc 1 -> rustc 2 (74 crates) [check] rustc 1 -> rustc 2 [check] rustc 1 -> Rustdoc 2 [check] rustc 1 -> rustc_codegen_cranelift 2 @@ -1967,7 +1967,7 @@ mod snapshot { ctx.config("check") .paths(&["library", "compiler"]) .args(&args) - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 07405a0309fe..61eef3c01592 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1859,11 +1859,17 @@ impl Config { .get(&target) .and_then(|t| t.llvm_libunwind) .or(self.llvm_libunwind_default) - .unwrap_or(if target.contains("fuchsia") || target.contains("hexagon") { - LlvmLibunwind::InTree - } else { - LlvmLibunwind::No - }) + .unwrap_or( + if target.contains("fuchsia") + || (target.contains("hexagon") && !target.contains("qurt")) + { + // Fuchsia and Hexagon Linux use in-tree llvm-libunwind. + // Hexagon QuRT uses libc_eh from the Hexagon SDK instead. + LlvmLibunwind::InTree + } else { + LlvmLibunwind::No + }, + ) } pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 8b6405afa892..e5327ab79ee2 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -48,6 +48,7 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ "thumbv6-none-eabi", "aarch64v8r-unknown-none", "aarch64v8r-unknown-none-softfloat", + "s390x-unknown-none-softfloat", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index f1bf6e399fb1..fee9b12aca06 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -3,8 +3,6 @@ /// See pub static CRATES: &[&str] = &[ // tidy-alphabetical-start - "annotate-snippets", - "anstyle", "askama_derive", "askama_parser", "basic-toml", @@ -59,7 +57,6 @@ pub static CRATES: &[&str] = &[ "unic-langid-impl", "unic-langid-macros", "unicode-ident", - "unicode-width", "version_check", "wasm-bindgen-macro-support", "wasm-bindgen-shared", diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index 07157e364158..98dd952033e5 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -111,6 +111,29 @@ pub struct JsonStepSystemStats { pub cpu_utilization_percent: f64, } +#[derive(Eq, Hash, PartialEq, Debug)] +pub enum DebuggerKind { + Gdb, + Lldb, + Cdb, +} + +impl DebuggerKind { + pub fn debuginfo_kind(name: &str) -> Option { + let name = name.to_ascii_lowercase(); + + if name.contains("debuginfo-gdb") { + Some(DebuggerKind::Gdb) + } else if name.contains("debuginfo-lldb") { + Some(DebuggerKind::Lldb) + } else if name.contains("debuginfo-cdb") { + Some(DebuggerKind::Cdb) + } else { + None + } + } +} + fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result { use serde::Deserialize as _; Option::::deserialize(d).map(|f| f.unwrap_or(f64::NAN)) diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index 9e1ded4d3f7c..fe1c92f049e0 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -66,9 +66,9 @@ checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "askama" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7125972258312e79827b60c9eb93938334100245081cf701a2dee981b17427" +checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" dependencies = [ "askama_macros", "itoa", @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba5e7259a1580c61571e3116ebaaa01e3c001b2132b17c4cc5c70780ca3e994" +checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" dependencies = [ "askama_parser", "basic-toml", @@ -96,18 +96,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236ce20b77cb13506eaf5024899f4af6e12e8825f390bd943c4c37fd8f322e46" +checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c63392767bb2df6aa65a6e1e3b80fd89bb7af6d58359b924c0695620f1512e" +checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" dependencies = [ "rustc-hash", "serde", diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index b394c6fbefff..0b1f2fe79bf7 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] anyhow = "1" -askama = "0.15.2" +askama = "0.15.4" clap = { version = "4.5", features = ["derive"] } csv = "1" diff = "0.1" diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 39b115154f9f..b8048f341ea2 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use std::time::Duration; use build_helper::metrics::{ - BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, + BuildStep, DebuggerKind, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; @@ -139,11 +139,39 @@ fn record_test_suites(metrics: &JsonRoot) { let table = render_table(aggregated); println!("\n# Test results\n"); println!("{table}"); + report_debuginfo_statistics(&suites); } else { eprintln!("No test suites found in metrics"); } } +fn report_debuginfo_statistics(suites: &[&TestSuite]) { + let mut debugger_test_record: HashMap = HashMap::new(); + for suite in suites { + if let TestSuiteMetadata::Compiletest { .. } = suite.metadata { + for test in &suite.tests { + if let Some(kind) = DebuggerKind::debuginfo_kind(&test.name) { + let record = + debugger_test_record.entry(kind).or_insert(TestSuiteRecord::default()); + match test.outcome { + TestOutcome::Passed => record.passed += 1, + TestOutcome::Ignored { .. } => record.ignored += 1, + TestOutcome::Failed => record.failed += 1, + } + } + } + } + } + + println!("## DebugInfo Test Statistics"); + for (kind, record) in debugger_test_record { + println!( + "- {:?}: Passed ✅={}, Failed ❌={}, Ignored 🚫={}", + kind, record.passed, record.failed, record.ignored + ); + } +} + fn render_table(suites: BTreeMap) -> String { use std::fmt::Write; @@ -194,8 +222,8 @@ pub fn output_test_diffs( report_test_diffs(aggregated_test_diffs, job_metrics, job_info_resolver); } -/// Prints the ten largest differences in bootstrap durations. -pub fn output_largest_duration_changes( +/// Prints the ten largest differences in job durations. +pub fn output_largest_job_duration_changes( job_metrics: &HashMap, job_info_resolver: &mut JobInfoResolver, ) { @@ -237,11 +265,11 @@ pub fn output_largest_duration_changes( println!("# Job duration changes"); for (index, entry) in changes.into_iter().take(10).enumerate() { println!( - "{}. {}: {:.1}s -> {:.1}s ({:+.1}%)", + "{}. {}: {} -> {} ({:+.1}%)", index + 1, format_job_link(job_info_resolver, job_metrics, entry.job), - entry.before.as_secs_f64(), - entry.after.as_secs_f64(), + format_duration(entry.before), + format_duration(entry.after), entry.change ); } @@ -256,6 +284,27 @@ mostly for t-infra members, for simpler debugging of potential CI slow-downs."# }); } +fn format_duration(duration: Duration) -> String { + let total_secs = duration.as_secs(); + let hours = total_secs / 3600; + let minutes = (total_secs % 3600) / 60; + let seconds = total_secs % 60; + + let mut res = String::new(); + + if hours > 0 { + res.push_str(&format!("{hours}h ")); + } + if minutes > 0 { + res.push_str(&format!("{minutes}m ")); + } + if hours == 0 && seconds > 0 { + res.push_str(&format!("{seconds}s")); + } + + res.trim().to_string() +} + #[derive(Default)] struct TestSuiteRecord { passed: u64, diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 01c0650b3c98..9b9cbe3862e3 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -17,7 +17,7 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; -use crate::analysis::{output_largest_duration_changes, output_test_diffs}; +use crate::analysis::{output_largest_job_duration_changes, output_test_diffs}; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::github::JobInfoResolver; @@ -205,7 +205,7 @@ And then open `test-dashboard/index.html` in your browser to see an overview of ); }); - output_largest_duration_changes(&metrics, &mut job_info_resolver); + output_largest_job_duration_changes(&metrics, &mut job_info_resolver); Ok(()) } diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 6787f00d9af8..247871de6025 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -6,7 +6,7 @@ const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/tes fn auto_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/auto"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","SELECT_XCODE":"/Applications/Xcode_15.4.app","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] + jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-15","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_26.2.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=auto "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index e26104905491..3bad1fe1b427 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -13,7 +13,7 @@ runners: <<: *base-job - &job-macos-m1 - os: macos-14 + os: macos-15 <<: *base-job - &job-windows @@ -33,7 +33,7 @@ envs: # Ensure that host tooling is tested on our minimum supported macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.2.app + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -112,8 +112,7 @@ auto: --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_15.4.app - USE_XCODE_CLANG: 1 + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 4ee02e9bf005..59cea7aa79a5 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -48,7 +48,7 @@ Refer to the [dev guide](https://rustc-dev-guide.rust-lang.org/tests/docker.html ## Docker Toolbox on Windows For Windows before Windows 10, the docker images can be run on Windows via -[Docker Toolbox]. There are several preparation needs to be made before running +[Docker Toolbox]. There are several preparations that need to be made before running a Docker image. 1. Stop the virtual machine from the terminal with `docker-machine stop` @@ -92,7 +92,7 @@ To run the image, A number of these images take quite a long time to compile as they're building whole gcc toolchains to do cross builds with. Much of this is relatively self-explanatory but some images use [crosstool-ng] which isn't quite as self -explanatory. Below is a description of where these `*.defconfig` files come form, +explanatory. Below is a description of where these `*.defconfig` files come from, how to generate them, and how the existing ones were generated. [crosstool-ng]: https://github.com/crosstool-ng/crosstool-ng @@ -231,25 +231,9 @@ For targets: `armv7-unknown-linux-gnueabihf` libraries like jemalloc. See the mk/cfg/arm(v7)-unknown-linux-gnueabi{,hf}.mk file in Rust's source code. -### `aarch64-linux-gnu.defconfig` - -For targets: `aarch64-unknown-linux-gnu` - -- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} -- Path and misc options > Use a mirror = ENABLE -- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc -- Target options > Target Architecture = arm -- Target options > Bitness = 64-bit -- Operating System > Target OS = linux -- Operating System > Linux kernel version = 4.1.49 -- Binary utilities > Version of binutils = 2.29.1 -- C-library > glibc version = 2.17 -- aarch64 support was introduced in this version -- C compiler > gcc version = 13.2.0 -- C compiler > C++ = ENABLE -- to cross compile LLVM - ### `i586-linux-gnu.defconfig` -For targets: `i586-unknown-linux-gnu` +For targets: `i586-unknown-linux-gnu`, `i586-unknown-linux-musl` and `i686-unknown-linux-musl` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} - Target options > Target Architecture = x86 @@ -266,7 +250,7 @@ For targets: `i586-unknown-linux-gnu` (\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets, but that makes our `compiler_builtins` incompatible with binutils < 2.32. -### `loongarch64-linux-gnu.defconfig` +### `loongarch64-unknown-linux-gnu.defconfig` For targets: `loongarch64-unknown-linux-gnu` @@ -282,7 +266,7 @@ For targets: `loongarch64-unknown-linux-gnu` - C compiler > gcc version = 14.2.0 - C compiler > C++ = ENABLE -- to cross compile LLVM -### `loongarch64-linux-musl.defconfig` +### `loongarch64-unknown-linux-musl.defconfig` For targets: `loongarch64-unknown-linux-musl` @@ -412,6 +396,56 @@ For targets: `powerpc64-unknown-linux-gnu` (+) These CPU options match the configuration of the toolchains in RHEL6. +### `powerpc64-unknown-linux-musl.defconfig` + +For targets: `powerpc64-unknown-linux-musl` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Use a mirror = ENABLE +- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc +- Target options > Target Architecture = powerpc +- Target options > Bitness = 64-bit +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 4.19 +- Binary utilities > Version of binutils = 2.42 +- C-library > musl version = 1.2.5 +- C compiler > gcc version = 14.2.0 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +### `powerpc64le-unknown-linux-gnu.defconfig` + +For targets: `powerpc64le-unknown-linux-gnu` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Use a mirror = ENABLE +- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc +- Target options > Target Architecture = powerpc +- Target options > Bitness = 64-bit +- Target options > Endianness = Little endian +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 3.10 +- Binary utilities > Version of binutils = 2.42 +- C-library > glibc version = 2.17 +- C compiler > gcc version = 14.2.0 +- C compiler > C++ = ENABLE -- to cross compile LLVM + +### `powerpc64le-unknown-linux-musl.defconfig` + +For targets: `powerpc64le-unknown-linux-musl` + +- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} +- Path and misc options > Use a mirror = ENABLE +- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc +- Target options > Target Architecture = powerpc +- Target options > Bitness = 64-bit +- Target options > Endianness = Little endian +- Operating System > Target OS = linux +- Operating System > Linux kernel version = 4.19 +- Binary utilities > Version of binutils = 2.42 +- C-library > musl version = 1.2.5 +- C compiler > gcc version = 14.2.0 +- C compiler > C++ = ENABLE -- to cross compile LLVM + ### `riscv64-unknown-linux-gnu.defconfig` For targets: `riscv64-unknown-linux-gnu` @@ -423,7 +457,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.36.1 +- Binary utilities > Version of binutils = 2.40 - 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-arm-linux-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile index 6e055cd2bd5a..dc35285dbab9 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile @@ -3,9 +3,6 @@ FROM ghcr.io/rust-lang/ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/crosstool-ng.sh /scripts/ -RUN sh /scripts/crosstool-ng.sh - WORKDIR /build COPY scripts/musl-toolchain.sh /build/ @@ -14,14 +11,8 @@ RUN CFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=non CXXFLAGS="-Wa,--compress-debug-sections=none -Wl,--compress-debug-sections=none" \ bash musl-toolchain.sh aarch64 && rm -rf build -COPY scripts/rustbuild-setup.sh /scripts/ -RUN sh /scripts/rustbuild-setup.sh WORKDIR /tmp -COPY scripts/crosstool-ng-build.sh /scripts/ -COPY host-x86_64/dist-arm-linux-musl/arm-linux-musl.defconfig /tmp/crosstool.defconfig -RUN /scripts/crosstool-ng-build.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-arm-linux-musl/arm-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-arm-linux-musl/arm-linux-musl.defconfig deleted file mode 100644 index 014930052b4a..000000000000 --- a/src/ci/docker/host-x86_64/dist-arm-linux-musl/arm-linux-musl.defconfig +++ /dev/null @@ -1,14 +0,0 @@ -CT_CONFIG_VERSION="4" -CT_PREFIX_DIR="/x-tools/${CT_TARGET}" -CT_USE_MIRROR=y -CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc" -CT_ARCH_ARM=y -CT_ARCH_ARCH="armv6" -CT_ARCH_FLOAT_SW=y -CT_KERNEL_LINUX=y -CT_LINUX_V_3_2=y -CT_BINUTILS_V_2_32=y -CT_GLIBC_V_2_17=y -CT_GCC_V_8=y -CT_CC_LANG_CXX=y -CT_MUSL_V_1_2_5=y 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 4b86ed32fd55..96acc5e97e94 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -50,6 +50,9 @@ ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ --enable-sanitizers \ - --disable-docs + --disable-docs \ + --set rust.jemalloc \ + --set rust.lto=thin \ + --set rust.codegen-units=1 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig index aa33f72268e4..bb1d2d1f8038 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig @@ -12,5 +12,7 @@ CT_TARGET_LDFLAGS="-mcmodel=medium" CT_KERNEL_LINUX=y CT_LINUX_V_5_19=y CT_GLIBC_V_2_36=y +CT_BINUTILS_V_2_42=y +CT_GCC_V_14=y CT_CC_GCC_ENABLE_DEFAULT_PIE=y CT_CC_LANG_CXX=y diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile index 763b29ae1c5e..44efc1089017 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -33,6 +33,9 @@ ENV RUST_CONFIGURE_ARGS \ --enable-profiler \ --enable-sanitizers \ --disable-docs \ + --set rust.jemalloc \ + --set rust.lto=thin \ + --set rust.codegen-units=1 \ --set target.loongarch64-unknown-linux-musl.crt-static=false \ --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig index 3ccbc583c1bd..aa1696e131d4 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig @@ -12,6 +12,9 @@ CT_TARGET_LDFLAGS="-mcmodel=medium" CT_KERNEL_LINUX=y CT_LINUX_V_5_19=y CT_LIBC_MUSL=y +CT_MUSL_V_1_2_5=y +CT_BINUTILS_V_2_42=y +CT_GCC_V_14=y CT_CC_GCC_ENABLE_DEFAULT_PIE=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig index 08132d3ab8ba..4b7a9c3d671f 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig +++ b/src/ci/docker/host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig @@ -11,5 +11,7 @@ CT_KERNEL_LINUX=y CT_LINUX_V_4_19=y CT_LIBC_MUSL=y CT_MUSL_V_1_2_5=y +CT_BINUTILS_V_2_42=y +CT_GCC_V_14=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig index 5fbf138cdd74..e1fd950922f7 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-gnu/powerpc64le-unknown-linux-gnu.defconfig @@ -11,5 +11,7 @@ CT_ARCH_ARCH="powerpc64le" CT_KERNEL_LINUX=y CT_LINUX_V_3_10=y CT_GLIBC_V_2_17=y +CT_BINUTILS_V_2_42=y +CT_GCC_V_14=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/powerpc64le-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/powerpc64le-unknown-linux-musl.defconfig index db2b5533947c..a89e08572aca 100644 --- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/powerpc64le-unknown-linux-musl.defconfig +++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux-musl/powerpc64le-unknown-linux-musl.defconfig @@ -12,5 +12,7 @@ CT_KERNEL_LINUX=y CT_LINUX_V_4_19=y CT_LIBC_MUSL=y CT_MUSL_V_1_2_5=y +CT_BINUTILS_V_2_42=y +CT_GCC_V_14=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y 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 323cd409a978..dacf3c0db202 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -85,9 +85,9 @@ RUN /tmp/build-fuchsia-toolchain.sh COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/tmp/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/tmp/wasi-sdk-30.0-x86_64-linux COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh i686 diff --git a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index 68162d136c3f..885bf0b30b18 100644 --- a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile @@ -21,9 +21,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ mingw-w64 \ && rm -rf /var/lib/apt/lists/* -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-30.0-x86_64-linux ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3" diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 9b1bf6c0df99..6512240730cc 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -41,9 +41,9 @@ WORKDIR / COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-30.0-x86_64-linux ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 691b8b8deb81..6c35105225c0 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -359,11 +359,11 @@ docker \ rust-ci \ "${command[@]}" -if isCI; then - cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" -fi - if [ -f /.dockerenv ]; then rm -rf $objdir docker cp checkout:/checkout/obj $objdir fi + +if isCI; then + cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" +fi diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index e7f86e10f55a..0af0328c5f2f 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,8 +2,9 @@ set -euo pipefail -# https://github.com/rust-lang/rust/pull/145974 -LINUX_VERSION=842cfd8e5aff3157cb25481b2900b49c188d628a +# https://github.com/rust-lang/rust/pull/151534 +# https://github.com/rust-lang/rust/pull/149389 +LINUX_VERSION=167ea5357eb7c3a39200627a36dfbfe249576192 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 6e07ffc43bc2..2300904f22c1 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -23,7 +23,7 @@ runners: <<: *base-job - &job-macos - os: macos-14 + os: macos-15 # macOS 15 Arm64 <<: *base-job - &job-windows @@ -459,23 +459,46 @@ auto: # Ensure that host tooling is built to support our minimum support macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.4.app - USE_XCODE_CLANG: 1 + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos - name: dist-apple-various env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim,aarch64-apple-ios-macabi,x86_64-apple-ios-macabi + # Build and distribute the standard library for these targets. + TARGETS: "aarch64-apple-ios,\ + aarch64-apple-ios-sim,\ + x86_64-apple-ios,\ + aarch64-apple-ios-macabi,\ + x86_64-apple-ios-macabi,\ + aarch64-apple-tvos,\ + aarch64-apple-tvos-sim,\ + aarch64-apple-visionos,\ + aarch64-apple-visionos-sim,\ + aarch64-apple-watchos,\ + aarch64-apple-watchos-sim" + SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=$TARGETS # Mac Catalyst cannot currently compile the sanitizer: # https://github.com/rust-lang/rust/issues/129069 - RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false + # + # And tvOS and watchOS don't currently support the profiler runtime: + # https://github.com/rust-lang/rust/issues/152426 + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + --set target.aarch64-apple-ios-macabi.sanitizers=false + --set target.x86_64-apple-ios-macabi.sanitizers=false + --set target.aarch64-apple-tvos.profiler=false + --set target.aarch64-apple-tvos-sim.profiler=false + --set target.aarch64-apple-watchos.profiler=false + --set target.aarch64-apple-watchos-sim.profiler=false # Ensure that host tooling is built to support our minimum support macOS version. # FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?) MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.2.app + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer <<: *job-macos - name: dist-aarch64-apple @@ -496,8 +519,7 @@ auto: # supports the hardware. MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - SELECT_XCODE: /Applications/Xcode_15.4.app - USE_XCODE_CLANG: 1 + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos @@ -511,8 +533,7 @@ auto: --enable-sanitizers --enable-profiler --set rust.jemalloc - SELECT_XCODE: /Applications/Xcode_15.4.app - USE_XCODE_CLANG: 1 + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 657e1492a6d6..75e8fc240660 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -9,41 +9,11 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -# Update both macOS's and Windows's tarballs when bumping the version here. +# Update Windows's tarballs when bumping the version here. # Try to keep this in sync with src/ci/docker/scripts/build-clang.sh LLVM_VERSION="20.1.3" -if isMacOS; then - # FIXME: This is the latest pre-built version of LLVM that's available for - # x86_64 MacOS. We may want to consider building our own LLVM binaries - # instead, or set `USE_XCODE_CLANG` like AArch64 does. - LLVM_VERSION="15.0.7" - - # If the job selects a specific Xcode version, use that instead of - # downloading our own version. - if [[ ${USE_XCODE_CLANG-0} -eq 1 ]]; then - bindir="$(xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain/usr/bin" - else - file="${MIRRORS_BASE}/clang%2Bllvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - retry curl -f "${file}" -o "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - tar xJf "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - bindir="$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0/bin" - fi - - ciCommandSetEnv CC "${bindir}/clang" - ciCommandSetEnv CXX "${bindir}/clang++" - - # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: those - # are now located deep into the filesystem, under Xcode's own files. The - # native clang is configured to use the correct path, but our custom one - # doesn't. This sets the SDKROOT environment variable to the SDK so that - # our own clang can figure out the correct include path on its own. - ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" - - # Configure `AR` specifically so bootstrap doesn't try to infer it as - # `clang-ar` by accident. - ciCommandSetEnv AR "ar" -elif isWindows && ! isKnownToBeMingwBuild; then +if isWindows && ! isKnownToBeMingwBuild; then # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh deleted file mode 100755 index 569c4a4136d9..000000000000 --- a/src/ci/scripts/select-xcode.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# This script selects the Xcode instance to use. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isMacOS; then - sudo xcode-select -s "${SELECT_XCODE}" -fi diff --git a/src/doc/book b/src/doc/book index 39aeceaa3aea..05d114287b7d 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 39aeceaa3aeab845bc4517e7a44e48727d3b9dbe +Subproject commit 05d114287b7d6f6c9253d5242540f00fbd6172ab diff --git a/src/doc/index.md b/src/doc/index.md index 892057a8f4db..418939353975 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -194,9 +194,8 @@ resources maintained by the [Embedded Working Group] useful. #### The Embedded Rust Book -[The Embedded Rust Book] is targeted at developers familiar with embedded -development and familiar with Rust, but have not used Rust for embedded -development. +[The Embedded Rust Book] is targeted at developers who are familiar with embedded +development and Rust, but who have not used Rust for embedded development. [The Embedded Rust Book]: embedded-book/index.html [Rust project]: https://www.rust-lang.org diff --git a/src/doc/nomicon b/src/doc/nomicon index 050c002a360f..b8f254a991b8 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 050c002a360fa45b701ea34feed7a860dc8a41bf +Subproject commit b8f254a991b8b7e8f704527f0d4f343a4697dfa9 diff --git a/src/doc/not_found.md b/src/doc/not_found.md index 9552759d2b8b..69e6ae3e2d03 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -41,7 +41,7 @@ Some things that might be helpful to you though: