From 67c61cefaf87cb842b2248935dcc481faad21b14 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Oct 2025 09:39:13 +0000 Subject: [PATCH 001/182] Remove opts field from CodegenContext --- src/back/lto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 404064fb7a06..08c36d2b7318 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -290,7 +290,7 @@ pub(crate) fn run_thin( let dcx = cgcx.create_dcx(); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); - if cgcx.opts.cg.linker_plugin_lto.enabled() { + if cgcx.use_linker_plugin_lto { unreachable!( "We should never reach this case if the LTO step \ is deferred to the linker" From 385590e9dc85761402f278c61fd081c24c184cb6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 15:08:09 +0000 Subject: [PATCH 002/182] Remove SharedEmitter from CodegenContext --- src/back/lto.rs | 12 +++++------- src/back/write.rs | 8 ++++++-- src/lib.rs | 14 +++++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 08c36d2b7318..24be3ee4c34d 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -26,11 +26,11 @@ use std::sync::atomic::Ordering; use gccjit::{Context, OutputKind}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; +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_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; @@ -112,10 +112,11 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// for further optimization. pub(crate) fn run_fat( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); /*let symbols_below_threshold = @@ -283,12 +284,11 @@ impl ModuleBufferMethods for ModuleBuffer { /// 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 dcx = cgcx.create_dcx(); - let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); if cgcx.use_linker_plugin_lto { unreachable!( @@ -522,8 +522,6 @@ pub fn optimize_thin_module( thin_module: ThinModule, _cgcx: &CodegenContext, ) -> ModuleCodegen { - //let dcx = cgcx.create_dcx(); - //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))?;*/ diff --git a/src/back/write.rs b/src/back/write.rs index eae0f2aa00f6..b6223c5be370 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -2,8 +2,11 @@ use std::{env, fs}; use gccjit::{Context, OutputKind}; use rustc_codegen_ssa::back::link::ensure_removed; -use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; +use rustc_codegen_ssa::back::write::{ + BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter, +}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_errors::DiagCtxt; use rustc_fs_util::link_or_copy; use rustc_log::tracing::debug; use rustc_session::config::OutputType; @@ -15,10 +18,11 @@ use crate::{GccCodegenBackend, GccContext, LtoMode}; pub(crate) fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - let dcx = cgcx.create_dcx(); + 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); diff --git a/src/lib.rs b/src/lib.rs index 409b7886740a..5a2ec0a2fc68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,7 +82,7 @@ use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; @@ -371,23 +371,25 @@ impl WriteBackendMethods for GccCodegenBackend { fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, // 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, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( cgcx: &CodegenContext, + 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)>, ) -> (Vec>, Vec) { - back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules) + back::lto::run_thin(cgcx, dcx, each_linked_rlib_for_lto, modules, cached_modules) } fn print_pass_timings(&self) { @@ -400,7 +402,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize( _cgcx: &CodegenContext, - _dcx: DiagCtxtHandle<'_>, + _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { @@ -409,6 +411,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize_thin( cgcx: &CodegenContext, + _shared_emitter: &SharedEmitter, thin: ThinModule, ) -> ModuleCodegen { back::lto::optimize_thin_module(thin, cgcx) @@ -416,10 +419,11 @@ impl WriteBackendMethods for GccCodegenBackend { fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, module, config) + back::write::codegen(cgcx, shared_emitter, module, config) } fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { From a8ffa1cbb035ddeb6e5c6326ffca26f58e7bb2b6 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 6 Dec 2025 15:12:20 +0800 Subject: [PATCH 003/182] docs: update default branch name of `rust-lang/rust` --- book/src/development/infrastructure/sync.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/infrastructure/sync.md b/book/src/development/infrastructure/sync.md index 2bbdf47a8358..4506ff15d8ff 100644 --- a/book/src/development/infrastructure/sync.md +++ b/book/src/development/infrastructure/sync.md @@ -79,7 +79,7 @@ to be run inside the `rust` directory): ```bash git fetch upstream # assuming upstream is the rust-lang/rust remote git switch rustup - git merge upstream/master --no-ff + git merge upstream/main --no-ff ``` > Note: This is one of the few instances where a merge commit is allowed in > a PR. @@ -99,7 +99,7 @@ to be run inside the `rust` directory): All the following commands have to be run inside the `rust` directory. -1. Make sure you have checked out the latest `master` of `rust-lang/rust`. +1. Make sure you have checked out the latest `main` of `rust-lang/rust`. 2. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: ```bash git switch -c clippy-subtree-update From bf5283cf6fe637fba494f81793be5a40acf93e1f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 21 Dec 2025 00:13:38 +0100 Subject: [PATCH 004/182] Merge commit '02f889aec5dc9b4e51d4cfd86c67ce5e4a0bbf72' --- build_system/src/build.rs | 12 +++- rust-toolchain | 2 +- src/intrinsic/archs.rs | 123 +++++++++++++++++++++++++++++-------- tests/failing-ui-tests.txt | 9 +++ triagebot.toml | 3 - 5 files changed, 118 insertions(+), 31 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 27476465d740..9b7ee8380ca5 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -111,14 +111,20 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // Symlink libgccjit.so to sysroot. let lib_path = start_dir.join("sysroot").join("lib"); + let rustlib_target_path = lib_path + .join("rustlib") + .join(&config.host_triple) + .join("codegen-backends") + .join("lib") + .join(&config.target_triple); let libgccjit_path = PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point")) .join("libgccjit.so"); - let libgccjit_in_sysroot_path = lib_path.join("libgccjit.so"); + let libgccjit_in_sysroot_path = rustlib_target_path.join("libgccjit.so"); // First remove the file to be able to create the symlink even when the file already exists. let _ = fs::remove_file(&libgccjit_in_sysroot_path); - create_dir(&lib_path)?; - symlink(libgccjit_path, libgccjit_in_sysroot_path) + create_dir(&rustlib_target_path)?; + symlink(libgccjit_path, &libgccjit_in_sysroot_path) .map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?; let library_dir = start_dir.join("sysroot_src").join("library"); diff --git a/rust-toolchain b/rust-toolchain index f9645451e964..86ae738d4483 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-11-24" +channel = "nightly-2025-12-20" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index bb8bcbf66f38..43e7c352c34a 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -70,10 +70,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sve.sm4e" => "__builtin_sve_svsm4e_u32", "sve.sm4ekey" => "__builtin_sve_svsm4ekey_u32", "sve.wrffr" => "__builtin_sve_svwrffr", - "tcancel" => "__builtin_arm_tcancel", - "tcommit" => "__builtin_arm_tcommit", - "tstart" => "__builtin_arm_tstart", - "ttest" => "__builtin_arm_ttest", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -1632,6 +1628,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vabs.f8.128B" => "__builtin_HEXAGON_V6_vabs_f8_128B", "V6.vabs.hf" => "__builtin_HEXAGON_V6_vabs_hf", "V6.vabs.hf.128B" => "__builtin_HEXAGON_V6_vabs_hf_128B", + "V6.vabs.qf16.hf" => "__builtin_HEXAGON_V6_vabs_qf16_hf", + "V6.vabs.qf16.hf.128B" => "__builtin_HEXAGON_V6_vabs_qf16_hf_128B", + "V6.vabs.qf16.qf16" => "__builtin_HEXAGON_V6_vabs_qf16_qf16", + "V6.vabs.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vabs_qf16_qf16_128B", + "V6.vabs.qf32.qf32" => "__builtin_HEXAGON_V6_vabs_qf32_qf32", + "V6.vabs.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vabs_qf32_qf32_128B", + "V6.vabs.qf32.sf" => "__builtin_HEXAGON_V6_vabs_qf32_sf", + "V6.vabs.qf32.sf.128B" => "__builtin_HEXAGON_V6_vabs_qf32_sf_128B", "V6.vabs.sf" => "__builtin_HEXAGON_V6_vabs_sf", "V6.vabs.sf.128B" => "__builtin_HEXAGON_V6_vabs_sf_128B", "V6.vabsb" => "__builtin_HEXAGON_V6_vabsb", @@ -1744,6 +1748,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vaddwsat.128B" => "__builtin_HEXAGON_V6_vaddwsat_128B", "V6.vaddwsat.dv" => "__builtin_HEXAGON_V6_vaddwsat_dv", "V6.vaddwsat.dv.128B" => "__builtin_HEXAGON_V6_vaddwsat_dv_128B", + "V6.valign4" => "__builtin_HEXAGON_V6_valign4", + "V6.valign4.128B" => "__builtin_HEXAGON_V6_valign4_128B", "V6.valignb" => "__builtin_HEXAGON_V6_valignb", "V6.valignb.128B" => "__builtin_HEXAGON_V6_valignb_128B", "V6.valignbi" => "__builtin_HEXAGON_V6_valignbi", @@ -1862,14 +1868,30 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vcl0w.128B" => "__builtin_HEXAGON_V6_vcl0w_128B", "V6.vcombine" => "__builtin_HEXAGON_V6_vcombine", "V6.vcombine.128B" => "__builtin_HEXAGON_V6_vcombine_128B", + "V6.vconv.bf.qf32" => "__builtin_HEXAGON_V6_vconv_bf_qf32", + "V6.vconv.bf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_bf_qf32_128B", + "V6.vconv.f8.qf16" => "__builtin_HEXAGON_V6_vconv_f8_qf16", + "V6.vconv.f8.qf16.128B" => "__builtin_HEXAGON_V6_vconv_f8_qf16_128B", "V6.vconv.h.hf" => "__builtin_HEXAGON_V6_vconv_h_hf", "V6.vconv.h.hf.128B" => "__builtin_HEXAGON_V6_vconv_h_hf_128B", + "V6.vconv.h.hf.rnd" => "__builtin_HEXAGON_V6_vconv_h_hf_rnd", + "V6.vconv.h.hf.rnd.128B" => "__builtin_HEXAGON_V6_vconv_h_hf_rnd_128B", "V6.vconv.hf.h" => "__builtin_HEXAGON_V6_vconv_hf_h", "V6.vconv.hf.h.128B" => "__builtin_HEXAGON_V6_vconv_hf_h_128B", "V6.vconv.hf.qf16" => "__builtin_HEXAGON_V6_vconv_hf_qf16", "V6.vconv.hf.qf16.128B" => "__builtin_HEXAGON_V6_vconv_hf_qf16_128B", "V6.vconv.hf.qf32" => "__builtin_HEXAGON_V6_vconv_hf_qf32", "V6.vconv.hf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_hf_qf32_128B", + "V6.vconv.qf16.f8" => "__builtin_HEXAGON_V6_vconv_qf16_f8", + "V6.vconv.qf16.f8.128B" => "__builtin_HEXAGON_V6_vconv_qf16_f8_128B", + "V6.vconv.qf16.hf" => "__builtin_HEXAGON_V6_vconv_qf16_hf", + "V6.vconv.qf16.hf.128B" => "__builtin_HEXAGON_V6_vconv_qf16_hf_128B", + "V6.vconv.qf16.qf16" => "__builtin_HEXAGON_V6_vconv_qf16_qf16", + "V6.vconv.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vconv_qf16_qf16_128B", + "V6.vconv.qf32.qf32" => "__builtin_HEXAGON_V6_vconv_qf32_qf32", + "V6.vconv.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vconv_qf32_qf32_128B", + "V6.vconv.qf32.sf" => "__builtin_HEXAGON_V6_vconv_qf32_sf", + "V6.vconv.qf32.sf.128B" => "__builtin_HEXAGON_V6_vconv_qf32_sf_128B", "V6.vconv.sf.qf32" => "__builtin_HEXAGON_V6_vconv_sf_qf32", "V6.vconv.sf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_sf_qf32_128B", "V6.vconv.sf.w" => "__builtin_HEXAGON_V6_vconv_sf_w", @@ -1984,6 +2006,22 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.veqh.or.128B" => "__builtin_HEXAGON_V6_veqh_or_128B", "V6.veqh.xor" => "__builtin_HEXAGON_V6_veqh_xor", "V6.veqh.xor.128B" => "__builtin_HEXAGON_V6_veqh_xor_128B", + "V6.veqhf" => "__builtin_HEXAGON_V6_veqhf", + "V6.veqhf.128B" => "__builtin_HEXAGON_V6_veqhf_128B", + "V6.veqhf.and" => "__builtin_HEXAGON_V6_veqhf_and", + "V6.veqhf.and.128B" => "__builtin_HEXAGON_V6_veqhf_and_128B", + "V6.veqhf.or" => "__builtin_HEXAGON_V6_veqhf_or", + "V6.veqhf.or.128B" => "__builtin_HEXAGON_V6_veqhf_or_128B", + "V6.veqhf.xor" => "__builtin_HEXAGON_V6_veqhf_xor", + "V6.veqhf.xor.128B" => "__builtin_HEXAGON_V6_veqhf_xor_128B", + "V6.veqsf" => "__builtin_HEXAGON_V6_veqsf", + "V6.veqsf.128B" => "__builtin_HEXAGON_V6_veqsf_128B", + "V6.veqsf.and" => "__builtin_HEXAGON_V6_veqsf_and", + "V6.veqsf.and.128B" => "__builtin_HEXAGON_V6_veqsf_and_128B", + "V6.veqsf.or" => "__builtin_HEXAGON_V6_veqsf_or", + "V6.veqsf.or.128B" => "__builtin_HEXAGON_V6_veqsf_or_128B", + "V6.veqsf.xor" => "__builtin_HEXAGON_V6_veqsf_xor", + "V6.veqsf.xor.128B" => "__builtin_HEXAGON_V6_veqsf_xor_128B", "V6.veqw" => "__builtin_HEXAGON_V6_veqw", "V6.veqw.128B" => "__builtin_HEXAGON_V6_veqw_128B", "V6.veqw.and" => "__builtin_HEXAGON_V6_veqw_and", @@ -2096,6 +2134,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vgtw.or.128B" => "__builtin_HEXAGON_V6_vgtw_or_128B", "V6.vgtw.xor" => "__builtin_HEXAGON_V6_vgtw_xor", "V6.vgtw.xor.128B" => "__builtin_HEXAGON_V6_vgtw_xor_128B", + "V6.vilog2.hf" => "__builtin_HEXAGON_V6_vilog2_hf", + "V6.vilog2.hf.128B" => "__builtin_HEXAGON_V6_vilog2_hf_128B", + "V6.vilog2.qf16" => "__builtin_HEXAGON_V6_vilog2_qf16", + "V6.vilog2.qf16.128B" => "__builtin_HEXAGON_V6_vilog2_qf16_128B", + "V6.vilog2.qf32" => "__builtin_HEXAGON_V6_vilog2_qf32", + "V6.vilog2.qf32.128B" => "__builtin_HEXAGON_V6_vilog2_qf32_128B", + "V6.vilog2.sf" => "__builtin_HEXAGON_V6_vilog2_sf", + "V6.vilog2.sf.128B" => "__builtin_HEXAGON_V6_vilog2_sf_128B", "V6.vinsertwr" => "__builtin_HEXAGON_V6_vinsertwr", "V6.vinsertwr.128B" => "__builtin_HEXAGON_V6_vinsertwr_128B", "V6.vlalignb" => "__builtin_HEXAGON_V6_vlalignb", @@ -2350,6 +2396,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vnavgub.128B" => "__builtin_HEXAGON_V6_vnavgub_128B", "V6.vnavgw" => "__builtin_HEXAGON_V6_vnavgw", "V6.vnavgw.128B" => "__builtin_HEXAGON_V6_vnavgw_128B", + "V6.vneg.qf16.hf" => "__builtin_HEXAGON_V6_vneg_qf16_hf", + "V6.vneg.qf16.hf.128B" => "__builtin_HEXAGON_V6_vneg_qf16_hf_128B", + "V6.vneg.qf16.qf16" => "__builtin_HEXAGON_V6_vneg_qf16_qf16", + "V6.vneg.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vneg_qf16_qf16_128B", + "V6.vneg.qf32.qf32" => "__builtin_HEXAGON_V6_vneg_qf32_qf32", + "V6.vneg.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vneg_qf32_qf32_128B", + "V6.vneg.qf32.sf" => "__builtin_HEXAGON_V6_vneg_qf32_sf", + "V6.vneg.qf32.sf.128B" => "__builtin_HEXAGON_V6_vneg_qf32_sf_128B", "V6.vnormamth" => "__builtin_HEXAGON_V6_vnormamth", "V6.vnormamth.128B" => "__builtin_HEXAGON_V6_vnormamth_128B", "V6.vnormamtw" => "__builtin_HEXAGON_V6_vnormamtw", @@ -2684,6 +2738,24 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "iocsrwr.d" => "__builtin_loongarch_iocsrwr_d", "iocsrwr.h" => "__builtin_loongarch_iocsrwr_h", "iocsrwr.w" => "__builtin_loongarch_iocsrwr_w", + "lasx.cast.128" => "__builtin_lasx_cast_128", + "lasx.cast.128.d" => "__builtin_lasx_cast_128_d", + "lasx.cast.128.s" => "__builtin_lasx_cast_128_s", + "lasx.concat.128" => "__builtin_lasx_concat_128", + "lasx.concat.128.d" => "__builtin_lasx_concat_128_d", + "lasx.concat.128.s" => "__builtin_lasx_concat_128_s", + "lasx.extract.128.hi" => "__builtin_lasx_extract_128_hi", + "lasx.extract.128.hi.d" => "__builtin_lasx_extract_128_hi_d", + "lasx.extract.128.hi.s" => "__builtin_lasx_extract_128_hi_s", + "lasx.extract.128.lo" => "__builtin_lasx_extract_128_lo", + "lasx.extract.128.lo.d" => "__builtin_lasx_extract_128_lo_d", + "lasx.extract.128.lo.s" => "__builtin_lasx_extract_128_lo_s", + "lasx.insert.128.hi" => "__builtin_lasx_insert_128_hi", + "lasx.insert.128.hi.d" => "__builtin_lasx_insert_128_hi_d", + "lasx.insert.128.hi.s" => "__builtin_lasx_insert_128_hi_s", + "lasx.insert.128.lo" => "__builtin_lasx_insert_128_lo", + "lasx.insert.128.lo.d" => "__builtin_lasx_insert_128_lo_d", + "lasx.insert.128.lo.s" => "__builtin_lasx_insert_128_lo_s", "lasx.vext2xv.d.b" => "__builtin_lasx_vext2xv_d_b", "lasx.vext2xv.d.h" => "__builtin_lasx_vext2xv_d_h", "lasx.vext2xv.d.w" => "__builtin_lasx_vext2xv_d_w", @@ -4950,8 +5022,20 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "f16x2.to.e5m2x2.rn.relu" => "__nvvm_f16x2_to_e5m2x2_rn_relu", "f2bf16.rn" => "__nvvm_f2bf16_rn", "f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu", + "f2bf16.rn.relu.satfinite" => "__nvvm_f2bf16_rn_relu_satfinite", + "f2bf16.rn.satfinite" => "__nvvm_f2bf16_rn_satfinite", "f2bf16.rz" => "__nvvm_f2bf16_rz", "f2bf16.rz.relu" => "__nvvm_f2bf16_rz_relu", + "f2bf16.rz.relu.satfinite" => "__nvvm_f2bf16_rz_relu_satfinite", + "f2bf16.rz.satfinite" => "__nvvm_f2bf16_rz_satfinite", + "f2f16.rn" => "__nvvm_f2f16_rn", + "f2f16.rn.relu" => "__nvvm_f2f16_rn_relu", + "f2f16.rn.relu.satfinite" => "__nvvm_f2f16_rn_relu_satfinite", + "f2f16.rn.satfinite" => "__nvvm_f2f16_rn_satfinite", + "f2f16.rz" => "__nvvm_f2f16_rz", + "f2f16.rz.relu" => "__nvvm_f2f16_rz_relu", + "f2f16.rz.relu.satfinite" => "__nvvm_f2f16_rz_relu_satfinite", + "f2f16.rz.satfinite" => "__nvvm_f2f16_rz_satfinite", "f2h.rn" => "__nvvm_f2h_rn", "f2h.rn.ftz" => "__nvvm_f2h_rn_ftz", "f2i.rm" => "__nvvm_f2i_rm", @@ -5035,20 +5119,28 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ff.to.ue8m0x2.rz.satfinite" => "__nvvm_ff_to_ue8m0x2_rz_satfinite", "ff2bf16x2.rn" => "__nvvm_ff2bf16x2_rn", "ff2bf16x2.rn.relu" => "__nvvm_ff2bf16x2_rn_relu", + "ff2bf16x2.rn.relu.satfinite" => "__nvvm_ff2bf16x2_rn_relu_satfinite", + "ff2bf16x2.rn.satfinite" => "__nvvm_ff2bf16x2_rn_satfinite", "ff2bf16x2.rs" => "__nvvm_ff2bf16x2_rs", "ff2bf16x2.rs.relu" => "__nvvm_ff2bf16x2_rs_relu", "ff2bf16x2.rs.relu.satfinite" => "__nvvm_ff2bf16x2_rs_relu_satfinite", "ff2bf16x2.rs.satfinite" => "__nvvm_ff2bf16x2_rs_satfinite", "ff2bf16x2.rz" => "__nvvm_ff2bf16x2_rz", "ff2bf16x2.rz.relu" => "__nvvm_ff2bf16x2_rz_relu", + "ff2bf16x2.rz.relu.satfinite" => "__nvvm_ff2bf16x2_rz_relu_satfinite", + "ff2bf16x2.rz.satfinite" => "__nvvm_ff2bf16x2_rz_satfinite", "ff2f16x2.rn" => "__nvvm_ff2f16x2_rn", "ff2f16x2.rn.relu" => "__nvvm_ff2f16x2_rn_relu", + "ff2f16x2.rn.relu.satfinite" => "__nvvm_ff2f16x2_rn_relu_satfinite", + "ff2f16x2.rn.satfinite" => "__nvvm_ff2f16x2_rn_satfinite", "ff2f16x2.rs" => "__nvvm_ff2f16x2_rs", "ff2f16x2.rs.relu" => "__nvvm_ff2f16x2_rs_relu", "ff2f16x2.rs.relu.satfinite" => "__nvvm_ff2f16x2_rs_relu_satfinite", "ff2f16x2.rs.satfinite" => "__nvvm_ff2f16x2_rs_satfinite", "ff2f16x2.rz" => "__nvvm_ff2f16x2_rz", "ff2f16x2.rz.relu" => "__nvvm_ff2f16x2_rz_relu", + "ff2f16x2.rz.relu.satfinite" => "__nvvm_ff2f16x2_rz_relu_satfinite", + "ff2f16x2.rz.satfinite" => "__nvvm_ff2f16x2_rz_satfinite", "floor.d" => "__nvvm_floor_d", "floor.f" => "__nvvm_floor_f", "floor.ftz.f" => "__nvvm_floor_ftz_f", @@ -5942,6 +6034,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", "altivec.vupklsw" => "__builtin_altivec_vupklsw", + "amo.ldat" => "__builtin_amo_ldat", + "amo.lwat" => "__builtin_amo_lwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", @@ -6202,6 +6296,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xvminsp" => "__builtin_vsx_xvminsp", "vsx.xvredp" => "__builtin_vsx_xvredp", "vsx.xvresp" => "__builtin_vsx_xvresp", + "vsx.xvrlw" => "__builtin_vsx_xvrlw", "vsx.xvrsqrtedp" => "__builtin_vsx_xvrsqrtedp", "vsx.xvrsqrtesp" => "__builtin_vsx_xvrsqrtesp", "vsx.xvtdivdp" => "__builtin_vsx_xvtdivdp", @@ -10158,24 +10253,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "stui" => "__builtin_ia32_stui", "subborrow.u32" => "__builtin_ia32_subborrow_u32", "subborrow.u64" => "__builtin_ia32_subborrow_u64", - "t2rpntlvwz0" => "__builtin_ia32_t2rpntlvwz0", "t2rpntlvwz0rs" => "__builtin_ia32_t2rpntlvwz0rs", "t2rpntlvwz0rst1" => "__builtin_ia32_t2rpntlvwz0rst1", - "t2rpntlvwz0t1" => "__builtin_ia32_t2rpntlvwz0t1", - "t2rpntlvwz1" => "__builtin_ia32_t2rpntlvwz1", "t2rpntlvwz1rs" => "__builtin_ia32_t2rpntlvwz1rs", "t2rpntlvwz1rst1" => "__builtin_ia32_t2rpntlvwz1rst1", - "t2rpntlvwz1t1" => "__builtin_ia32_t2rpntlvwz1t1", "tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "tbm.bextri.u64" => "__builtin_ia32_bextri_u64", "tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", "tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal", "tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps", "tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", - "tconjtcmmimfp16ps" => "__builtin_ia32_tconjtcmmimfp16ps", - "tconjtcmmimfp16ps.internal" => "__builtin_ia32_tconjtcmmimfp16ps_internal", - "tconjtfp16" => "__builtin_ia32_tconjtfp16", - "tconjtfp16.internal" => "__builtin_ia32_tconjtfp16_internal", "tcvtrowd2ps" => "__builtin_ia32_tcvtrowd2ps", "tcvtrowd2ps.internal" => "__builtin_ia32_tcvtrowd2ps_internal", "tcvtrowps2bf16h" => "__builtin_ia32_tcvtrowps2bf16h", @@ -10225,18 +10312,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tmmultf32ps" => "__builtin_ia32_tmmultf32ps", "tmmultf32ps.internal" => "__builtin_ia32_tmmultf32ps_internal", "tpause" => "__builtin_ia32_tpause", - "ttcmmimfp16ps" => "__builtin_ia32_ttcmmimfp16ps", - "ttcmmimfp16ps.internal" => "__builtin_ia32_ttcmmimfp16ps_internal", - "ttcmmrlfp16ps" => "__builtin_ia32_ttcmmrlfp16ps", - "ttcmmrlfp16ps.internal" => "__builtin_ia32_ttcmmrlfp16ps_internal", - "ttdpbf16ps" => "__builtin_ia32_ttdpbf16ps", - "ttdpbf16ps.internal" => "__builtin_ia32_ttdpbf16ps_internal", - "ttdpfp16ps" => "__builtin_ia32_ttdpfp16ps", - "ttdpfp16ps.internal" => "__builtin_ia32_ttdpfp16ps_internal", - "ttmmultf32ps" => "__builtin_ia32_ttmmultf32ps", - "ttmmultf32ps.internal" => "__builtin_ia32_ttmmultf32ps_internal", - "ttransposed" => "__builtin_ia32_ttransposed", - "ttransposed.internal" => "__builtin_ia32_ttransposed_internal", "umonitor" => "__builtin_ia32_umonitor", "umwait" => "__builtin_ia32_umwait", "urdmsr" => "__builtin_ia32_urdmsr", diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2380bd0fc137..99a80fa7e4f4 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -88,3 +88,12 @@ tests/ui/test-attrs/test-panic-while-printing.rs 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/default/local_crate.rs +tests/ui/eii/multiple_impls.rs +tests/ui/eii/default/call_default.rs +tests/ui/eii/same-symbol.rs +tests/ui/eii/privacy1.rs +tests/ui/eii/default/call_impl.rs diff --git a/triagebot.toml b/triagebot.toml index 13da0a87def3..eb0c7b011f60 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -2,6 +2,3 @@ # Prevents un-canonicalized issue links (to avoid wrong issues being linked in r-l/rust) [issue-links] - -# Prevents mentions in commits to avoid users being spammed -[no-mentions] From 9ba3ed5423d409cf92ab85a80c9b49dd9a148c92 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Sep 2025 13:25:01 +0000 Subject: [PATCH 005/182] Move llvm intrinsic call to backend --- src/intrinsic/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index d2714ba7914f..75ea39c23114 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -9,7 +9,7 @@ use gccjit::Type; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; -use rustc_abi::{BackendRepr, HasDataLayout}; +use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -20,7 +20,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - IntrinsicCallBuilderMethods, + IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; use rustc_middle::bug; #[cfg(feature = "master")] @@ -609,6 +609,54 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc Ok(()) } + fn codegen_llvm_intrinsic_call( + &mut self, + instance: ty::Instance<'tcx>, + args: &[OperandRef<'tcx, Self::Value>], + is_cleanup: bool, + ) -> Self::Value { + let fn_ptr = self.get_fn_addr(instance); + let fn_ty = fn_ptr.get_type(); + + let mut llargs = vec![]; + + for arg in args { + match arg.val { + OperandValue::ZeroSized => {} + OperandValue::Immediate(_) => llargs.push(arg.immediate()), + OperandValue::Pair(a, b) => { + llargs.push(a); + llargs.push(b); + } + OperandValue::Ref(op_place_val) => { + let mut llval = op_place_val.llval; + // We can't use `PlaceRef::load` here because the argument + // may have a type we don't treat as immediate, but the ABI + // used for this call is passing it by-value. In that case, + // the load would just produce `OperandValue::Ref` instead + // of the `OperandValue::Immediate` we need for the call. + llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align); + if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr { + if scalar.is_bool() { + self.range_metadata(llval, WrappingRange { start: 0, end: 1 }); + } + // We store bools as `i8` so we need to truncate to `i1`. + llval = self.to_immediate_scalar(llval, scalar); + } + llargs.push(llval); + } + } + } + + // FIXME directly use the llvm intrinsic adjustment functions here + let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None); + if is_cleanup { + self.apply_attrs_to_cleanup_callsite(llret); + } + + llret + } + fn abort(&mut self) { let func = self.context.get_builtin_function("abort"); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; From 0462ce9934e6b66e44c5f4ab673ff3fde52395b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:03:25 +0100 Subject: [PATCH 006/182] Don't assume get_fn is only called from codegen_mir in cg_gcc --- src/builder.rs | 1 + src/context.rs | 4 +--- src/declare.rs | 8 ++------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 79228c20d292..f57c50eb64d1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -514,6 +514,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { type CodegenCx = CodegenCx<'gcc, 'tcx>; fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> { + *cx.current_func.borrow_mut() = Some(block.get_function()); Builder::with_cx(cx, block) } diff --git a/src/context.rs b/src/context.rs index dbb89a4ff7db..67bec261cc2e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -391,9 +391,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> { - let func = get_fn(self, instance); - *self.current_func.borrow_mut() = Some(func); - func + get_fn(self, instance) } fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { diff --git a/src/declare.rs b/src/declare.rs index 42d6fb17a88b..fec7d9d0a403 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -100,18 +100,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let return_type = self.type_i32(); let variadic = false; self.linkage.set(FunctionType::Exported); - let func = declare_raw_fn( + declare_raw_fn( self, name, callconv, return_type, &[self.type_i32(), const_string], variadic, - ); - // NOTE: it is needed to set the current_func here as well, because get_fn() is not called - // for the main function. - *self.current_func.borrow_mut() = Some(func); - func + ) } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { From 56be08eb45c2a1e0169470a3f0644fe296d1b534 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:14:03 +0100 Subject: [PATCH 007/182] Pass Function to Builder::function_call in cg_gcc --- src/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index f57c50eb64d1..8b4a8de94bf3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -316,12 +316,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn function_call( &mut self, - func: RValue<'gcc>, + func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, ) -> RValue<'gcc> { - // TODO(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); let args = self.check_call("call", func, args); // gccjit requires to use the result of functions, even when it's not used. @@ -1766,6 +1764,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): remove when having a proper API. let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // TODO(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); self.function_call(func, args, funclet) } else { // If it's a not function that was defined, it's a function pointer. From 5bcd472b8688437b4967bcba077c4089572a17ea Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:42:32 +0000 Subject: [PATCH 008/182] Partially inline get_fn_addr/get_fn in codegen_llvm_intrinsic_call This moves all LLVM intrinsic handling out of the regular call path for cg_gcc and makes it easier to hook into this code for future cg_llvm changes. --- src/builder.rs | 2 +- src/context.rs | 7 ++++--- src/declare.rs | 14 -------------- src/intrinsic/mod.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8b4a8de94bf3..3def9a5c015c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -314,7 +314,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } - fn function_call( + pub fn function_call( &mut self, func: Function<'gcc>, args: &[RValue<'gcc>], diff --git a/src/context.rs b/src/context.rs index 67bec261cc2e..d200d5319a93 100644 --- a/src/context.rs +++ b/src/context.rs @@ -92,6 +92,8 @@ pub struct CodegenCx<'gcc, 'tcx> { pub instances: RefCell, LValue<'gcc>>>, /// Cache function instances of monomorphic and polymorphic items pub function_instances: RefCell, Function<'gcc>>>, + /// Cache function instances of intrinsics + pub intrinsic_instances: RefCell, Function<'gcc>>>, /// Cache generated vtables pub vtables: RefCell, Option>), RValue<'gcc>>>, @@ -280,6 +282,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { linkage: Cell::new(FunctionType::Internal), instances: Default::default(), function_instances: Default::default(), + intrinsic_instances: Default::default(), on_stack_params: Default::default(), on_stack_function_params: Default::default(), vtables: Default::default(), @@ -397,9 +400,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; - let func = if self.intrinsics.borrow().contains_key(func_name) { - self.intrinsics.borrow()[func_name] - } else if let Some(variable) = self.get_declared_value(func_name) { + let func = if let Some(variable) = self.get_declared_value(func_name) { return variable; } else { get_fn(self, instance) diff --git a/src/declare.rs b/src/declare.rs index fec7d9d0a403..e4130b221ee3 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -8,7 +8,6 @@ use rustc_target::callconv::FnAbi; use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; -use crate::intrinsic::llvm; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn get_or_insert_global( @@ -162,19 +161,6 @@ fn declare_raw_fn<'gcc>( param_types: &[Type<'gcc>], variadic: bool, ) -> Function<'gcc> { - if name.starts_with("llvm.") { - let intrinsic = match name { - "llvm.fma.f16" => { - // fma is not a target builtin, but a normal builtin, so we handle it differently - // here. - cx.context.get_builtin_function("fma") - } - _ => llvm::intrinsic(name, cx), - }; - - cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic); - return intrinsic; - } let func = if cx.functions.borrow().contains_key(name) { cx.functions.borrow()[name] } else { diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 75ea39c23114..77b88a969084 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -615,7 +615,47 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc args: &[OperandRef<'tcx, Self::Value>], is_cleanup: bool, ) -> Self::Value { - let fn_ptr = self.get_fn_addr(instance); + let func = if let Some(&func) = self.intrinsic_instances.borrow().get(&instance) { + func + } else { + let sym = self.tcx.symbol_name(instance).name; + + let func = if let Some(func) = self.intrinsics.borrow().get(sym) { + *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" => { + // fma is not a target builtin, but a normal builtin, so we handle it differently + // here. + self.context.get_builtin_function("fma") + } + _ => llvm::intrinsic(sym, self), + }; + + 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); + } + + crate::attributes::from_fn_attrs(self, func, instance); + + func + }; + + self.intrinsic_instances.borrow_mut().insert(instance, func); + + func + }; + let fn_ptr = func.get_address(None); let fn_ty = fn_ptr.get_type(); let mut llargs = vec![]; From ea8f037c760f1eb0099521230c87318d028d8e49 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 27 Dec 2025 08:49:59 +0000 Subject: [PATCH 009/182] Fix compilation of cg_gcc with master feature disabled --- src/intrinsic/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 77b88a969084..36ea76cbc51a 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -23,16 +23,12 @@ use rustc_codegen_ssa::traits::{ IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; use rustc_middle::bug; -#[cfg(feature = "master")] -use rustc_middle::ty::layout::FnAbiOf; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; -#[cfg(feature = "master")] -use crate::abi::FnAbiGccExt; -use crate::abi::GccType; +use crate::abi::{FnAbiGccExt, GccType}; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; From f004b3eb19b988a9066ca9dc9b2a63919f504ada Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:05:09 +0000 Subject: [PATCH 010/182] Reduce usage of FnAbi in codegen_llvm_intrinsic_call --- src/intrinsic/mod.rs | 88 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 36ea76cbc51a..f138b87d3405 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,10 +4,10 @@ mod simd; #[cfg(feature = "master")] use std::iter; -#[cfg(feature = "master")] -use gccjit::Type; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] +use gccjit::{FnAttribute, Type}; +#[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; @@ -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}; use rustc_middle::ty::{self, Instance, Ty}; +#[cfg(feature = "master")] +use rustc_session::config; use rustc_span::{Span, Symbol, sym}; +#[cfg(feature = "master")] +use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGccExt, GccType}; +use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -621,7 +626,82 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } 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); + assert!(!fn_abi.ret.is_indirect()); + assert!(!fn_abi.c_variadic); + + let return_type = match fn_abi.ret.mode { + PassMode::Ignore => self.type_void(), + PassMode::Direct(_) | PassMode::Pair(..) => { + fn_abi.ret.layout.immediate_gcc_type(self) + } + PassMode::Cast { .. } | PassMode::Indirect { .. } => { + unreachable!() + } + }; + + #[cfg(feature = "master")] + let mut non_null_args = Vec::new(); + + #[cfg(feature = "master")] + let mut apply_attrs = + |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { + if self.sess().opts.optimize == config::OptLevel::No { + return ty; + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { + ty = ty.make_restrict() + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { + non_null_args.push(arg_index as i32 + 1); + } + ty + }; + #[cfg(not(feature = "master"))] + let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; + + let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); + for arg in fn_abi.args.iter() { + match arg.mode { + PassMode::Ignore => {} + PassMode::Pair(a, b) => { + let arg_pos = argument_tys.len(); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 0), + &a, + arg_pos, + )); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 1), + &b, + arg_pos + 1, + )); + } + PassMode::Direct(attrs) => argument_tys.push(apply_attrs( + arg.layout.immediate_gcc_type(self), + &attrs, + argument_tys.len(), + )), + PassMode::Indirect { .. } | PassMode::Cast { .. } => { + unreachable!() + } + } + } + + #[cfg(feature = "master")] + let fn_attrs = if non_null_args.is_empty() { + Vec::new() + } else { + vec![FnAttribute::NonNull(non_null_args)] + }; + + let fn_ty = FnAbiGcc { + return_type, + arguments_type: argument_tys, + is_c_variadic: false, + on_stack_param_indices: FxHashSet::default(), + #[cfg(feature = "master")] + fn_attributes: fn_attrs, + }; let func = match sym { "llvm.fma.f16" => { From e90414f6224b95662c2f52fcfc508a316f54db09 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:47:29 +0000 Subject: [PATCH 011/182] Don't compute FnAbi for LLVM intrinsics in backends --- src/intrinsic/mod.rs | 101 ++++--------------------------------------- 1 file changed, 9 insertions(+), 92 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f138b87d3405..de262994fa45 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,9 +4,9 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] -use gccjit::{FnAttribute, Type}; +use gccjit::Type; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; @@ -24,16 +24,16 @@ use rustc_codegen_ssa::traits::{ }; 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}; -#[cfg(feature = "master")] -use rustc_session::config; use rustc_span::{Span, Symbol, sym}; -#[cfg(feature = "master")] -use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGcc, 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; @@ -625,83 +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()); - assert!(!fn_abi.ret.is_indirect()); - assert!(!fn_abi.c_variadic); - - let return_type = match fn_abi.ret.mode { - PassMode::Ignore => self.type_void(), - PassMode::Direct(_) | PassMode::Pair(..) => { - fn_abi.ret.layout.immediate_gcc_type(self) - } - PassMode::Cast { .. } | PassMode::Indirect { .. } => { - unreachable!() - } - }; - - #[cfg(feature = "master")] - let mut non_null_args = Vec::new(); - - #[cfg(feature = "master")] - let mut apply_attrs = - |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { - if self.sess().opts.optimize == config::OptLevel::No { - return ty; - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { - ty = ty.make_restrict() - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { - non_null_args.push(arg_index as i32 + 1); - } - ty - }; - #[cfg(not(feature = "master"))] - let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - - let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); - for arg in fn_abi.args.iter() { - match arg.mode { - PassMode::Ignore => {} - PassMode::Pair(a, b) => { - let arg_pos = argument_tys.len(); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 0), - &a, - arg_pos, - )); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 1), - &b, - arg_pos + 1, - )); - } - PassMode::Direct(attrs) => argument_tys.push(apply_attrs( - arg.layout.immediate_gcc_type(self), - &attrs, - argument_tys.len(), - )), - PassMode::Indirect { .. } | PassMode::Cast { .. } => { - unreachable!() - } - } - } - - #[cfg(feature = "master")] - let fn_attrs = if non_null_args.is_empty() { - Vec::new() - } else { - vec![FnAttribute::NonNull(non_null_args)] - }; - - let fn_ty = FnAbiGcc { - return_type, - arguments_type: argument_tys, - is_c_variadic: false, - on_stack_param_indices: FxHashSet::default(), - #[cfg(feature = "master")] - fn_attributes: fn_attrs, - }; let func = match sym { "llvm.fma.f16" => { @@ -714,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); From fe0facf0f6f021f0c5d597fb214d96ae48571c91 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 1 Jan 2026 10:47:22 +0100 Subject: [PATCH 012/182] Finish transition from `semitransparent` to `semiopaque` for `rustc_macro_transparency` --- example/mini_core.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 64a5b431bd07..0aba44a88c5a 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -748,25 +748,25 @@ extern "C" { pub struct VaList<'a>(&'a mut VaListImpl); #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro stringify($($t:tt)*) { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro file() { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro line() { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro cfg() { /* compiler built-in */ } From c9a063ced93ec7dce1dfaca57f818dba5334cfca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Jan 2026 10:30:08 +1100 Subject: [PATCH 013/182] Remove `Deref`/`DerefMut` impl for `Providers`. It's described as a "backwards compatibility hack to keep the diff small". Removing it requires only a modest amount of churn, and the resulting code is clearer without the invisible derefs. --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 96d3a0024f41..cf1be1806235 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -286,7 +286,8 @@ impl CodegenBackend for GccCodegenBackend { } fn provide(&self, providers: &mut Providers) { - providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess) + providers.queries.global_backend_features = + |tcx, ()| gcc_util::global_gcc_features(tcx.sess) } fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { From 628bacac3312357af71816b0875174062b310a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 04:22:55 +0100 Subject: [PATCH 014/182] add tests for emergent behavior of partial captures --- .../auxiliary/partial_move_drop_order_lib.rs | 11 ++ .../match/auxiliary/partial_move_lib.rs | 4 + .../match/partial-move-drop-order.rs | 83 ++++++++++++ .../match/partial-move-drop-order.run.stdout | 23 ++++ .../match/partial-move.rs | 118 +++++++++++++++++ .../match/partial-move.stderr | 123 ++++++++++++++++++ 6 files changed, 362 insertions(+) create mode 100644 tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move.stderr diff --git a/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs new file mode 100644 index 000000000000..8cf25c6ba7b2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs @@ -0,0 +1,11 @@ +pub struct LoudDrop(pub &'static str); +impl Drop for LoudDrop { + fn drop(&mut self) { + println!("dropping {}", self.0); + } +} + +#[non_exhaustive] +pub enum ExtNonExhaustive { + One(i32, LoudDrop), +} diff --git a/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs new file mode 100644 index 000000000000..b0646f1d0032 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs @@ -0,0 +1,4 @@ +#[non_exhaustive] +pub enum ExtNonExhaustive { + A(u32, String), +} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs new file mode 100644 index 000000000000..1c178bd3f684 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs @@ -0,0 +1,83 @@ +//@ edition:2021 +//@ run-pass +//@ check-run-results +//@ aux-build:partial_move_drop_order_lib.rs + +extern crate partial_move_drop_order_lib; +use partial_move_drop_order_lib::{LoudDrop, ExtNonExhaustive}; + +pub enum OneVariant { + One(i32, LoudDrop), +} + +pub enum TwoVariants { + One(i32, LoudDrop), + Two, +} + +#[non_exhaustive] +pub enum NonExhaustive { + One(i32, LoudDrop), +} + +#[allow(unused)] +fn one_variant() { + println!("one variant:"); + let mut thing = OneVariant::One(0, LoudDrop("a")); + let closure = move || match thing { + OneVariant::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = OneVariant::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn two_variants() { + println!("two variants:"); + let mut thing = TwoVariants::One(0, LoudDrop("a")); + let closure = move || match thing { + TwoVariants::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = TwoVariants::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn non_exhaustive() { + println!("non exhaustive:"); + let mut thing = NonExhaustive::One(0, LoudDrop("a")); + let closure = move || match thing { + NonExhaustive::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = NonExhaustive::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn ext_non_exhaustive() { + println!("external non exhaustive:"); + let mut thing = ExtNonExhaustive::One(0, LoudDrop("a")); + let closure = move || match thing { + ExtNonExhaustive::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = ExtNonExhaustive::One(1, LoudDrop("b")); + println!("after assign"); +} + +fn main() { + one_variant(); + println!(); + two_variants(); + println!(); + non_exhaustive(); + println!(); + ext_non_exhaustive(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout new file mode 100644 index 000000000000..e0d83dd99549 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout @@ -0,0 +1,23 @@ +one variant: +before assign +dropping a +after assign +dropping b + +two variants: +before assign +after assign +dropping a +dropping b + +non exhaustive: +before assign +dropping a +after assign +dropping b + +external non exhaustive: +before assign +after assign +dropping a +dropping b diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs new file mode 100644 index 000000000000..62d1b362cb83 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs @@ -0,0 +1,118 @@ +// This test measures the effect of matching-induced partial captures on the borrow checker. +// In particular, in each of the cases below, the closure either captures the entire enum/struct, +// or each field separately. +// +// If the entire ADT gets captured, it'll happen by move, and the closure will live for 'static. +// On the other hand, if each field gets captured separately, the u32 field, being Copy, will only +// get captured by an immutable borrow, resulting in a borrow checker error. +// +// See rust-lang/rust#147722 +// +//@ edition:2021 +//@ aux-build:partial_move_lib.rs +pub struct Struct(u32, String); + +pub enum Enum { + A(u32, String), +} + +pub enum TwoVariants { + A(u32, String), + B, +} + +#[non_exhaustive] +pub enum NonExhaustive { + A(u32, String), +} + +extern crate partial_move_lib; +use partial_move_lib::ExtNonExhaustive; + +// First, let's assert that the additional wildcard arm is not a source of any behavior +// differences: +pub fn test_enum1(x: Enum) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Enum::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +pub fn test_enum2(x: Enum) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Enum::A(a, b) => { + drop((a, b)); + } + } + } +} + +// The behavior for single-variant enums matches what happens for a struct +pub fn test_struct(x: Struct) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Struct(a, b) => { + drop((a, b)); + } + } + } +} + +// If we have two variants, the entire enum gets moved into the closure +pub fn test_two_variants(x: TwoVariants) -> impl FnOnce() { + || { + match x { + TwoVariants::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +// ...and single-variant, non-exhaustive enums *should* behave as if they had multiple variants +pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + NonExhaustive::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +// (again, wildcard branch or not) +pub fn test_non_exhaustive2(x: NonExhaustive) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + NonExhaustive::A(a, b) => { + drop((a, b)); + } + } + } +} + +// ...regardless of whether the enum is defined in the current, or in another crate +pub fn test_ext(x: ExtNonExhaustive) -> impl FnOnce() { + || { + match x { + ExtNonExhaustive::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr new file mode 100644 index 000000000000..36adcc6717ed --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr @@ -0,0 +1,123 @@ +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:35:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:35:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Enum::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:47:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:47:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Enum::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:59:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:59:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Struct(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:83:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:83:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | NonExhaustive::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:96:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:96:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | NonExhaustive::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0373`. From 3c175080dca2a60eb42a28d46ecc416d3a6f8879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 19:34:37 +0100 Subject: [PATCH 015/182] add tests for discriminant read borrowck --- tests/ui/match/borrowck-uninhabited.rs | 53 +++++++++++++++++++ tests/ui/match/borrowck-uninhabited.stderr | 14 +++++ tests/ui/match/uninhabited-granular-moves.rs | 46 ++++++++++++++++ .../match/uninhabited-granular-moves.stderr | 18 +++++++ 4 files changed, 131 insertions(+) create mode 100644 tests/ui/match/borrowck-uninhabited.rs create mode 100644 tests/ui/match/borrowck-uninhabited.stderr create mode 100644 tests/ui/match/uninhabited-granular-moves.rs create mode 100644 tests/ui/match/uninhabited-granular-moves.stderr diff --git a/tests/ui/match/borrowck-uninhabited.rs b/tests/ui/match/borrowck-uninhabited.rs new file mode 100644 index 000000000000..93838ede2793 --- /dev/null +++ b/tests/ui/match/borrowck-uninhabited.rs @@ -0,0 +1,53 @@ +// See: rust-lang/rust#146590 + +enum Never {} + +// baseline +fn both_inhabited(x: &mut Result) { + match x { + &mut Ok(ref mut y) => match x { + //~^ ERROR: cannot use `*x` because it was mutably borrowed + &mut Err(ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + }, + _ => {} + }; +} + +fn ref_uninhabited(x: &mut Result) { + match x { + &mut Ok(ref mut y) => match x { + &mut Err(ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + }, + _ => {} + }; +} + +enum Single { + V(String, String), +} + +// arguably this should be rejected as well, but currently it is still accepted +fn single_variant(x: &mut Single) { + match x { + &mut Single::V(ref mut y, _) => { + match x { + &mut Single::V(_, ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + } + }, + _ => {} + }; +} + +fn main() {} diff --git a/tests/ui/match/borrowck-uninhabited.stderr b/tests/ui/match/borrowck-uninhabited.stderr new file mode 100644 index 000000000000..ee3b814da9f4 --- /dev/null +++ b/tests/ui/match/borrowck-uninhabited.stderr @@ -0,0 +1,14 @@ +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/borrowck-uninhabited.rs:8:37 + | +LL | &mut Ok(ref mut y) => match x { + | --------- ^ use of borrowed `x.0` + | | + | `x.0` is borrowed here +... +LL | let _y = y; + | - borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/match/uninhabited-granular-moves.rs b/tests/ui/match/uninhabited-granular-moves.rs new file mode 100644 index 000000000000..9d04fcb3259e --- /dev/null +++ b/tests/ui/match/uninhabited-granular-moves.rs @@ -0,0 +1,46 @@ +// See rust-lang/rust#146590, as well as Zulip discussion: +// +// https://rust-lang.zulipchat.com/#narrow/channel/513289-t-patterns/topic/Question.20about.20patterns.20and.20moves/with/558638455 +// +// Whether pattern matching performs a discriminant read shouldn't depend on whether +// you explicitly write down an uninhabited branch, or leave it implicit. + +enum Emp { } + +enum Foo { + Bar(A), + Qux(Emp), +} + +fn test1(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + } + + match thefoo { + Foo::Bar((_, a)) => { } + } +} + +fn test2(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + Foo::Qux(_) => { } + } + match thefoo { //~ ERROR: use of partially moved value: `thefoo` + Foo::Bar((_, a)) => { } + Foo::Qux(_) => { } + } +} + +fn test3(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + Foo::Qux(_) => { } + } + match thefoo { + Foo::Bar((_, a)) => { } + } +} + +fn main() {} diff --git a/tests/ui/match/uninhabited-granular-moves.stderr b/tests/ui/match/uninhabited-granular-moves.stderr new file mode 100644 index 000000000000..d32f935d3d55 --- /dev/null +++ b/tests/ui/match/uninhabited-granular-moves.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:30:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From ee1a6f4e88bb71d964864de1d7c935d53a3d0cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 04:22:55 +0100 Subject: [PATCH 016/182] match in closure: capture non_exhaustive even if defined in current crate --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 29 +++-------- .../match/non-exhaustive-match.rs | 16 +++--- .../match/non-exhaustive-match.stderr | 19 +++++-- .../match/partial-move-drop-order.rs | 5 ++ .../match/partial-move-drop-order.run.stdout | 2 +- .../match/partial-move.rs | 4 +- .../match/partial-move.stderr | 50 +------------------ 7 files changed, 39 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ad34994526ed..9e9b511b9b23 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -818,14 +818,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. @@ -1852,26 +1850,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/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs index 5b7259c6c2cc..f47d70b52f20 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs @@ -28,12 +28,6 @@ fn main() { let _b = || { match l1 { L1::A => () } }; //~^ ERROR: non-exhaustive patterns: `L1::B` not covered [E0004] - // l2 should not be captured as it is a non-exhaustive SingleVariant - // defined in this crate - let _c = || { match l2 { L2::C => (), _ => () } }; - let mut mut_l2 = l2; - _c(); - // E1 is not visibly uninhabited from here let (e1, e2, e3, e4) = bar(); let _d = || { match e1 {} }; @@ -42,8 +36,14 @@ fn main() { //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] let _f = || { match e2 { E2::A => (), E2::B => (), _ => () } }; - // e3 should be captured as it is a non-exhaustive SingleVariant - // defined in another crate + // non-exhaustive enums should always be captured, regardless if they + // are defined in the current crate: + let _c = || { match l2 { L2::C => (), _ => () } }; + let mut mut_l2 = l2; + //~^ ERROR: cannot move out of `l2` because it is borrowed + _c(); + + // ...or in another crate: let _g = || { match e3 { E3::C => (), _ => () } }; let mut mut_e3 = e3; //~^ ERROR: cannot move out of `e3` because it is borrowed diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 99d33b05429e..e34d1889803a 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -16,7 +16,7 @@ LL | let _b = || { match l1 { L1::A => (), L1::B => todo!() } }; | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: type `E1` is non-empty - --> $DIR/non-exhaustive-match.rs:39:25 + --> $DIR/non-exhaustive-match.rs:33:25 | LL | let _d = || { match e1 {} }; | ^^ @@ -35,7 +35,7 @@ LL ~ } }; | error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/non-exhaustive-match.rs:41:25 + --> $DIR/non-exhaustive-match.rs:35:25 | LL | let _e = || { match e2 { E2::A => (), E2::B => () } }; | ^^ pattern `_` not covered @@ -52,6 +52,19 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } }; | ++++++++++++++ +error[E0505]: cannot move out of `l2` because it is borrowed + --> $DIR/non-exhaustive-match.rs:42:22 + | +LL | let _c = || { match l2 { L2::C => (), _ => () } }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `l2` occurs here +LL | let mut mut_l2 = l2; + | ^^ move out of `l2` occurs here +LL | +LL | _c(); + | -- borrow later used here + error[E0505]: cannot move out of `e3` because it is borrowed --> $DIR/non-exhaustive-match.rs:48:22 | @@ -65,7 +78,7 @@ LL | LL | _g(); | -- borrow later used here -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0004, E0505. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs index 1c178bd3f684..348d558dd980 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs @@ -1,3 +1,8 @@ +// Make sure that #[non_exhaustive] cannot cause drop order to depend on which +// crate the code is in. +// +// See rust-lang/rust#147722 +// //@ edition:2021 //@ run-pass //@ check-run-results diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout index e0d83dd99549..3fa346d87b07 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout @@ -12,8 +12,8 @@ dropping b non exhaustive: before assign -dropping a after assign +dropping a dropping b external non exhaustive: diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs index 62d1b362cb83..7bd435bd1856 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs @@ -78,10 +78,9 @@ pub fn test_two_variants(x: TwoVariants) -> impl FnOnce() { } } -// ...and single-variant, non-exhaustive enums *should* behave as if they had multiple variants +// ...and single-variant, non-exhaustive enums behave as if they had multiple variants pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { || { - //~^ ERROR: closure may outlive the current function, but it borrows `x.0` match x { NonExhaustive::A(a, b) => { drop((a, b)); @@ -94,7 +93,6 @@ pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { // (again, wildcard branch or not) pub fn test_non_exhaustive2(x: NonExhaustive) -> impl FnOnce() { || { - //~^ ERROR: closure may outlive the current function, but it borrows `x.0` match x { NonExhaustive::A(a, b) => { drop((a, b)); diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr index 36adcc6717ed..09f9adf95d5b 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr @@ -70,54 +70,6 @@ help: to force the closure to take ownership of `x.0` (and any other referenced LL | move || { | ++++ -error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function - --> $DIR/partial-move.rs:83:5 - | -LL | || { - | ^^ may outlive borrowed value `x.0` -LL | -LL | match x { - | - `x.0` is borrowed here - | -note: closure is returned here - --> $DIR/partial-move.rs:83:5 - | -LL | / || { -LL | | -LL | | match x { -LL | | NonExhaustive::A(a, b) => { -... | -LL | | } - | |_____^ -help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword - | -LL | move || { - | ++++ - -error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function - --> $DIR/partial-move.rs:96:5 - | -LL | || { - | ^^ may outlive borrowed value `x.0` -LL | -LL | match x { - | - `x.0` is borrowed here - | -note: closure is returned here - --> $DIR/partial-move.rs:96:5 - | -LL | / || { -LL | | -LL | | match x { -LL | | NonExhaustive::A(a, b) => { -... | -LL | | } - | |_____^ -help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword - | -LL | move || { - | ++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0373`. From af302a67fdc508cfd08ee22facb96bcf0e5bf831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 19:34:37 +0100 Subject: [PATCH 017/182] discriminant reads: make semantics independent of module/crate --- .../src/builder/matches/match_pair.rs | 20 +++----- .../fail/match/all_variants_uninhabited.rs | 25 ++++++++++ .../match/all_variants_uninhabited.stderr | 13 +++++ .../{ => match}/closures/deref-in-pattern.rs | 0 .../closures/deref-in-pattern.stderr | 2 +- .../{ => match}/closures/partial-pattern.rs | 0 .../closures/partial-pattern.stderr | 2 +- .../closures/uninhabited-variant1.rs} | 0 .../closures/uninhabited-variant1.stderr} | 6 +-- .../match/closures/uninhabited-variant2.rs | 32 ++++++++++++ .../closures/uninhabited-variant2.stderr | 18 +++++++ .../fail/match/only_inhabited_variant.rs | 21 ++++++++ .../fail/match/only_inhabited_variant.stderr | 13 +++++ .../miri/tests/fail/match/single_variant.rs | 31 ++++++++++++ .../tests/fail/match/single_variant.stderr | 13 +++++ .../tests/fail/match/single_variant_uninit.rs | 36 +++++++++++++ .../fail/match/single_variant_uninit.stderr | 18 +++++++ .../enum/enum-transparent-extract.rs | 4 ++ ...atterns.opt1.SimplifyCfg-initial.after.mir | 10 ++-- ...atterns.opt2.SimplifyCfg-initial.after.mir | 15 ++++++ ...atterns.opt3.SimplifyCfg-initial.after.mir | 17 ++++--- ...ng.identity.JumpThreading.panic-abort.diff | 19 +++++-- ...g.identity.JumpThreading.panic-unwind.diff | 19 +++++-- ...map_via_question_mark.PreCodegen.after.mir | 50 +++++++++++-------- ...e_const_switch.identity.JumpThreading.diff | 15 ++++-- ...ch.UnreachablePropagation.panic-abort.diff | 12 +++-- ...h.UnreachablePropagation.panic-unwind.diff | 12 +++-- tests/mir-opt/unreachable.rs | 2 +- ....UnreachableEnumBranching.panic-abort.diff | 28 +++++------ ...UnreachableEnumBranching.panic-unwind.diff | 28 +++++------ tests/ui/match/borrowck-uninhabited.rs | 2 + tests/ui/match/borrowck-uninhabited.stderr | 13 ++++- tests/ui/match/uninhabited-granular-moves.rs | 4 +- .../match/uninhabited-granular-moves.stderr | 32 +++++++++++- .../borrowck-exhaustive.rs | 12 ----- .../borrowck-non-exhaustive.rs | 12 +++++ .../borrowck-non-exhaustive.stderr | 15 +++++- 37 files changed, 455 insertions(+), 116 deletions(-) create mode 100644 src/tools/miri/tests/fail/match/all_variants_uninhabited.rs create mode 100644 src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr rename src/tools/miri/tests/fail/{ => match}/closures/deref-in-pattern.rs (100%) rename src/tools/miri/tests/fail/{ => match}/closures/deref-in-pattern.stderr (91%) rename src/tools/miri/tests/fail/{ => match}/closures/partial-pattern.rs (100%) rename src/tools/miri/tests/fail/{ => match}/closures/partial-pattern.stderr (92%) rename src/tools/miri/tests/fail/{closures/uninhabited-variant.rs => match/closures/uninhabited-variant1.rs} (100%) rename src/tools/miri/tests/fail/{closures/uninhabited-variant.stderr => match/closures/uninhabited-variant1.stderr} (74%) create mode 100644 src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs create mode 100644 src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr create mode 100644 src/tools/miri/tests/fail/match/only_inhabited_variant.rs create mode 100644 src/tools/miri/tests/fail/match/only_inhabited_variant.stderr create mode 100644 src/tools/miri/tests/fail/match/single_variant.rs create mode 100644 src/tools/miri/tests/fail/match/single_variant.stderr create mode 100644 src/tools/miri/tests/fail/match/single_variant_uninit.rs create mode 100644 src/tools/miri/tests/fail/match/single_variant_uninit.stderr 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 8cee3ff27e8f..07af66127ef9 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -295,22 +295,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/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs new file mode 100644 index 000000000000..e7ca45579d84 --- /dev/null +++ b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs @@ -0,0 +1,25 @@ +#![allow(deref_nullptr)] + +enum Never {} + +fn main() { + unsafe { + match *std::ptr::null::>() { + //~^ ERROR: read discriminant of an uninhabited enum variant + Ok(_) => { + lol(); + } + Err(_) => { + wut(); + } + } + } +} + +fn lol() { + println!("lol"); +} + +fn wut() { + println!("wut"); +} diff --git a/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr b/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr new file mode 100644 index 000000000000..90809219340b --- /dev/null +++ b/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/all_variants_uninhabited.rs:LL:CC + | +LL | match *std::ptr::null::>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.rs b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/deref-in-pattern.rs rename to src/tools/miri/tests/fail/match/closures/deref-in-pattern.rs diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr similarity index 91% rename from src/tools/miri/tests/fail/closures/deref-in-pattern.stderr rename to src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr index fae2d286c487..cbb74df5de77 100644 --- a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr +++ b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) - --> tests/fail/closures/deref-in-pattern.rs:LL:CC + --> tests/fail/match/closures/deref-in-pattern.rs:LL:CC | LL | let _ = || { | _____________^ diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.rs b/src/tools/miri/tests/fail/match/closures/partial-pattern.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/partial-pattern.rs rename to src/tools/miri/tests/fail/match/closures/partial-pattern.rs diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr similarity index 92% rename from src/tools/miri/tests/fail/closures/partial-pattern.stderr rename to src/tools/miri/tests/fail/match/closures/partial-pattern.stderr index 8dea4d4d8c64..b8ca04559e23 100644 --- a/src/tools/miri/tests/fail/closures/partial-pattern.stderr +++ b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) - --> tests/fail/closures/partial-pattern.rs:LL:CC + --> tests/fail/match/closures/partial-pattern.rs:LL:CC | LL | let _ = || { | _____________^ diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.rs b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/uninhabited-variant.rs rename to src/tools/miri/tests/fail/match/closures/uninhabited-variant1.rs diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr similarity index 74% rename from src/tools/miri/tests/fail/closures/uninhabited-variant.stderr rename to src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr index aea878660115..1a10a5b24d25 100644 --- a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: read discriminant of an uninhabited enum variant - --> tests/fail/closures/uninhabited-variant.rs:LL:CC + --> tests/fail/match/closures/uninhabited-variant1.rs:LL:CC | LL | match r { | ^ Undefined Behavior occurred here @@ -8,9 +8,9 @@ LL | match r { = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: stack backtrace: 0: main::{closure#0} - at tests/fail/closures/uninhabited-variant.rs:LL:CC + at tests/fail/match/closures/uninhabited-variant1.rs:LL:CC 1: main - at tests/fail/closures/uninhabited-variant.rs:LL:CC + at tests/fail/match/closures/uninhabited-variant1.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs new file mode 100644 index 000000000000..ed68e357fbd5 --- /dev/null +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs @@ -0,0 +1,32 @@ +// Motivated by rust-lang/rust#138961, this shows how invalid discriminants interact with +// closure captures. +// +// Test case with only one inhabited variant, for which rustc used to not emit +// a discriminant read in the first place. See: rust-lang/miri#4778 +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1(!), // 1 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 1u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + let f = || { + // After rust-lang/rust#138961, constructing the closure performs a reborrow of r. + // Nevertheless, the discriminant is only actually inspected when the closure + // is called. + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1(_) => {} + } + }; + + f(); +} diff --git a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr new file mode 100644 index 000000000000..611e0435ef0e --- /dev/null +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + | +LL | match r { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: stack backtrace: + 0: main::{closure#0} + at tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + 1: main + at tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/only_inhabited_variant.rs b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs new file mode 100644 index 000000000000..30a7350d2b66 --- /dev/null +++ b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs @@ -0,0 +1,21 @@ +// rust-lang/miri#4778 +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1(!), // 1 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 1u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1(_) => {} + } +} diff --git a/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr b/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr new file mode 100644 index 000000000000..8ca362f902d3 --- /dev/null +++ b/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/only_inhabited_variant.rs:LL:CC + | +LL | match r { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/single_variant.rs b/src/tools/miri/tests/fail/match/single_variant.rs new file mode 100644 index 000000000000..dcef6d461a2c --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant.rs @@ -0,0 +1,31 @@ +// Ideally, this would be UB regardless of #[non_exhaustive]. For now, +// at least the semantics don't depend on the crate you're in. +// +// See: rust-lang/rust#147722 +#![allow(dead_code)] + +#[repr(u8)] +enum Exhaustive { + A(u8) = 42, +} + +#[repr(u8)] +#[non_exhaustive] +enum NonExhaustive { + A(u8) = 42, +} + +fn main() { + unsafe { + let x: &[u8; 2] = &[21, 37]; + let y: &Exhaustive = std::mem::transmute(x); + match y { + Exhaustive::A(_) => {}, + } + + let y: &NonExhaustive = std::mem::transmute(x); + match y { //~ ERROR: enum value has invalid tag + NonExhaustive::A(_) => {}, + } + } +} diff --git a/src/tools/miri/tests/fail/match/single_variant.stderr b/src/tools/miri/tests/fail/match/single_variant.stderr new file mode 100644 index 000000000000..7467e27ff791 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: enum value has invalid tag: 0x15 + --> tests/fail/match/single_variant.rs:LL:CC + | +LL | match y { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/single_variant_uninit.rs b/src/tools/miri/tests/fail/match/single_variant_uninit.rs new file mode 100644 index 000000000000..51e8bc57c837 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant_uninit.rs @@ -0,0 +1,36 @@ +// Ideally, this would be UB regardless of #[non_exhaustive]. For now, +// at least the semantics don't depend on the crate you're in. +// +// See: rust-lang/rust#147722 +#![allow(dead_code)] +#![allow(unreachable_patterns)] + +#[repr(u8)] +enum Exhaustive { + A(u8) = 0, +} + +#[repr(u8)] +#[non_exhaustive] +enum NonExhaustive { + A(u8) = 0, +} + +use std::mem::MaybeUninit; + +fn main() { + let buffer: [MaybeUninit; 2] = [MaybeUninit::uninit(), MaybeUninit::new(0u8)]; + let exh: *const Exhaustive = (&raw const buffer).cast(); + let nexh: *const NonExhaustive = (&raw const buffer).cast(); + unsafe { + match *exh { + Exhaustive::A(ref _val) => {} + _ => {} + } + + match *nexh { //~ ERROR: memory is uninitialized + NonExhaustive::A(ref _val) => {} + _ => {} + } + } +} diff --git a/src/tools/miri/tests/fail/match/single_variant_uninit.stderr b/src/tools/miri/tests/fail/match/single_variant_uninit.stderr new file mode 100644 index 000000000000..fa8e9babae60 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant_uninit.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: reading memory at ALLOC[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + --> tests/fail/match/single_variant_uninit.rs:LL:CC + | +LL | match *nexh { + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +Uninitialized memory occurred at ALLOC[0x0..0x1], in this allocation: +ALLOC (stack variable, size: 2, align: 1) { + __ 00 │ ░. +} + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/tests/codegen-llvm/enum/enum-transparent-extract.rs b/tests/codegen-llvm/enum/enum-transparent-extract.rs index 1435e6ec8022..1a05b236abfb 100644 --- a/tests/codegen-llvm/enum/enum-transparent-extract.rs +++ b/tests/codegen-llvm/enum/enum-transparent-extract.rs @@ -11,6 +11,8 @@ pub enum Never {} pub fn make_unmake_result_never(x: i32) -> i32 { // CHECK-LABEL: define i32 @make_unmake_result_never(i32{{( signext)?}} %x) // CHECK: start: + // CHECK-NEXT: br label %[[next:bb.*]] + // CHECK: [[next]]: // CHECK-NEXT: ret i32 %x let y: Result = Ok(x); @@ -22,6 +24,8 @@ pub fn make_unmake_result_never(x: i32) -> i32 { pub fn extract_control_flow_never(x: ControlFlow<&str, Never>) -> &str { // CHECK-LABEL: define { ptr, i64 } @extract_control_flow_never(ptr align 1 %x.0, i64 %x.1) // CHECK: start: + // CHECK-NEXT: br label %[[next:bb.*]] + // CHECK: [[next]]: // CHECK-NEXT: %[[P0:.+]] = insertvalue { ptr, i64 } poison, ptr %x.0, 0 // CHECK-NEXT: %[[P1:.+]] = insertvalue { ptr, i64 } %[[P0]], i64 %x.1, 1 // CHECK-NEXT: ret { ptr, i64 } %[[P1]] diff --git a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir index bba4d9c0149a..78356a90743a 100644 --- a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir @@ -13,17 +13,17 @@ fn opt1(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); - falseEdge -> [real: bb4, imaginary: bb1]; + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; } bb1: { - _2 = discriminant((*_1)); - switchInt(move _2) -> [1: bb3, otherwise: bb2]; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb2: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; + falseEdge -> [real: bb4, imaginary: bb3]; } bb3: { diff --git a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir index fc0769d6f7dc..979fbb2860dc 100644 --- a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir @@ -11,10 +11,25 @@ fn opt2(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb2: { StorageLive(_3); _3 = &(((*_1) as Ok).0: u32); _0 = &(*_3); StorageDead(_3); return; } + + bb3: { + FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); + unreachable; + } } diff --git a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir index 86347db4d92e..93ebe600b3ff 100644 --- a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir @@ -12,19 +12,24 @@ fn opt3(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); _2 = discriminant((*_1)); - switchInt(move _2) -> [1: bb2, otherwise: bb1]; + switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; } bb1: { - StorageLive(_3); - _3 = &(((*_1) as Ok).0: u32); - _0 = &(*_3); - StorageDead(_3); - return; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb2: { FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); unreachable; } + + bb3: { + StorageLive(_3); + _3 = &(((*_1) as Ok).0: u32); + _0 = &(*_3); + StorageDead(_3); + return; + } } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index 97b8d484194f..9630f4001494 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -16,8 +16,10 @@ debug residual => _6; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _14: i32; - let mut _15: i32; + let mut _14: isize; + let _15: i32; + let mut _16: i32; + let mut _17: bool; scope 9 { scope 10 (inlined >::from) { } @@ -74,10 +76,17 @@ StorageLive(_8); _8 = copy _6; StorageLive(_14); - _14 = move ((_8 as Err).0: i32); StorageLive(_15); - _15 = move _14; - _0 = Result::::Err(move _15); + StorageLive(_17); + _14 = discriminant(_8); + _17 = Eq(copy _14, const 1_isize); + assume(move _17); + _15 = move ((_8 as Err).0: i32); + StorageLive(_16); + _16 = move _15; + _0 = Result::::Err(move _16); + StorageDead(_16); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_8); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index 97b8d484194f..9630f4001494 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -16,8 +16,10 @@ debug residual => _6; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _14: i32; - let mut _15: i32; + let mut _14: isize; + let _15: i32; + let mut _16: i32; + let mut _17: bool; scope 9 { scope 10 (inlined >::from) { } @@ -74,10 +76,17 @@ StorageLive(_8); _8 = copy _6; StorageLive(_14); - _14 = move ((_8 as Err).0: i32); StorageLive(_15); - _15 = move _14; - _0 = Result::::Err(move _15); + StorageLive(_17); + _14 = discriminant(_8); + _17 = Eq(copy _14, const 1_isize); + assume(move _17); + _15 = move ((_8 as Err).0: i32); + StorageLive(_16); + _16 = move _15; + _0 = Result::::Err(move _16); + StorageDead(_16); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir index b921b96966b2..ef7ccfa5bddf 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir @@ -3,56 +3,66 @@ fn map_via_question_mark(_1: Option) -> Option { debug x => _1; let mut _0: std::option::Option; - let mut _4: std::ops::ControlFlow, i32>; - let _5: i32; - let mut _6: i32; + let mut _4: std::option::Option; + let mut _7: std::ops::ControlFlow, i32>; + let _8: i32; + let mut _9: i32; scope 1 { debug residual => const Option::::None; scope 2 { scope 7 (inlined as FromResidual>>::from_residual) { + let mut _3: isize; + let mut _5: bool; } } } scope 3 { - debug val => _5; + debug val => _8; scope 4 { } } scope 5 (inlined as Try>::branch) { let mut _2: isize; - let _3: i32; + let _6: i32; scope 6 { } } bb0: { - StorageLive(_6); - StorageLive(_4); + StorageLive(_9); + StorageLive(_7); StorageLive(_2); - StorageLive(_3); + StorageLive(_6); _2 = discriminant(_1); switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } bb1: { - StorageDead(_3); - StorageDead(_2); - _0 = const Option::::None; StorageDead(_6); - StorageDead(_4); + StorageDead(_2); + StorageLive(_3); + StorageLive(_5); + _3 = discriminant(_4); + _5 = Eq(copy _3, const 0_isize); + assume(move _5); + _0 = const Option::::None; + StorageDead(_5); + StorageDead(_3); + StorageDead(_9); + StorageDead(_7); goto -> bb3; } bb2: { - _3 = copy ((_1 as Some).0: i32); - _4 = ControlFlow::, i32>::Continue(copy _3); - StorageDead(_3); - StorageDead(_2); - _5 = copy ((_4 as Continue).0: i32); - _6 = Add(copy _5, const 1_i32); - _0 = Option::::Some(move _6); + _6 = copy ((_1 as Some).0: i32); + _7 = ControlFlow::, i32>::Continue(copy _6); StorageDead(_6); - StorageDead(_4); + StorageDead(_2); + _8 = copy ((_7 as Continue).0: i32); + _9 = Add(copy _8, const 1_i32); + _0 = Option::::Some(move _9); + StorageDead(_9); + StorageDead(_7); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index 34f451fc698c..10ad4ec75414 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -12,7 +12,9 @@ debug residual => _4; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _10: i32; + let mut _10: isize; + let _11: i32; + let mut _12: bool; scope 9 { scope 10 (inlined >::from) { } @@ -58,8 +60,15 @@ bb3: { _4 = copy ((_2 as Break).0: std::result::Result); - _10 = copy ((_4 as Err).0: i32); - _0 = Result::::Err(copy _10); + StorageLive(_10); + StorageLive(_12); + _10 = discriminant(_4); + _12 = Eq(copy _10, const 1_isize); + assume(move _12); + _11 = copy ((_4 as Err).0: i32); + _0 = Result::::Err(copy _11); + StorageDead(_12); + StorageDead(_10); StorageDead(_2); return; } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff index 17ddce0cdf8d..8c3b8ad9b66a 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff @@ -19,19 +19,23 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(copy _2, const 1_isize); +- switchInt(move _2) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ _5 = Eq(copy _2, const 0_isize); + assume(move _5); -+ goto -> bb2; ++ goto -> bb3; } bb2: { + unreachable; + } + + bb3: { _0 = const (); StorageDead(_1); return; } - bb3: { + bb4: { - StorageLive(_3); - _3 = move ((_1 as Some).0: Empty); - StorageLive(_4); diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff index 2f78092f5bd2..98f2a0a692ff 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff @@ -19,19 +19,23 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(copy _2, const 1_isize); +- switchInt(move _2) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ _5 = Eq(copy _2, const 0_isize); + assume(move _5); -+ goto -> bb2; ++ goto -> bb3; } bb2: { + unreachable; + } + + bb3: { _0 = const (); StorageDead(_1); return; } - bb3: { + bb4: { - StorageLive(_3); - _3 = move ((_1 as Some).0: Empty); - StorageLive(_4); diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index afab1291fc3d..97cd15b107c1 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -45,7 +45,7 @@ fn as_match() { // CHECK: bb0: { // CHECK: {{_.*}} = empty() // CHECK: bb1: { - // CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize); + // CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize); // CHECK-NEXT: assume(move [[eq]]); // CHECK-NEXT: goto -> [[return:bb.*]]; // CHECK: [[return]]: { diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff index c24bd7e7446d..befee026d6cb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; +- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb4; + goto -> bb5; } - bb2: { + bb3: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb4; + goto -> bb5; } bb4: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb5: { StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb5: { -+ unreachable; } } diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff index c24bd7e7446d..befee026d6cb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; +- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb4; + goto -> bb5; } - bb2: { + bb3: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb4; + goto -> bb5; } bb4: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb5: { StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb5: { -+ unreachable; } } diff --git a/tests/ui/match/borrowck-uninhabited.rs b/tests/ui/match/borrowck-uninhabited.rs index 93838ede2793..34f5e323a91e 100644 --- a/tests/ui/match/borrowck-uninhabited.rs +++ b/tests/ui/match/borrowck-uninhabited.rs @@ -17,9 +17,11 @@ fn both_inhabited(x: &mut Result) { }; } +// this used to be accepted, even though it shouldn't fn ref_uninhabited(x: &mut Result) { match x { &mut Ok(ref mut y) => match x { + //~^ ERROR: cannot use `*x` because it was mutably borrowed &mut Err(ref mut z) => { let _y = y; let _z = z; diff --git a/tests/ui/match/borrowck-uninhabited.stderr b/tests/ui/match/borrowck-uninhabited.stderr index ee3b814da9f4..4bbe6ecea16b 100644 --- a/tests/ui/match/borrowck-uninhabited.stderr +++ b/tests/ui/match/borrowck-uninhabited.stderr @@ -9,6 +9,17 @@ LL | &mut Ok(ref mut y) => match x { LL | let _y = y; | - borrow later used here -error: aborting due to 1 previous error +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/borrowck-uninhabited.rs:23:37 + | +LL | &mut Ok(ref mut y) => match x { + | --------- ^ use of borrowed `x.0` + | | + | `x.0` is borrowed here +... +LL | let _y = y; + | - borrow later used here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/match/uninhabited-granular-moves.rs b/tests/ui/match/uninhabited-granular-moves.rs index 9d04fcb3259e..f836aedbebc7 100644 --- a/tests/ui/match/uninhabited-granular-moves.rs +++ b/tests/ui/match/uninhabited-granular-moves.rs @@ -17,7 +17,7 @@ fn test1(thefoo: Foo<(Box, Box)>) { Foo::Bar((a, _)) => { } } - match thefoo { + match thefoo { //~ ERROR: use of partially moved value: `thefoo` Foo::Bar((_, a)) => { } } } @@ -38,7 +38,7 @@ fn test3(thefoo: Foo<(Box, Box)>) { Foo::Bar((a, _)) => { } Foo::Qux(_) => { } } - match thefoo { + match thefoo { //~ ERROR: use of partially moved value: `thefoo` Foo::Bar((_, a)) => { } } } diff --git a/tests/ui/match/uninhabited-granular-moves.stderr b/tests/ui/match/uninhabited-granular-moves.stderr index d32f935d3d55..e3a66db526d4 100644 --- a/tests/ui/match/uninhabited-granular-moves.stderr +++ b/tests/ui/match/uninhabited-granular-moves.stderr @@ -1,3 +1,18 @@ +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:20:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + error[E0382]: use of partially moved value: `thefoo` --> $DIR/uninhabited-granular-moves.rs:30:11 | @@ -13,6 +28,21 @@ help: borrow this binding in the pattern to avoid moving the value LL | Foo::Bar((ref a, _)) => { } | +++ -error: aborting due to 1 previous error +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:41:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs index b2ebab382bd9..2e40819d69ad 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs @@ -14,11 +14,6 @@ enum Local { Variant(u32), } -#[non_exhaustive] -enum LocalNonExhaustive { - Variant(u32), -} - fn main() { let mut x = ExhaustiveMonovariant::Variant(1); let y = &mut x; @@ -34,11 +29,4 @@ fn main() { _ => {}, } drop(y); - let mut x = LocalNonExhaustive::Variant(1); - let y = &mut x; - match x { - LocalNonExhaustive::Variant(_) => {}, - _ => {}, - } - drop(y); } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs index d616f5e5e89a..a6a369e92a6c 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs @@ -6,6 +6,11 @@ extern crate monovariants; use monovariants::NonExhaustiveMonovariant; +#[non_exhaustive] +enum LocalNonExhaustive { + Variant(u32), +} + fn main() { let mut x = NonExhaustiveMonovariant::Variant(1); let y = &mut x; @@ -15,4 +20,11 @@ fn main() { _ => {}, } drop(y); + let mut x = LocalNonExhaustive::Variant(1); + let y = &mut x; + match x { //~ ERROR cannot use `x` because it was mutably borrowed + LocalNonExhaustive::Variant(_) => {}, + _ => {}, + } + drop(y); } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr index 70f5b2b84d86..d6225adc95cb 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -1,5 +1,5 @@ error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/borrowck-non-exhaustive.rs:12:11 + --> $DIR/borrowck-non-exhaustive.rs:17:11 | LL | let y = &mut x; | ------ `x` is borrowed here @@ -9,6 +9,17 @@ LL | match x { LL | drop(y); | - borrow later used here -error: aborting due to 1 previous error +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-non-exhaustive.rs:25:11 + | +LL | let y = &mut x; + | ------ `x` is borrowed here +LL | match x { + | ^ use of borrowed `x` +... +LL | drop(y); + | - borrow later used here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0503`. From 3e789ed57663cac867309eb4d9e1f14094b02900 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 16:38:10 +0100 Subject: [PATCH 018/182] Stop cloning old `llvmint` repositories to generate intrinsics --- src/intrinsic/archs.rs | 1424 +--------------------------------- src/intrinsic/llvm.rs | 2 + src/intrinsic/old_archs.rs | 1384 +++++++++++++++++++++++++++++++++ tools/generate_intrinsics.py | 50 +- 4 files changed, 1420 insertions(+), 1440 deletions(-) create mode 100644 src/intrinsic/old_archs.rs diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 43e7c352c34a..89a6cf7f3d6e 100644 --- a/src/intrinsic/archs.rs +++ b/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 { @@ -537,8 +503,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 +559,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 +609,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 +912,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 +1342,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 +1512,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 +2102,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 +2603,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 +2614,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,8 +4832,6 @@ 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", @@ -4925,10 +4845,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "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", "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", @@ -4938,17 +4855,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "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 +4921,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 +5006,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", @@ -5219,7 +5122,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 +5152,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 +5174,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 +5198,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 +5214,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 +5254,33 @@ 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.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 +5298,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 +5563,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 +6002,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 +6116,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 { @@ -7902,10 +7662,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 +7680,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", @@ -7965,22 +7714,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "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 +7998,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 +8016,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 +8042,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 +8051,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 +8075,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 +8089,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 +8128,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 +8138,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 +8152,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 +8162,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 +8173,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 +8191,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 +8214,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 +8262,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 +8298,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 +8330,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 +8343,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 +8355,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 +8369,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 +8378,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 +8406,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 +8422,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 +8430,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 +8438,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 +8665,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 +8685,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 +8709,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 +8722,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 +8729,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 +8757,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 +8775,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 +8797,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,41 +8817,15 @@ 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", @@ -10232,11 +8855,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,8 +8869,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", @@ -10330,8 +8946,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 +8989,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 +9021,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 +9050,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/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index e3d189c95ced..72fc72d118b7 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1604,5 +1604,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/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs new file mode 100644 index 000000000000..3a59707b2ebe --- /dev/null +++ b/src/intrinsic/old_archs.rs @@ -0,0 +1,1384 @@ +// 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.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", + "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/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 767082c23cce..56b425cdb0cd 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -147,14 +147,12 @@ def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics): all_intrinsics[entry[0]] = entry[1] -def update_intrinsics(llvm_path, llvmint, llvmint2): +def update_intrinsics(llvm_path): 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. @@ -173,13 +171,17 @@ 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 @@ -199,7 +201,13 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): 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,14 +218,6 @@ 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( @@ -227,17 +227,7 @@ def main(): branch="main", sub_paths=["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) if __name__ == "__main__": From 3dc60d0bf14638cbc2dcaf70e720c6f417608365 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 16:48:14 +0100 Subject: [PATCH 019/182] Simplify intrinsics translation generation script --- tools/generate_intrinsics.py | 150 ++++++++--------------------------- 1 file changed, 33 insertions(+), 117 deletions(-) diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 56b425cdb0cd..539032340777 100644 --- a/tools/generate_intrinsics.py +++ b/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,119 +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) - -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] + return intrinsics def update_intrinsics(llvm_path): - intrinsics_llvm = {} - intrinsics_llvmint = {} - all_intrinsics = {} - - extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm) - - 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) + intrinsics = extract_intrinsics_from_llvm(llvm_path) archs = [arch for arch in intrinsics] archs.sort() @@ -187,15 +101,13 @@ match arch {""") 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])) @@ -224,11 +136,15 @@ def main(): "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/"], ) 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()) From c848b28a5d20b512e7edcd03da5ba616fabf0a8d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 17:05:01 +0100 Subject: [PATCH 020/182] Ignore `src/intrinsic/old_archs.rs` for typo checks --- .cspell.json | 1 + _typos.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 388ccce2b091..556432d69a41 100644 --- a/.cspell.json +++ b/.cspell.json @@ -18,6 +18,7 @@ ], "ignorePaths": [ "src/intrinsic/archs.rs", + "src/intrinsic/old_archs.rs", "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ diff --git a/_typos.toml b/_typos.toml index 4a6a506a981a..c4918b114621 100644 --- a/_typos.toml +++ b/_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"] From 4f59819c26c72f86baa98a2805d411cd5b665759 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jan 2026 17:46:34 +0100 Subject: [PATCH 021/182] Regenerate intrinsics --- src/intrinsic/archs.rs | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 89a6cf7f3d6e..3c1698df6dec 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,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", @@ -414,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", @@ -4836,19 +4838,24 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "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", + "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.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", @@ -5050,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", @@ -5061,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", @@ -5274,6 +5289,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_pm1", "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_pm2", "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_pm3", + "read.ptx.sreg.pm4" => "__nvvm_read_ptx_sreg_pm4", "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_smid", "read.ptx.sreg.tid.w" => "__nvvm_read_ptx_sreg_tid_w", "read.ptx.sreg.tid.x" => "__nvvm_read_ptx_sreg_tid_x", @@ -6370,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" => { @@ -6377,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}"), } } @@ -7711,8 +7729,6 @@ 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.vpermilvar.pd" => "__builtin_ia32_vpermilvarpd", "avx.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256", @@ -8829,10 +8845,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "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", @@ -8869,10 +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", - "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", @@ -8881,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", @@ -8920,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", From 2177aa9ac736b0c16c8ad73230508fcb273b980e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jan 2026 18:09:37 +0100 Subject: [PATCH 022/182] Manually include intrinsic conversion that is not present in LLVM files --- src/intrinsic/old_archs.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 3a59707b2ebe..8d3e3487b5cb 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -242,6 +242,8 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "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", @@ -1352,6 +1354,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "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", From ccdda582a84a2985a90374cb8720b0084b4c9408 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 16 Jan 2026 22:53:37 +0100 Subject: [PATCH 023/182] clean-up --- clippy_lints/src/methods/str_split.rs | 6 ++++-- tests/ui/str_split.fixed | 2 -- tests/ui/str_split.rs | 2 -- tests/ui/str_split.stderr | 20 ++++++++++---------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/methods/str_split.rs b/clippy_lints/src/methods/str_split.rs index 479064a0671e..9644b2c774b5 100644 --- a/clippy_lints/src/methods/str_split.rs +++ b/clippy_lints/src/methods/str_split.rs @@ -19,8 +19,10 @@ pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &' && cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str() && !is_const_evaluatable(cx, trim_recv) && let ExprKind::Lit(split_lit) = split_arg.kind - && (matches!(split_lit.node, LitKind::Char('\n')) - || matches!(split_lit.node, LitKind::Str(sym::LF | sym::CRLF, _))) + && matches!( + split_lit.node, + LitKind::Char('\n') | LitKind::Str(sym::LF | sym::CRLF, _) + ) { let mut app = Applicability::MaybeIncorrect; span_lint_and_sugg( diff --git a/tests/ui/str_split.fixed b/tests/ui/str_split.fixed index 6aca5051c570..c93d4d4f818d 100644 --- a/tests/ui/str_split.fixed +++ b/tests/ui/str_split.fixed @@ -1,7 +1,5 @@ #![warn(clippy::str_split_at_newline)] -#![allow(clippy::needless_lifetimes)] -use core::str::Split; use std::ops::Deref; struct NotStr<'a> { diff --git a/tests/ui/str_split.rs b/tests/ui/str_split.rs index 11e9862da14b..5792ce04ec33 100644 --- a/tests/ui/str_split.rs +++ b/tests/ui/str_split.rs @@ -1,7 +1,5 @@ #![warn(clippy::str_split_at_newline)] -#![allow(clippy::needless_lifetimes)] -use core::str::Split; use std::ops::Deref; struct NotStr<'a> { diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr index c4eca81004c5..40202c8ac47a 100644 --- a/tests/ui/str_split.stderr +++ b/tests/ui/str_split.stderr @@ -1,5 +1,5 @@ error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:60:13 + --> tests/ui/str_split.rs:58:13 | LL | let _ = s1.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` @@ -8,55 +8,55 @@ LL | let _ = s1.trim().split('\n'); = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:63:13 + --> tests/ui/str_split.rs:61:13 | LL | let _ = s1.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:65:13 + --> tests/ui/str_split.rs:63:13 | LL | let _ = s1.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:69:13 + --> tests/ui/str_split.rs:67:13 | LL | let _ = s2.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:72:13 + --> tests/ui/str_split.rs:70:13 | LL | let _ = s2.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:74:13 + --> tests/ui/str_split.rs:72:13 | LL | let _ = s2.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:79:13 + --> tests/ui/str_split.rs:77:13 | LL | let _ = s3.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:82:13 + --> tests/ui/str_split.rs:80:13 | LL | let _ = s3.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:84:13 + --> tests/ui/str_split.rs:82:13 | LL | let _ = s3.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:88:13 + --> tests/ui/str_split.rs:86:13 | LL | let _ = make_str!(s1).trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()` From f11abba6415b5d7bd82c92196e8cfea61a192abe Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 19 Jan 2026 00:42:38 +0100 Subject: [PATCH 024/182] add `simd_splat` intrinsic --- src/intrinsic/simd.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 39b4bb3ebefa..0606639d1731 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -121,6 +121,35 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate())); } + if name == sym::simd_splat { + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + + require!( + args[0].layout.ty == out_ty, + InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: out_ty, + vector_type: ret_ty, + } + ); + + let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type"); + let elem_ty = vec_ty.get_element_type(); + + // Cast pointer type to usize (GCC does not support pointer SIMD vectors). + let scalar = args[0].immediate(); + let scalar = if scalar.get_type().unqualified() != elem_ty.unqualified() { + bx.ptrtoint(scalar, elem_ty) + } else { + scalar + }; + + let elements = vec![scalar; out_len as usize]; + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements)); + } + // every intrinsic below takes a SIMD vector as its first argument require_simd!( args[0].layout.ty, From e0b87e4dd53c028e2db49fd8dc64e2f56d3548f8 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 19 Jan 2026 15:44:11 +0100 Subject: [PATCH 025/182] `simd_splat`: custom error in gcc backend for invalid element type --- src/intrinsic/simd.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 0606639d1731..eab067a02b7b 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -121,9 +121,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate())); } + #[cfg(feature = "master")] if name == sym::simd_splat { - require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); - let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn); require!( args[0].layout.ty == out_ty, @@ -139,11 +139,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let elem_ty = vec_ty.get_element_type(); // Cast pointer type to usize (GCC does not support pointer SIMD vectors). - let scalar = args[0].immediate(); - let scalar = if scalar.get_type().unqualified() != elem_ty.unqualified() { - bx.ptrtoint(scalar, elem_ty) + let value = args[0]; + let scalar = if value.layout.ty.is_numeric() { + value.immediate() + } else if value.layout.ty.is_raw_ptr() { + bx.ptrtoint(value.immediate(), elem_ty) } else { - scalar + return_error!(InvalidMonomorphization::UnsupportedOperation { + span, + name, + in_ty: ret_ty, + in_elem: value.layout.ty + }); }; let elements = vec![scalar; out_len as usize]; From ca5a25496fea0f9ece6440c1d23cd63b1c0e7e50 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 15:48:35 -0600 Subject: [PATCH 026/182] rustdoc: change getVar signature This has two advantages: * removes a bunch of @ts-expect-error * typos of var names will cause type errors instead of runtime errors --- src/librustdoc/html/static/js/main.js | 3 --- src/librustdoc/html/static/js/rustdoc.d.ts | 12 ++++++++++++ src/librustdoc/html/static/js/storage.js | 10 +++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f438fe173810..28d3522e47e8 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -231,7 +231,6 @@ function preLoadCss(cssUrl) { // When loading settings.html as a standalone page, the equivalent HTML is // generated in context.rs. setTimeout(() => { - // @ts-expect-error const themes = getVar("themes").split(","); for (const theme of themes) { // if there are no themes, do nothing @@ -415,12 +414,10 @@ function preLoadCss(cssUrl) { } window.StringdexOnload.push(() => { loadScript( - // @ts-expect-error getVar("static-root-path") + getVar("search-js"), sendSearchForm, ); }); - // @ts-expect-error loadScript(getVar("static-root-path") + getVar("stringdex-js"), sendSearchForm); loadScript(resourcePath("search.index/root", ".js"), sendSearchForm); } diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 60df4fc10b8c..f53c98b9672d 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -576,4 +576,16 @@ declare namespace rustdoc { "typeNameIdOfHof": number, "typeNameIdOfNever": number, }; + + type VarName = "name" + | "root-path" + | "static-root-path" + | "current-crate" + | "themes" + | "resource-suffix" + | "rustdoc-version" + | "channel" + | "search-js" + | "stringdex-js" + | "settings-js"; } diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 40ab8be03c93..2d544eaa237a 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -199,12 +199,16 @@ function getCurrentValue(name) { * Get a value from the rustdoc-vars div, which is used to convey data from * Rust to the JS. If there is no such element, return null. * - * @param {string} name - * @returns {string|null} + * @param {rustdoc.VarName} name + * @returns {string} */ function getVar(name) { const el = document.querySelector("head > meta[name='rustdoc-vars']"); - return el ? el.getAttribute("data-" + name) : null; + const v = el ? el.getAttribute("data-" + name) : null; + if (v !== null) { + return v; + } + throw `rustdoc var "${name}" is missing`; } /** From b7ba80d2ad2d94e81e67e2063f33962aaa6aa760 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 15:53:50 -0600 Subject: [PATCH 027/182] rustdoc(storage.js): add comment explaining use of @ts-ignore --- src/librustdoc/html/static/js/storage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 2d544eaa237a..e722d8573783 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -298,6 +298,8 @@ const updateTheme = (function() { return updateTheme; })(); +// typescript thinks we're forgetting to call window.matchMedia, +// but we're checking browser support of media queries. // @ts-ignore if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { // update the preferred dark theme if the user is already using a dark theme From 760d8868f045433d67a3c5e01754682da08f9e78 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:00:46 -0600 Subject: [PATCH 028/182] rustdoc(main.js): use instanceof instead of tagName where applicable --- src/librustdoc/html/static/js/main.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 28d3522e47e8..4b37ae1f4296 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -619,8 +619,7 @@ function preLoadCss(cssUrl) { */ function openParentDetails(elem) { while (elem) { - if (elem.tagName === "DETAILS") { - // @ts-expect-error + if (elem instanceof HTMLDetailsElement) { elem.open = true; } elem = elem.parentElement; @@ -656,10 +655,8 @@ function preLoadCss(cssUrl) { } if (document.activeElement && - document.activeElement.tagName === "INPUT" && - // @ts-expect-error + document.activeElement instanceof HTMLInputElement && document.activeElement.type !== "checkbox" && - // @ts-expect-error document.activeElement.type !== "radio") { switch (getVirtualKey(ev)) { case "Escape": From 38d7b5309236c5a2898a378217455ad71f4b3aa9 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:09:38 -0600 Subject: [PATCH 029/182] rustdoc(main.js): use nonnull to clear up type errors --- src/librustdoc/html/static/js/main.js | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 4b37ae1f4296..447aa1e02a4c 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -963,19 +963,19 @@ function preLoadCss(cssUrl) { const selfPath = script ? script.getAttribute("data-self-path") : null; // These sidebar blocks need filled in, too. - const mainContent = document.querySelector("#main-content"); - const sidebarSection = document.querySelector(".sidebar section"); + const mainContent = nonnull(document.querySelector("#main-content")); + const sidebarSection = nonnull(document.querySelector(".sidebar section")); let methods = document.querySelector(".sidebar .block.method"); let associatedTypes = document.querySelector(".sidebar .block.associatedtype"); let associatedConstants = document.querySelector(".sidebar .block.associatedconstant"); let sidebarTraitList = document.querySelector(".sidebar .block.trait-implementation"); - // @ts-expect-error - for (const impList of imp[window.currentCrate]) { + for (const impList of imp[nonnull(window.currentCrate)]) { const types = impList.slice(2); const text = impList[0]; const isTrait = impList[1] !== 0; const traitName = impList[1]; + // @ts-expect-error if (types.indexOf(selfPath) === -1) { continue; } @@ -999,33 +999,26 @@ function preLoadCss(cssUrl) { h.appendChild(link); trait_implementations = outputList; trait_implementations_header = outputListHeader; - // @ts-expect-error sidebarSection.appendChild(h); sidebarTraitList = document.createElement("ul"); sidebarTraitList.className = "block trait-implementation"; - // @ts-expect-error sidebarSection.appendChild(sidebarTraitList); - // @ts-expect-error mainContent.appendChild(outputListHeader); - // @ts-expect-error mainContent.appendChild(outputList); } else { implementations = outputList; if (trait_implementations) { - // @ts-expect-error mainContent.insertBefore(outputListHeader, trait_implementations_header); - // @ts-expect-error mainContent.insertBefore(outputList, trait_implementations_header); } else { - const mainContent = document.querySelector("#main-content"); - // @ts-expect-error + const mainContent = nonnull(document.querySelector("#main-content")); mainContent.appendChild(outputListHeader); - // @ts-expect-error mainContent.appendChild(outputList); } } } const template = document.createElement("template"); + // @ts-expect-error template.innerHTML = text; onEachLazy(template.content.querySelectorAll("a"), elem => { @@ -1065,8 +1058,8 @@ function preLoadCss(cssUrl) { if (isTrait) { const li = document.createElement("li"); const a = document.createElement("a"); + a.href = `#${nonnull(template.content.querySelector(".impl")).id}`; // @ts-expect-error - a.href = `#${template.content.querySelector(".impl").id}`; a.textContent = traitName; li.appendChild(a); // @ts-expect-error @@ -1093,14 +1086,10 @@ function preLoadCss(cssUrl) { const insertionReference = methods || sidebarTraitList; if (insertionReference) { const insertionReferenceH = insertionReference.previousElementSibling; - // @ts-expect-error sidebarSection.insertBefore(blockHeader, insertionReferenceH); - // @ts-expect-error sidebarSection.insertBefore(block, insertionReferenceH); } else { - // @ts-expect-error sidebarSection.appendChild(blockHeader); - // @ts-expect-error sidebarSection.appendChild(block); } if (hasClass(item, "associatedtype")) { From 3b4de4b21d93e349d83b5cb59b98cb832c764746 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:44:05 -0600 Subject: [PATCH 030/182] rustdoc: make TypeImpls more specific. --- src/librustdoc/html/static/js/main.js | 1 - src/librustdoc/html/static/js/rustdoc.d.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 447aa1e02a4c..eca1bd366d4b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1018,7 +1018,6 @@ function preLoadCss(cssUrl) { } } const template = document.createElement("template"); - // @ts-expect-error template.innerHTML = text; onEachLazy(template.content.querySelectorAll("a"), elem => { diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index f53c98b9672d..a7dfaa61bfec 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -524,7 +524,8 @@ declare namespace rustdoc { } type TypeImpls = { - [cratename: string]: Array> + /* [text, traitName (0 if not a trait), ...types] */ + [cratename: string]: Array<[string, string|0, ...string[]]> } /** From 519c0d9d433debe17a877e6ee46e9d81fc603763 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 17:07:31 -0600 Subject: [PATCH 031/182] rustdoc: remove redundant mainContent variable --- src/librustdoc/html/static/js/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index eca1bd366d4b..a26683e2e9bb 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1011,7 +1011,6 @@ function preLoadCss(cssUrl) { mainContent.insertBefore(outputListHeader, trait_implementations_header); mainContent.insertBefore(outputList, trait_implementations_header); } else { - const mainContent = nonnull(document.querySelector("#main-content")); mainContent.appendChild(outputListHeader); mainContent.appendChild(outputList); } From 012c4603b720f9d0a402d6ca2620006abcce2acb Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 27 Dec 2025 17:17:54 +0100 Subject: [PATCH 032/182] `c_variadic`: use `Clone` instead of LLVM `va_copy` --- src/intrinsic/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 36ea76cbc51a..553e4d3d2fe0 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -391,9 +391,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::breakpoint => { unimplemented!(); } - sym::va_copy => { - unimplemented!(); - } sym::va_arg => { unimplemented!(); } From 19bfad06939cea13de4729b448f8a2aa0c10abde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 6 Jan 2026 23:40:21 +0100 Subject: [PATCH 033/182] Introduce `AssocTag::descr` & refactor in the vicinity --- clippy_utils/src/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a90d64e972c1..c1be4acc7068 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -1226,7 +1226,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n .associated_items(did) .filter_by_name_unhygienic(method_name) .next() - .filter(|item| item.as_tag() == AssocTag::Fn) + .filter(|item| item.tag() == AssocTag::Fn) }) } else { None From 454842a8d3320e3e7d4efa36164ef9468a4c0d90 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 12 Dec 2025 13:23:48 +0100 Subject: [PATCH 034/182] update `dbg!` clippy lint --- clippy_lints/src/dbg_macro.rs | 80 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 152516baf734..9197870cb695 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; +use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext, sym}; @@ -90,33 +90,27 @@ impl LateLintPass<'_> for DbgMacro { (macro_call.span, String::from("()")) } }, - // dbg!(1) - ExprKind::Match(val, ..) => ( - macro_call.span, - snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) - .to_string(), - ), - // dbg!(2, 3) - ExprKind::Tup( - [ - Expr { - kind: ExprKind::Match(first, ..), - .. - }, - .., - Expr { - kind: ExprKind::Match(last, ..), - .. - }, - ], - ) => { - let snippet = snippet_with_applicability( - cx, - first.span.source_callsite().to(last.span.source_callsite()), - "..", - &mut applicability, - ); - (macro_call.span, format!("({snippet})")) + ExprKind::Match(first, arms, _) => { + let vals = collect_vals(first, arms); + let suggestion = match vals.as_slice() { + // dbg!(1) => 1 + &[val] => { + snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) + .to_string() + } + // dbg!(2, 3) => (2, 3) + &[first, .., last] => { + let snippet = snippet_with_applicability( + cx, + first.span.source_callsite().to(last.span.source_callsite()), + "..", + &mut applicability, + ); + format!("({snippet})") + } + _ => unreachable!(), + }; + (macro_call.span, suggestion) }, _ => unreachable!(), }; @@ -169,3 +163,33 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option { macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } + +/// Extracts all value expressions from the `match`-tree generated by `dbg!`. +/// +/// E.g. from +/// ```rust, ignore +/// match 1 { +/// tmp_1 => match 2 { +/// tmp_2 => { +/// /* printing */ +/// (tmp_1, tmp_2) +/// } +/// } +/// } +/// ``` +/// this extracts `1` and `2`. +fn collect_vals<'hir>(first: &'hir Expr<'hir>, mut arms: &'hir [Arm<'hir>]) -> Vec<&'hir Expr<'hir>> { + let mut vals = vec![first]; + loop { + let [arm] = arms else { unreachable!("dbg! macro expansion only has single-arm matches") }; + + match is_async_move_desugar(arm.body).unwrap_or(arm.body).peel_drop_temps().kind { + ExprKind::Block(..) => return vals, + ExprKind::Match(val, a, _) => { + vals.push(val); + arms = a; + } + _ => unreachable!("dbg! macro expansion only results in block or match expressions"), + } + } +} From e8c449dfbd2687eedf4a850b7e4e22460163c1ea Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 19 Jan 2026 10:33:40 +0100 Subject: [PATCH 035/182] Move assert_matches to planned stable path --- clippy_utils/src/ty/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a90d64e972c1..53ad6675ab07 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -29,7 +29,10 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Obligation, ObligationCause}; +#[cfg(bootstrap)] use std::assert_matches::debug_assert_matches; +#[cfg(not(bootstrap))] +use std::debug_assert_matches; use std::collections::hash_map::Entry; use std::{iter, mem}; From 76a536c5901dbe8b5a805f96cd6f4f89cfec3ce3 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 22 Jan 2026 00:17:38 +0100 Subject: [PATCH 036/182] test: remove `unwrap.rs` The file is testing `unwrap_used`, but that's already covered by the `unwrap_expect_used.rs` test file --- tests/ui/unwrap.rs | 22 ---------------------- tests/ui/unwrap.stderr | 31 ------------------------------- 2 files changed, 53 deletions(-) delete mode 100644 tests/ui/unwrap.rs delete mode 100644 tests/ui/unwrap.stderr diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs deleted file mode 100644 index 3191b396f99b..000000000000 --- a/tests/ui/unwrap.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![warn(clippy::unwrap_used)] -#![allow(clippy::unnecessary_literal_unwrap)] - -fn unwrap_option() { - let opt = Some(0); - let _ = opt.unwrap(); - //~^ unwrap_used -} - -fn unwrap_result() { - let res: Result = Ok(0); - let _ = res.unwrap(); - //~^ unwrap_used - - let _ = res.unwrap_err(); - //~^ unwrap_used -} - -fn main() { - unwrap_option(); - unwrap_result(); -} diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr deleted file mode 100644 index c242541a6bd7..000000000000 --- a/tests/ui/unwrap.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error: used `unwrap()` on an `Option` value - --> tests/ui/unwrap.rs:6:13 - | -LL | let _ = opt.unwrap(); - | ^^^^^^^^^^^^ - | - = note: if this value is `None`, it will panic - = help: consider using `expect()` to provide a better panic message - = note: `-D clippy::unwrap-used` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` - -error: used `unwrap()` on a `Result` value - --> tests/ui/unwrap.rs:12:13 - | -LL | let _ = res.unwrap(); - | ^^^^^^^^^^^^ - | - = note: if this value is an `Err`, it will panic - = help: consider using `expect()` to provide a better panic message - -error: used `unwrap_err()` on a `Result` value - --> tests/ui/unwrap.rs:15:13 - | -LL | let _ = res.unwrap_err(); - | ^^^^^^^^^^^^^^^^ - | - = note: if this value is an `Ok`, it will panic - = help: consider using `expect_err()` to provide a better panic message - -error: aborting due to 3 previous errors - From a0d33e07b058c19092f23f0e2dd6606608d0d591 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 20 Jan 2026 21:04:54 -0500 Subject: [PATCH 037/182] Bump stage0 --- clippy_lints/src/lib.rs | 1 - clippy_utils/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ae236ac25de7..a5e5ecb5fa19 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(bootstrap, feature(array_windows))] #![feature(box_patterns)] #![feature(macro_metavar_expr_concat)] #![feature(f128)] diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9b6a9937b8ac..7e3b1ccd224e 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -5,7 +5,6 @@ #![feature(rustc_private)] #![feature(assert_matches)] #![feature(unwrap_infallible)] -#![cfg_attr(bootstrap, feature(array_windows))] #![recursion_limit = "512"] #![allow( clippy::missing_errors_doc, From 977eddef3f3293008f4a734cdf3a61deabceb15f Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 22 Jan 2026 17:10:24 +0100 Subject: [PATCH 038/182] Merge commit '54482290b5f32e6c6b57cc9e0a17153f432b0036' into clippy-subtree-update --- CHANGELOG.md | 64 +- Cargo.toml | 2 +- book/src/lint_configuration.md | 1 + clippy_config/Cargo.toml | 2 +- clippy_config/src/conf.rs | 1 + clippy_config/src/lib.rs | 5 +- clippy_dev/src/deprecate_lint.rs | 54 +- .../src/{rename_lint.rs => edit_lints.rs} | 351 +++++--- clippy_dev/src/lib.rs | 3 +- clippy_dev/src/main.rs | 42 +- clippy_dev/src/parse/cursor.rs | 16 + clippy_dev/src/serve.rs | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/attrs/mod.rs | 4 + clippy_lints/src/casts/mod.rs | 6 + clippy_lints/src/comparison_chain.rs | 4 - clippy_lints/src/declared_lints.rs | 3 + clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/doc/mod.rs | 6 + clippy_lints/src/duration_suboptimal_units.rs | 204 +++++ clippy_lints/src/floating_point_arithmetic.rs | 761 ------------------ .../floating_point_arithmetic/custom_abs.rs | 100 +++ .../src/floating_point_arithmetic/expm1.rs | 42 + .../src/floating_point_arithmetic/hypot.rs | 82 ++ .../src/floating_point_arithmetic/lib.rs | 42 + .../src/floating_point_arithmetic/ln1p.rs | 41 + .../src/floating_point_arithmetic/log_base.rs | 44 + .../floating_point_arithmetic/log_division.rs | 52 ++ .../src/floating_point_arithmetic/mod.rs | 141 ++++ .../src/floating_point_arithmetic/mul_add.rs | 94 +++ .../src/floating_point_arithmetic/powf.rs | 94 +++ .../src/floating_point_arithmetic/powi.rs | 70 ++ .../src/floating_point_arithmetic/radians.rs | 89 ++ clippy_lints/src/int_plus_one.rs | 191 +++-- clippy_lints/src/lib.rs | 12 +- clippy_lints/src/lifetimes.rs | 38 +- clippy_lints/src/loops/while_let_loop.rs | 30 +- clippy_lints/src/manual_checked_ops.rs | 170 ++++ clippy_lints/src/manual_take.rs | 114 +++ .../src/methods/manual_is_variant_and.rs | 129 +-- clippy_lints/src/methods/map_unwrap_or.rs | 249 ++++-- .../src/methods/map_unwrap_or_else.rs | 68 ++ clippy_lints/src/methods/mod.rs | 17 +- clippy_lints/src/methods/needless_collect.rs | 224 +++++- .../src/methods/option_map_unwrap_or.rs | 180 ----- .../src/methods/suspicious_to_owned.rs | 23 +- .../src/methods/unnecessary_map_or.rs | 38 +- .../src/methods/unnecessary_sort_by.rs | 376 ++++++--- clippy_lints/src/missing_trait_methods.rs | 10 +- clippy_lints/src/needless_continue.rs | 31 +- .../src/operators/arithmetic_side_effects.rs | 5 +- .../src/operators/double_comparison.rs | 12 + clippy_lints/src/redundant_test_prefix.rs | 4 + .../src/significant_drop_tightening.rs | 24 +- .../src/slow_vector_initialization.rs | 4 +- clippy_lints/src/strlen_on_c_strings.rs | 68 +- .../src/transmute/transmuting_null.rs | 12 + .../src/undocumented_unsafe_blocks.rs | 35 + clippy_lints/src/unnested_or_patterns.rs | 7 +- clippy_lints/src/useless_conversion.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- ...alls.rs => collapsible_span_lint_calls.rs} | 119 +-- clippy_lints_internal/src/lib.rs | 8 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/README.md | 2 +- clippy_utils/src/attrs.rs | 5 +- clippy_utils/src/hir_utils.rs | 44 +- clippy_utils/src/lib.rs | 14 +- clippy_utils/src/msrvs.rs | 10 +- clippy_utils/src/sym.rs | 15 + clippy_utils/src/ty/mod.rs | 19 +- declare_clippy_lint/Cargo.toml | 2 +- lintcheck/src/input.rs | 3 +- rust-toolchain.toml | 2 +- src/driver.rs | 13 +- src/main.rs | 17 +- .../collapsible_span_lint_calls.fixed | 9 + .../collapsible_span_lint_calls.rs | 29 + .../collapsible_span_lint_calls.stderr | 50 +- .../undocumented_unsafe_blocks.default.stderr | 156 ++-- ...undocumented_unsafe_blocks.disabled.stderr | 168 ++-- .../undocumented_unsafe_blocks.rs | 67 ++ tests/ui/arithmetic_side_effects.rs | 1 - tests/ui/arithmetic_side_effects.stderr | 266 +++--- tests/ui/cognitive_complexity.rs | 25 + tests/ui/cognitive_complexity.stderr | 18 +- .../entrypoint_recursion.rs | 7 +- .../entrypoint_recursion.stderr | 12 + .../no_std_main_recursion.rs | 13 + tests/ui/double_comparison.fixed | 16 + tests/ui/double_comparison.rs | 16 + tests/ui/double_comparison.stderr | 26 +- tests/ui/duration_suboptimal_units.fixed | 91 +++ tests/ui/duration_suboptimal_units.rs | 91 +++ tests/ui/duration_suboptimal_units.stderr | 152 ++++ ...duration_suboptimal_units_days_weeks.fixed | 17 + .../duration_suboptimal_units_days_weeks.rs | 17 + ...uration_suboptimal_units_days_weeks.stderr | 40 + tests/ui/extra_unused_lifetimes.rs | 32 + tests/ui/extra_unused_lifetimes.stderr | 14 +- tests/ui/if_same_then_else.rs | 84 +- tests/ui/if_same_then_else.stderr | 230 +++++- tests/ui/int_plus_one.fixed | 16 +- tests/ui/int_plus_one.rs | 16 +- tests/ui/int_plus_one.stderr | 26 +- tests/ui/manual_checked_ops.rs | 72 ++ tests/ui/manual_checked_ops.stderr | 50 ++ tests/ui/manual_take.fixed | 57 ++ tests/ui/manual_take.rs | 69 ++ tests/ui/manual_take.stderr | 53 ++ tests/ui/manual_take_nocore.rs | 37 + tests/ui/manual_take_nostd.fixed | 10 + tests/ui/manual_take_nostd.rs | 22 + tests/ui/manual_take_nostd.stderr | 54 ++ tests/ui/map_unwrap_or.rs | 8 + tests/ui/map_unwrap_or.stderr | 8 +- tests/ui/map_unwrap_or_fixable.fixed | 39 + tests/ui/map_unwrap_or_fixable.rs | 39 + tests/ui/map_unwrap_or_fixable.stderr | 90 ++- tests/ui/missing_trait_methods.rs | 7 + tests/ui/missing_trait_methods.stderr | 10 +- tests/ui/needless_collect.fixed | 76 ++ tests/ui/needless_collect.rs | 76 ++ tests/ui/needless_collect.stderr | 112 ++- tests/ui/needless_continue.rs | 35 + tests/ui/needless_lifetimes.fixed | 25 +- tests/ui/needless_lifetimes.rs | 25 +- tests/ui/significant_drop_tightening.fixed | 36 + tests/ui/significant_drop_tightening.rs | 33 + tests/ui/significant_drop_tightening.stderr | 71 +- tests/ui/strlen_on_c_strings.fixed | 61 +- tests/ui/strlen_on_c_strings.rs | 47 +- tests/ui/strlen_on_c_strings.stderr | 86 +- tests/ui/suspicious_to_owned.1.fixed | 73 ++ tests/ui/suspicious_to_owned.2.fixed | 73 ++ tests/ui/suspicious_to_owned.rs | 1 - tests/ui/suspicious_to_owned.stderr | 36 +- tests/ui/transmuting_null.rs | 11 + tests/ui/transmuting_null.stderr | 14 +- tests/ui/unnecessary_map_or.fixed | 2 +- tests/ui/unnecessary_map_or.rs | 2 +- tests/ui/unnecessary_map_or.stderr | 38 +- tests/ui/unnecessary_sort_by.fixed | 62 ++ tests/ui/unnecessary_sort_by.rs | 62 ++ tests/ui/unnecessary_sort_by.stderr | 217 ++++- tests/ui/unnecessary_sort_by_no_core.rs | 26 + tests/ui/unnecessary_sort_by_no_std.stderr | 15 +- tests/ui/while_let_loop.rs | 21 + 148 files changed, 6333 insertions(+), 2109 deletions(-) rename clippy_dev/src/{rename_lint.rs => edit_lints.rs} (52%) create mode 100644 clippy_lints/src/duration_suboptimal_units.rs delete mode 100644 clippy_lints/src/floating_point_arithmetic.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/custom_abs.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/expm1.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/hypot.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/lib.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/ln1p.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/log_base.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/log_division.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/mod.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/mul_add.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/powf.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/powi.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/radians.rs create mode 100644 clippy_lints/src/manual_checked_ops.rs create mode 100644 clippy_lints/src/manual_take.rs create mode 100644 clippy_lints/src/methods/map_unwrap_or_else.rs delete mode 100644 clippy_lints/src/methods/option_map_unwrap_or.rs rename clippy_lints_internal/src/{collapsible_calls.rs => collapsible_span_lint_calls.rs} (66%) create mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.stderr create mode 100644 tests/ui/crate_level_checks/no_std_main_recursion.rs create mode 100644 tests/ui/duration_suboptimal_units.fixed create mode 100644 tests/ui/duration_suboptimal_units.rs create mode 100644 tests/ui/duration_suboptimal_units.stderr create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.fixed create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.rs create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.stderr create mode 100644 tests/ui/manual_checked_ops.rs create mode 100644 tests/ui/manual_checked_ops.stderr create mode 100644 tests/ui/manual_take.fixed create mode 100644 tests/ui/manual_take.rs create mode 100644 tests/ui/manual_take.stderr create mode 100644 tests/ui/manual_take_nocore.rs create mode 100644 tests/ui/manual_take_nostd.fixed create mode 100644 tests/ui/manual_take_nostd.rs create mode 100644 tests/ui/manual_take_nostd.stderr create mode 100644 tests/ui/suspicious_to_owned.1.fixed create mode 100644 tests/ui/suspicious_to_owned.2.fixed create mode 100644 tests/ui/unnecessary_sort_by_no_core.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d793489be2..795eba1dfeaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,66 @@ document. ## Unreleased / Beta / In Rust Nightly -[d9fb15c...master](https://github.com/rust-lang/rust-clippy/compare/d9fb15c...master) +[92b4b68...master](https://github.com/rust-lang/rust-clippy/compare/92b4b68...master) + +## Rust 1.93 + +Current stable, released 2026-01-22 + +[View all 96 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2025-10-17T15%3A48%3A11Z..2025-11-28T19%3A22%3A54Z+base%3Amaster) + +### New Lints + +* Added [`doc_paragraphs_missing_punctuation`] to `restriction` + [#15758](https://github.com/rust-lang/rust-clippy/pull/15758) + +### Moves and Deprecations + +* Renamed [`needless_if`] to [`needless_ifs`] + [#15961](https://github.com/rust-lang/rust-clippy/pull/15961) +* Renamed [`empty_enum`] to [`empty_enums`] + [#15912](https://github.com/rust-lang/rust-clippy/pull/15912) + +### Enhancements + +* [`result_large_err`] added `large_error_ignored` configuration + [#15697](https://github.com/rust-lang/rust-clippy/pull/15697) +* [`explicit_deref_methods`] don't lint in `impl Deref(Mut)` + [#16113](https://github.com/rust-lang/rust-clippy/pull/16113) +* [`missing_docs_in_private_items`] don't lint items in bodies and automatically derived impls; + better detect when things are accessible from the crate root; lint unnameable items which are + accessible outside the crate + [#14741](https://github.com/rust-lang/rust-clippy/pull/14741) +* [`unnecessary_unwrap`] and [`panicking_unwrap`] lint field accesses + [#15949](https://github.com/rust-lang/rust-clippy/pull/15949) +* [`ok_expect`] add autofix + [#15867](https://github.com/rust-lang/rust-clippy/pull/15867) +* [`let_and_return`] disallow _any_ text between let and return + [#16006](https://github.com/rust-lang/rust-clippy/pull/16006) +* [`needless_collect`] extend to lint more cases + [#14361](https://github.com/rust-lang/rust-clippy/pull/14361) +* [`needless_doctest_main`] and [`test_attr_in_doctest`] now handle whitespace in language tags + [#15967](https://github.com/rust-lang/rust-clippy/pull/15967) +* [`search_is_some`] now fixes code spanning multiple lines + [#15902](https://github.com/rust-lang/rust-clippy/pull/15902) +* [`unnecessary_find_map`] and [`unnecessary_filter_map`] make diagnostic spans more precise + [#15929](https://github.com/rust-lang/rust-clippy/pull/15929) +* [`precedence`] warn about ambiguity when a closure is used as a method call receiver + [#14421](https://github.com/rust-lang/rust-clippy/pull/14421) +* [`match_as_ref`] suggest `as_ref` when the reference needs to be cast; improve diagnostics + [#15934](https://github.com/rust-lang/rust-clippy/pull/15934) + [#15928](https://github.com/rust-lang/rust-clippy/pull/15928) + +### False Positive Fixes + +* [`single_range_in_vec_init`] fix FP for explicit `Range` + [#16043](https://github.com/rust-lang/rust-clippy/pull/16043) +* [`mod_module_files`] fix false positive for integration tests in workspace crates + [#16048](https://github.com/rust-lang/rust-clippy/pull/16048) +* [`replace_box`] fix FP when the box is moved + [#15984](https://github.com/rust-lang/rust-clippy/pull/15984) +* [`len_zero`] fix FP on unstable methods + [#15894](https://github.com/rust-lang/rust-clippy/pull/15894) ## Rust 1.92 @@ -6406,6 +6465,7 @@ Released 2018-09-13 [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes +[`duration_suboptimal_units`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_suboptimal_units [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute [`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names @@ -6607,6 +6667,7 @@ Released 2018-09-13 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals +[`manual_checked_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_checked_ops [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp [`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains [`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_dangling_ptr @@ -6652,6 +6713,7 @@ Released 2018-09-13 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap +[`manual_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_take [`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or [`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default diff --git a/Cargo.toml b/Cargo.toml index 7379dcbb7b37..560f1e8d7fbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.94" +version = "0.1.95" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index a1c079898594..f81dd421f59b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -905,6 +905,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) * [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) * [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`manual_take`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_take) * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) * [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) * [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index a65fe7bcbda5..da5166392b4e 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.94" +version = "0.1.95" edition = "2024" publish = false diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index e1d7c1d88eb9..849d9a613d80 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -780,6 +780,7 @@ define_Conf! { manual_split_once, manual_str_repeat, manual_strip, + manual_take, manual_try_fold, map_clone, map_unwrap_or, diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index a565a21a0e77..f18272ecf5a0 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -6,10 +6,7 @@ unused_lifetimes, unused_qualifications )] -#![allow( - clippy::must_use_candidate, - clippy::missing_panics_doc, -)] +#![allow(clippy::must_use_candidate, clippy::missing_panics_doc)] #![deny(clippy::derive_deserialize_allowing_unknown)] extern crate rustc_data_structures; diff --git a/clippy_dev/src/deprecate_lint.rs b/clippy_dev/src/deprecate_lint.rs index 0401cfda7080..bee7508dabb9 100644 --- a/clippy_dev/src/deprecate_lint.rs +++ b/clippy_dev/src/deprecate_lint.rs @@ -1,4 +1,4 @@ -use crate::parse::{DeprecatedLint, Lint, ParseCx}; +use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; use crate::update_lints::generate_lint_files; use crate::utils::{UpdateMode, Version}; use std::ffi::OsStr; @@ -61,6 +61,58 @@ pub fn deprecate<'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'cx str, } } +pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { + let mut lints = cx.find_lint_decls(); + let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint) = lints.iter().find(|l| l.name == old_name) else { + eprintln!("error: failed to find lint `{old_name}`"); + return; + }; + + let old_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", old_name]); + cx.arena.alloc_str(buf) + }); + for lint in &mut renamed_lints { + if lint.new_name == old_name_prefixed { + lint.new_name = new_name; + } + } + match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { + Ok(_) => { + println!("`{old_name}` is already deprecated"); + return; + }, + Err(idx) => renamed_lints.insert( + idx, + RenamedLint { + old_name: old_name_prefixed, + new_name, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + let mod_path = { + let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module)); + if mod_path.is_dir() { + mod_path = mod_path.join("mod"); + } + + mod_path.set_extension("rs"); + mod_path + }; + + if remove_lint_declaration(old_name, &mod_path, &mut lints).unwrap_or(false) { + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{old_name}` has successfully been uplifted"); + println!("note: you must run `cargo uitest` to update the test results"); + } else { + eprintln!("error: lint not found"); + } +} + fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec>) -> io::Result { fn remove_lint(name: &str, lints: &mut Vec>) { lints.iter().position(|l| l.name == name).map(|pos| lints.remove(pos)); diff --git a/clippy_dev/src/rename_lint.rs b/clippy_dev/src/edit_lints.rs similarity index 52% rename from clippy_dev/src/rename_lint.rs rename to clippy_dev/src/edit_lints.rs index 8e30eb7ce95b..fb1c1458c50c 100644 --- a/clippy_dev/src/rename_lint.rs +++ b/clippy_dev/src/edit_lints.rs @@ -1,5 +1,5 @@ use crate::parse::cursor::{self, Capture, Cursor}; -use crate::parse::{ParseCx, RenamedLint}; +use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; use crate::update_lints::generate_lint_files; use crate::utils::{ ErrAction, FileUpdater, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists, @@ -10,6 +10,96 @@ use std::ffi::OsString; use std::fs; use std::path::Path; +/// Runs the `deprecate` command +/// +/// This does the following: +/// * Adds an entry to `deprecated_lints.rs`. +/// * Removes the lint declaration (and the entire file if applicable) +/// +/// # Panics +/// +/// If a file path could not read from or written to +pub fn deprecate<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'env str, reason: &'env str) { + let mut lints = cx.find_lint_decls(); + let (mut deprecated_lints, renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint_idx) = lints.iter().position(|l| l.name == name) else { + eprintln!("error: failed to find lint `{name}`"); + return; + }; + + let prefixed_name = cx.str_buf.with(|buf| { + buf.extend(["clippy::", name]); + cx.arena.alloc_str(buf) + }); + match deprecated_lints.binary_search_by(|x| x.name.cmp(prefixed_name)) { + Ok(_) => { + println!("`{name}` is already deprecated"); + return; + }, + Err(idx) => deprecated_lints.insert( + idx, + DeprecatedLint { + name: prefixed_name, + reason, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + remove_lint_declaration(lint_idx, &mut lints, &mut FileUpdater::default()); + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{name}` has successfully been deprecated"); + println!("note: you must run `cargo uitest` to update the test results"); +} + +pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { + let mut lints = cx.find_lint_decls(); + let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint_idx) = lints.iter().position(|l| l.name == old_name) else { + eprintln!("error: failed to find lint `{old_name}`"); + return; + }; + + let old_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", old_name]); + cx.arena.alloc_str(buf) + }); + for lint in &mut renamed_lints { + if lint.new_name == old_name_prefixed { + lint.new_name = new_name; + } + } + match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { + Ok(_) => { + println!("`{old_name}` is already deprecated"); + return; + }, + Err(idx) => renamed_lints.insert( + idx, + RenamedLint { + old_name: old_name_prefixed, + new_name, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + let mut updater = FileUpdater::default(); + let remove_mod = remove_lint_declaration(lint_idx, &mut lints, &mut updater); + let mut update_fn = uplift_update_fn(old_name, new_name, remove_mod); + for e in walk_dir_no_dot_or_target(".") { + let e = expect_action(e, ErrAction::Read, "."); + if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") { + updater.update_file(e.path(), &mut update_fn); + } + } + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{old_name}` has successfully been uplifted as `{new_name}`"); + println!("note: you must run `cargo uitest` to update the test results"); +} + /// Runs the `rename_lint` command. /// /// This does the following: @@ -25,8 +115,7 @@ use std::path::Path; /// * If either lint name has a prefix /// * If `old_name` doesn't name an existing lint. /// * If `old_name` names a deprecated or renamed lint. -#[expect(clippy::too_many_lines)] -pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str, new_name: &'cx str, uplift: bool) { +pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { let mut updater = FileUpdater::default(); let mut lints = cx.find_lint_decls(); let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); @@ -34,20 +123,15 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str let Ok(lint_idx) = lints.binary_search_by(|x| x.name.cmp(old_name)) else { panic!("could not find lint `{old_name}`"); }; - let lint = &lints[lint_idx]; let old_name_prefixed = cx.str_buf.with(|buf| { buf.extend(["clippy::", old_name]); cx.arena.alloc_str(buf) }); - let new_name_prefixed = if uplift { - new_name - } else { - cx.str_buf.with(|buf| { - buf.extend(["clippy::", new_name]); - cx.arena.alloc_str(buf) - }) - }; + let new_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", new_name]); + cx.arena.alloc_str(buf) + }); for lint in &mut renamed_lints { if lint.new_name == old_name_prefixed { @@ -71,37 +155,8 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str }, } - // Some tests are named `lint_name_suffix` which should also be renamed, - // but we can't do that if the renamed lint's name overlaps with another - // lint. e.g. renaming 'foo' to 'bar' when a lint 'foo_bar' also exists. - let change_prefixed_tests = lints.get(lint_idx + 1).is_none_or(|l| !l.name.starts_with(old_name)); - - let mut mod_edit = ModEdit::None; - if uplift { - let is_unique_mod = lints[..lint_idx].iter().any(|l| l.module == lint.module) - || lints[lint_idx + 1..].iter().any(|l| l.module == lint.module); - if is_unique_mod { - if delete_file_if_exists(lint.path.as_ref()) { - mod_edit = ModEdit::Delete; - } - } else { - updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { - let mut start = &src[..lint.declaration_range.start]; - if start.ends_with("\n\n") { - start = &start[..start.len() - 1]; - } - let mut end = &src[lint.declaration_range.end..]; - if end.starts_with("\n\n") { - end = &end[1..]; - } - dst.push_str(start); - dst.push_str(end); - UpdateStatus::Changed - }); - } - delete_test_files(old_name, change_prefixed_tests); - lints.remove(lint_idx); - } else if lints.binary_search_by(|x| x.name.cmp(new_name)).is_err() { + let mut rename_mod = false; + if lints.binary_search_by(|x| x.name.cmp(new_name)).is_err() { let lint = &mut lints[lint_idx]; if lint.module.ends_with(old_name) && lint @@ -112,7 +167,7 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str let mut new_path = lint.path.with_file_name(new_name).into_os_string(); new_path.push(".rs"); if try_rename_file(lint.path.as_ref(), new_path.as_ref()) { - mod_edit = ModEdit::Rename; + rename_mod = true; } lint.module = cx.str_buf.with(|buf| { @@ -121,7 +176,16 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str cx.arena.alloc_str(buf) }); } - rename_test_files(old_name, new_name, change_prefixed_tests); + + rename_test_files( + old_name, + new_name, + &lints[lint_idx + 1..] + .iter() + .map(|l| l.name) + .take_while(|&n| n.starts_with(old_name)) + .collect::>(), + ); lints[lint_idx].name = new_name; lints.sort_by(|lhs, rhs| lhs.name.cmp(rhs.name)); } else { @@ -130,7 +194,7 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str return; } - let mut update_fn = file_update_fn(old_name, new_name, mod_edit); + let mut update_fn = rename_update_fn(old_name, new_name, rename_mod); for e in walk_dir_no_dot_or_target(".") { let e = expect_action(e, ErrAction::Read, "."); if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") { @@ -139,67 +203,85 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str } generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); - if uplift { - println!("Uplifted `clippy::{old_name}` as `{new_name}`"); - if matches!(mod_edit, ModEdit::None) { - println!("Only the rename has been registered, the code will need to be edited manually"); - } else { - println!("All the lint's code has been deleted"); - println!("Make sure to inspect the results as some things may have been missed"); - } - } else { - println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); - println!("All code referencing the old name has been updated"); - println!("Make sure to inspect the results as some things may have been missed"); - } + println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); + println!("All code referencing the old name has been updated"); + println!("Make sure to inspect the results as some things may have been missed"); println!("note: `cargo uibless` still needs to be run to update the test results"); } -#[derive(Clone, Copy)] -enum ModEdit { - None, - Delete, - Rename, +/// Removes a lint's declaration and test files. Returns whether the module containing the +/// lint was deleted. +fn remove_lint_declaration(lint_idx: usize, lints: &mut Vec>, updater: &mut FileUpdater) -> bool { + let lint = lints.remove(lint_idx); + let delete_mod = if lints.iter().all(|l| l.module != lint.module) { + delete_file_if_exists(lint.path.as_ref()) + } else { + updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { + let mut start = &src[..lint.declaration_range.start]; + if start.ends_with("\n\n") { + start = &start[..start.len() - 1]; + } + let mut end = &src[lint.declaration_range.end..]; + if end.starts_with("\n\n") { + end = &end[1..]; + } + dst.push_str(start); + dst.push_str(end); + UpdateStatus::Changed + }); + false + }; + delete_test_files( + lint.name, + &lints[lint_idx..] + .iter() + .map(|l| l.name) + .take_while(|&n| n.starts_with(lint.name)) + .collect::>(), + ); + + delete_mod } -fn collect_ui_test_names(lint: &str, rename_prefixed: bool, dst: &mut Vec<(OsString, bool)>) { +fn collect_ui_test_names(lint: &str, ignored_prefixes: &[&str], dst: &mut Vec<(OsString, bool)>) { for e in fs::read_dir("tests/ui").expect("error reading `tests/ui`") { let e = e.expect("error reading `tests/ui`"); let name = e.file_name(); - if let Some((name_only, _)) = name.as_encoded_bytes().split_once(|&x| x == b'.') { - if name_only.starts_with(lint.as_bytes()) && (rename_prefixed || name_only.len() == lint.len()) { - dst.push((name, true)); - } - } else if name.as_encoded_bytes().starts_with(lint.as_bytes()) && (rename_prefixed || name.len() == lint.len()) + if name.as_encoded_bytes().starts_with(lint.as_bytes()) + && !ignored_prefixes + .iter() + .any(|&pre| name.as_encoded_bytes().starts_with(pre.as_bytes())) + && let Ok(ty) = e.file_type() + && (ty.is_file() || ty.is_dir()) + { + dst.push((name, ty.is_file())); + } + } +} + +fn collect_ui_toml_test_names(lint: &str, ignored_prefixes: &[&str], dst: &mut Vec<(OsString, bool)>) { + for e in fs::read_dir("tests/ui-toml").expect("error reading `tests/ui-toml`") { + let e = e.expect("error reading `tests/ui-toml`"); + let name = e.file_name(); + if name.as_encoded_bytes().starts_with(lint.as_bytes()) + && !ignored_prefixes + .iter() + .any(|&pre| name.as_encoded_bytes().starts_with(pre.as_bytes())) + && e.file_type().is_ok_and(|ty| ty.is_dir()) { dst.push((name, false)); } } } -fn collect_ui_toml_test_names(lint: &str, rename_prefixed: bool, dst: &mut Vec<(OsString, bool)>) { - if rename_prefixed { - for e in fs::read_dir("tests/ui-toml").expect("error reading `tests/ui-toml`") { - let e = e.expect("error reading `tests/ui-toml`"); - let name = e.file_name(); - if name.as_encoded_bytes().starts_with(lint.as_bytes()) && e.file_type().is_ok_and(|ty| ty.is_dir()) { - dst.push((name, false)); - } - } - } else { - dst.push((lint.into(), false)); - } -} - -/// Renames all test files for the given lint. -/// -/// If `rename_prefixed` is `true` this will also rename tests which have the lint name as a prefix. -fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { - let mut tests = Vec::new(); +/// Renames all test files for the given lint where the file name does not start with any +/// of the given prefixes. +fn rename_test_files(old_name: &str, new_name: &str, ignored_prefixes: &[&str]) { + let mut tests: Vec<(OsString, bool)> = Vec::new(); let mut old_buf = OsString::from("tests/ui/"); let mut new_buf = OsString::from("tests/ui/"); - collect_ui_test_names(old_name, rename_prefixed, &mut tests); + collect_ui_test_names(old_name, ignored_prefixes, &mut tests); for &(ref name, is_file) in &tests { old_buf.push(name); new_buf.extend([new_name.as_ref(), name.slice_encoded_bytes(old_name.len()..)]); @@ -217,7 +299,7 @@ fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { new_buf.truncate("tests/ui".len()); old_buf.push("-toml/"); new_buf.push("-toml/"); - collect_ui_toml_test_names(old_name, rename_prefixed, &mut tests); + collect_ui_toml_test_names(old_name, ignored_prefixes, &mut tests); for (name, _) in &tests { old_buf.push(name); new_buf.extend([new_name.as_ref(), name.slice_encoded_bytes(old_name.len()..)]); @@ -227,11 +309,13 @@ fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { } } -fn delete_test_files(lint: &str, rename_prefixed: bool) { +/// Deletes all test files for the given lint where the file name does not start with any +/// of the given prefixes. +fn delete_test_files(lint: &str, ignored_prefixes: &[&str]) { let mut tests = Vec::new(); let mut buf = OsString::from("tests/ui/"); - collect_ui_test_names(lint, rename_prefixed, &mut tests); + collect_ui_test_names(lint, ignored_prefixes, &mut tests); for &(ref name, is_file) in &tests { buf.push(name); if is_file { @@ -246,7 +330,7 @@ fn delete_test_files(lint: &str, rename_prefixed: bool) { buf.push("-toml/"); tests.clear(); - collect_ui_toml_test_names(lint, rename_prefixed, &mut tests); + collect_ui_toml_test_names(lint, ignored_prefixes, &mut tests); for (name, _) in &tests { buf.push(name); delete_dir_if_exists(buf.as_ref()); @@ -271,12 +355,50 @@ fn snake_to_pascal(s: &str) -> String { String::from_utf8(dst).unwrap() } -#[expect(clippy::too_many_lines)] -fn file_update_fn<'a, 'b>( +/// Creates an update function which replaces all instances of `clippy::old_name` with +/// `new_name`. +fn uplift_update_fn<'a>( old_name: &'a str, - new_name: &'b str, - mod_edit: ModEdit, -) -> impl use<'a, 'b> + FnMut(&Path, &str, &mut String) -> UpdateStatus { + new_name: &'a str, + remove_mod: bool, +) -> impl use<'a> + FnMut(&Path, &str, &mut String) -> UpdateStatus { + move |_, src, dst| { + let mut copy_pos = 0u32; + let mut changed = false; + let mut cursor = Cursor::new(src); + while let Some(ident) = cursor.find_any_ident() { + match cursor.get_text(ident) { + "mod" + if remove_mod && cursor.match_all(&[cursor::Pat::Ident(old_name), cursor::Pat::Semi], &mut []) => + { + dst.push_str(&src[copy_pos as usize..ident.pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + if src[copy_pos as usize..].starts_with('\n') { + copy_pos += 1; + } + changed = true; + }, + "clippy" if cursor.match_all(&[cursor::Pat::DoubleColon, cursor::Pat::Ident(old_name)], &mut []) => { + dst.push_str(&src[copy_pos as usize..ident.pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + changed = true; + }, + + _ => {}, + } + } + dst.push_str(&src[copy_pos as usize..]); + UpdateStatus::from_changed(changed) + } +} + +fn rename_update_fn<'a>( + old_name: &'a str, + new_name: &'a str, + rename_mod: bool, +) -> impl use<'a> + FnMut(&Path, &str, &mut String) -> UpdateStatus { let old_name_pascal = snake_to_pascal(old_name); let new_name_pascal = snake_to_pascal(new_name); let old_name_upper = old_name.to_ascii_uppercase(); @@ -307,34 +429,15 @@ fn file_update_fn<'a, 'b>( }, // mod lint_name "mod" => { - if !matches!(mod_edit, ModEdit::None) - && let Some(pos) = cursor.find_ident(old_name) - { - match mod_edit { - ModEdit::Rename => { - dst.push_str(&src[copy_pos as usize..pos as usize]); - dst.push_str(new_name); - copy_pos = cursor.pos(); - changed = true; - }, - ModEdit::Delete if cursor.match_pat(cursor::Pat::Semi) => { - let mut start = &src[copy_pos as usize..match_start as usize]; - if start.ends_with("\n\n") { - start = &start[..start.len() - 1]; - } - dst.push_str(start); - copy_pos = cursor.pos(); - if src[copy_pos as usize..].starts_with("\n\n") { - copy_pos += 1; - } - changed = true; - }, - ModEdit::Delete | ModEdit::None => {}, - } + if rename_mod && let Some(pos) = cursor.match_ident(old_name) { + dst.push_str(&src[copy_pos as usize..pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + changed = true; } }, // lint_name:: - name if matches!(mod_edit, ModEdit::Rename) && name == old_name => { + name if rename_mod && name == old_name => { let name_end = cursor.pos(); if cursor.match_pat(cursor::Pat::DoubleColon) { dst.push_str(&src[copy_pos as usize..match_start as usize]); diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index cd103908be03..69309403c8d0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -23,13 +23,12 @@ extern crate rustc_arena; extern crate rustc_driver; extern crate rustc_lexer; -pub mod deprecate_lint; pub mod dogfood; +pub mod edit_lints; pub mod fmt; pub mod lint; pub mod new_lint; pub mod release; -pub mod rename_lint; pub mod serve; pub mod setup; pub mod sync; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 392c3aabf193..8dc2290df8e4 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -4,8 +4,8 @@ use clap::{Args, Parser, Subcommand}; use clippy_dev::{ - ClippyInfo, UpdateMode, deprecate_lint, dogfood, fmt, lint, new_lint, new_parse_cx, release, rename_lint, serve, - setup, sync, update_lints, + ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, lint, new_lint, new_parse_cx, release, serve, setup, sync, + update_lints, }; use std::env; @@ -74,21 +74,14 @@ fn main() { }, DevCommand::Serve { port, lint } => serve::run(port, lint), DevCommand::Lint { path, edition, args } => lint::run(&path, &edition, args.iter()), - DevCommand::RenameLint { - old_name, - new_name, - uplift, - } => new_parse_cx(|cx| { - rename_lint::rename( - cx, - clippy.version, - &old_name, - new_name.as_ref().unwrap_or(&old_name), - uplift, - ); + DevCommand::RenameLint { old_name, new_name } => new_parse_cx(|cx| { + edit_lints::rename(cx, clippy.version, &old_name, &new_name); + }), + DevCommand::Uplift { old_name, new_name } => new_parse_cx(|cx| { + edit_lints::uplift(cx, clippy.version, &old_name, new_name.as_deref().unwrap_or(&old_name)); }), DevCommand::Deprecate { name, reason } => { - new_parse_cx(|cx| deprecate_lint::deprecate(cx, clippy.version, &name, &reason)); + new_parse_cx(|cx| edit_lints::deprecate(cx, clippy.version, &name, &reason)); }, DevCommand::Sync(SyncCommand { subcommand }) => match subcommand { SyncSubcommand::UpdateNightly => sync::update_nightly(), @@ -243,15 +236,9 @@ enum DevCommand { /// The name of the lint to rename #[arg(value_parser = lint_name)] old_name: String, - #[arg( - required_unless_present = "uplift", - value_parser = lint_name, - )] + #[arg(value_parser = lint_name)] /// The new name of the lint - new_name: Option, - #[arg(long)] - /// This lint will be uplifted into rustc - uplift: bool, + new_name: String, }, /// Deprecate the given lint Deprecate { @@ -266,6 +253,15 @@ enum DevCommand { Sync(SyncCommand), /// Manage Clippy releases Release(ReleaseCommand), + /// Marks a lint as uplifted into rustc and removes its code + Uplift { + /// The name of the lint to uplift + #[arg(value_parser = lint_name)] + old_name: String, + /// The name of the lint in rustc + #[arg(value_parser = lint_name)] + new_name: Option, + }, } #[derive(Args)] diff --git a/clippy_dev/src/parse/cursor.rs b/clippy_dev/src/parse/cursor.rs index 6dc003f326de..2c142af4883a 100644 --- a/clippy_dev/src/parse/cursor.rs +++ b/clippy_dev/src/parse/cursor.rs @@ -219,6 +219,22 @@ impl<'txt> Cursor<'txt> { } } + /// Consume the returns the position of the next non-whitespace token if it's an + /// identifier. Returns `None` otherwise. + pub fn match_ident(&mut self, s: &str) -> Option { + loop { + match self.next_token.kind { + TokenKind::Ident if s == self.peek_text() => { + let pos = self.pos; + self.step(); + return Some(pos); + }, + TokenKind::Whitespace => self.step(), + _ => return None, + } + } + } + /// Continually attempt to match the pattern on subsequent tokens until a match is /// found. Returns whether the pattern was successfully matched. /// diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index d9e018133813..b99289672420 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -54,7 +54,7 @@ pub fn run(port: u16, lint: Option) -> ! { } // Delay to avoid updating the metadata too aggressively. - thread::sleep(Duration::from_millis(1000)); + thread::sleep(Duration::from_secs(1)); } } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7a78ef32bf3c..c0804dbb0492 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.94" +version = "0.1.95" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 42c321df61c1..fa2951d91934 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -468,6 +468,10 @@ declare_clippy_lint! { /// #[ignore = "Some good reason"] /// fn test() {} /// ``` + /// + /// ### Note + /// Clippy can only lint compiled code. For this lint to trigger, you must configure `cargo clippy` + /// to include test compilation, for instance, by using flags such as `--tests` or `--all-targets`. #[clippy::version = "1.88.0"] pub IGNORE_WITHOUT_REASON, pedantic, diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 7220a8a80066..3c9ebef73f0d 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -145,6 +145,12 @@ declare_clippy_lint! { /// let _ = i32::try_from(u32::MAX).ok(); /// ``` /// + /// If the wrapping is intended, you can use: + /// ```no_run + /// let _ = u32::MAX.cast_signed(); + /// let _ = (-1i32).cast_unsigned(); + /// ``` + /// #[clippy::version = "pre 1.29.0"] pub CAST_POSSIBLE_WRAP, pedantic, diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 238ebd4a444c..a2ddf3dad7a2 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -17,10 +17,6 @@ declare_clippy_lint! { /// `if` is not guaranteed to be exhaustive and conditionals can get /// repetitive /// - /// ### Known problems - /// The match statement may be slower due to the compiler - /// not inlining the call to cmp. See issue [#5354](https://github.com/rust-lang/rust-clippy/issues/5354) - /// /// ### Example /// ```rust,ignore /// # fn a() {} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 6b68940c6423..a04d133b0d72 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -135,6 +135,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::drop_forget_ref::FORGET_NON_DROP_INFO, crate::drop_forget_ref::MEM_FORGET_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, + crate::duration_suboptimal_units::DURATION_SUBOPTIMAL_UNITS_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, crate::empty_enums::EMPTY_ENUMS_INFO, @@ -296,6 +297,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::manual_assert::MANUAL_ASSERT_INFO, crate::manual_async_fn::MANUAL_ASYNC_FN_INFO, crate::manual_bits::MANUAL_BITS_INFO, + crate::manual_checked_ops::MANUAL_CHECKED_OPS_INFO, crate::manual_clamp::MANUAL_CLAMP_INFO, crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, @@ -315,6 +317,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, + crate::manual_take::MANUAL_TAKE_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 6b8a6aec92fa..992ed320ce68 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -105,7 +105,7 @@ fn check_struct<'tcx>( if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind && let Some(PathSegment { args, .. }) = p.segments.last() { - let args = args.map(|a| a.args).unwrap_or(&[]); + let args = args.map(|a| a.args).unwrap_or_default(); // ty_args contains the generic parameters of the type declaration, while args contains the // arguments used at instantiation time. If both len are not equal, it means that some diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 2b41275ee3a4..ecf7acbd7ce6 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -692,6 +692,12 @@ declare_clippy_lint! { /// /// /// /// It was chosen by a fair dice roll. /// ``` + /// + /// ### Terminal punctuation marks + /// This lint treats these characters as end markers: '.', '?', '!', '…' and ':'. + /// + /// The colon is not exactly a terminal punctuation mark, but this is required for paragraphs that + /// introduce a table or a list for example. #[clippy::version = "1.93.0"] pub DOC_PARAGRAPHS_MISSING_PUNCTUATION, restriction, diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs new file mode 100644 index 000000000000..8140585b70d3 --- /dev/null +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -0,0 +1,204 @@ +use std::ops::ControlFlow; + +use clippy_config::Conf; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeDef; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, QPath, RustcVersion}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::ty::TyCtxt; +use rustc_session::impl_lint_pass; +use rustc_span::Symbol; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for instances where a `std::time::Duration` is constructed using a smaller time unit + /// when the value could be expressed more clearly using a larger unit. + /// + /// ### Why is this bad? + /// + /// Using a smaller unit for a duration that is evenly divisible by a larger unit reduces + /// readability. Readers have to mentally convert values, which can be error-prone and makes + /// the code less clear. + /// + /// ### Example + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::from_millis(5_000); + /// let dur = Duration::from_secs(180); + /// let dur = Duration::from_mins(10 * 60); + /// ``` + /// + /// Use instead: + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::from_secs(5); + /// let dur = Duration::from_mins(3); + /// let dur = Duration::from_hours(10); + /// ``` + #[clippy::version = "1.95.0"] + pub DURATION_SUBOPTIMAL_UNITS, + pedantic, + "constructing a `Duration` using a smaller unit when a larger unit would be more readable" +} + +impl_lint_pass!(DurationSuboptimalUnits => [DURATION_SUBOPTIMAL_UNITS]); + +pub struct DurationSuboptimalUnits { + msrv: Msrv, + units: Vec, +} + +impl DurationSuboptimalUnits { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { + // The order of the units matters, as they are walked top to bottom + let mut units = UNITS.to_vec(); + if tcx.features().enabled(sym::duration_constructors) { + units.extend(EXTENDED_UNITS); + } + Self { msrv: conf.msrv, units } + } +} + +impl LateLintPass<'_> for DurationSuboptimalUnits { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + if !expr.span.in_external_macro(cx.sess().source_map()) + // Check if a function on std::time::Duration is called + && let ExprKind::Call(func, [arg]) = expr.kind + && let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind + && cx + .typeck_results() + .node_type(func_ty.hir_id) + .is_diag_item(cx, sym::Duration) + // We intentionally don't want to evaluate referenced constants, as we don't want to + // recommend a literal value over using constants: + // + // let dur = Duration::from_secs(SIXTY); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)` + && let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt()) + && let value = u64::try_from(value).expect("All Duration::from_ constructors take a u64") + // There is no need to promote e.g. 0 seconds to 0 hours + && value != 0 + && let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value) + { + span_lint_and_then( + cx, + DURATION_SUBOPTIMAL_UNITS, + expr.span, + "constructing a `Duration` using a smaller unit when a larger unit would be more readable", + |diag| { + let suggestions = vec![ + (func_name.ident.span, promoted_constructor.to_string()), + (arg.span, promoted_value.to_string()), + ]; + diag.multipart_suggestion_verbose( + format!("try using {promoted_constructor}"), + suggestions, + Applicability::MachineApplicable, + ); + }, + ); + } + } +} + +impl DurationSuboptimalUnits { + /// Tries to promote the given constructor and value to a bigger time unit and returns the + /// promoted constructor name and value. + /// + /// Returns [`None`] in case no promotion could be done. + fn promote(&self, cx: &LateContext<'_>, constructor_name: Symbol, value: u64) -> Option<(Symbol, u64)> { + let (best_unit, best_value) = self + .units + .iter() + .skip_while(|unit| unit.constructor_name != constructor_name) + .skip(1) + .try_fold( + (constructor_name, value), + |(current_unit, current_value), bigger_unit| { + if let Some(bigger_value) = current_value.div_exact(u64::from(bigger_unit.factor)) + && bigger_unit.stable_since.is_none_or(|v| self.msrv.meets(cx, v)) + { + ControlFlow::Continue((bigger_unit.constructor_name, bigger_value)) + } else { + // We have to break early, as we can't skip versions, as they are needed to + // correctly calculate the promoted value. + ControlFlow::Break((current_unit, current_value)) + } + }, + ) + .into_value(); + (best_unit != constructor_name).then_some((best_unit, best_value)) + } +} + +#[derive(Clone, Copy)] +struct Unit { + /// Name of the constructor on [`Duration`](std::time::Duration) to construct it from the given + /// unit, e.g. [`Duration::from_secs`](std::time::Duration::from_secs) + constructor_name: Symbol, + + /// The increase factor over the previous (smaller) unit + factor: u16, + + /// In what rustc version stable support for this constructor was added. + /// We do not need to track the version stable support in const contexts was added, as the const + /// stabilization was done in an ascending order of the time unites, so it's always valid to + /// promote a const constructor. + stable_since: Option, +} + +/// Time unit constructors available on stable. The order matters! +const UNITS: [Unit; 6] = [ + Unit { + constructor_name: sym::from_nanos, + // The value doesn't matter, as there is no previous unit + factor: 0, + stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS), + }, + Unit { + constructor_name: sym::from_micros, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS), + }, + Unit { + constructor_name: sym::from_millis, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS), + }, + Unit { + constructor_name: sym::from_secs, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS), + }, + Unit { + constructor_name: sym::from_mins, + factor: 60, + stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS), + }, + Unit { + constructor_name: sym::from_hours, + factor: 60, + stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS), + }, +]; + +/// Time unit constructors behind the `duration_constructors` feature. The order matters! +const EXTENDED_UNITS: [Unit; 2] = [ + Unit { + constructor_name: sym::from_days, + factor: 24, + stable_since: None, + }, + Unit { + constructor_name: sym::from_weeks, + factor: 7, + stable_since: None, + }, +]; diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs deleted file mode 100644 index 5f022ba307ff..000000000000 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ /dev/null @@ -1,761 +0,0 @@ -use clippy_utils::consts::Constant::{F32, F64, Int}; -use clippy_utils::consts::{ConstEvalCtxt, Constant}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; -use clippy_utils::{ - eq_expr_value, get_parent_expr, has_ambiguous_literal_in_expr, higher, is_in_const_context, is_no_std_crate, - numeric_literal, peel_blocks, sugg, sym, -}; -use rustc_ast::ast; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::declare_lint_pass; -use rustc_span::SyntaxContext; -use rustc_span::source_map::Spanned; -use std::f32::consts as f32_consts; -use std::f64::consts as f64_consts; -use sugg::Sugg; - -declare_clippy_lint! { - /// ### What it does - /// Looks for floating-point expressions that - /// can be expressed using built-in methods to improve accuracy - /// at the cost of performance. - /// - /// ### Why is this bad? - /// Negatively impacts accuracy. - /// - /// ### Example - /// ```no_run - /// let a = 3f32; - /// let _ = a.powf(1.0 / 3.0); - /// let _ = (1.0 + a).ln(); - /// let _ = a.exp() - 1.0; - /// ``` - /// - /// Use instead: - /// ```no_run - /// let a = 3f32; - /// let _ = a.cbrt(); - /// let _ = a.ln_1p(); - /// let _ = a.exp_m1(); - /// ``` - #[clippy::version = "1.43.0"] - pub IMPRECISE_FLOPS, - nursery, - "usage of imprecise floating point operations" -} - -declare_clippy_lint! { - /// ### What it does - /// Looks for floating-point expressions that - /// can be expressed using built-in methods to improve both - /// accuracy and performance. - /// - /// ### Why is this bad? - /// Negatively impacts accuracy and performance. - /// - /// ### Example - /// ```no_run - /// use std::f32::consts::E; - /// - /// let a = 3f32; - /// let _ = (2f32).powf(a); - /// let _ = E.powf(a); - /// let _ = a.powf(1.0 / 2.0); - /// let _ = a.log(2.0); - /// let _ = a.log(10.0); - /// let _ = a.log(E); - /// let _ = a.powf(2.0); - /// let _ = a * 2.0 + 4.0; - /// let _ = if a < 0.0 { - /// -a - /// } else { - /// a - /// }; - /// let _ = if a < 0.0 { - /// a - /// } else { - /// -a - /// }; - /// ``` - /// - /// is better expressed as - /// - /// ```no_run - /// use std::f32::consts::E; - /// - /// let a = 3f32; - /// let _ = a.exp2(); - /// let _ = a.exp(); - /// let _ = a.sqrt(); - /// let _ = a.log2(); - /// let _ = a.log10(); - /// let _ = a.ln(); - /// let _ = a.powi(2); - /// let _ = a.mul_add(2.0, 4.0); - /// let _ = a.abs(); - /// let _ = -a.abs(); - /// ``` - #[clippy::version = "1.43.0"] - pub SUBOPTIMAL_FLOPS, - nursery, - "usage of sub-optimal floating point operations" -} - -declare_lint_pass!(FloatingPointArithmetic => [ - IMPRECISE_FLOPS, - SUBOPTIMAL_FLOPS -]); - -// Returns the specialized log method for a given base if base is constant -// and is one of 2, 10 and e -fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>, ctxt: SyntaxContext) -> Option<&'static str> { - if let Some(value) = ConstEvalCtxt::new(cx).eval_local(base, ctxt) { - if F32(2.0) == value || F64(2.0) == value { - return Some("log2"); - } else if F32(10.0) == value || F64(10.0) == value { - return Some("log10"); - } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - return Some("ln"); - } - } - - None -} - -// Adds type suffixes and parenthesis to method receivers if necessary -fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Sugg<'a> { - let mut suggestion = Sugg::hir(cx, expr, ".."); - - if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { - expr = inner_expr; - } - - if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind() - // if the expression is a float literal and it is unsuffixed then - // add a suffix so the suggestion is valid and unambiguous - && let ExprKind::Lit(lit) = &expr.kind - && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node - { - let op = format!( - "{suggestion}{}{}", - // Check for float literals without numbers following the decimal - // separator such as `2.` and adds a trailing zero - if sym.as_str().ends_with('.') { "0" } else { "" }, - float_ty.name_str() - ) - .into(); - - suggestion = match suggestion { - Sugg::MaybeParen(_) | Sugg::UnOp(UnOp::Neg, _) => Sugg::MaybeParen(op), - _ => Sugg::NonParen(op), - }; - } - - suggestion.maybe_paren() -} - -fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(method) = get_specialized_log_method(cx, &args[0], expr.span.ctxt()) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "logarithm for bases 2, 10 and e can be computed more accurately", - "consider using", - format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_paren()), - Applicability::MachineApplicable, - ); - } -} - -// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and -// suggest usage of `(x + (y - 1)).ln_1p()` instead -fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Add, .. - }, - lhs, - rhs, - ) = receiver.kind - { - let ecx = ConstEvalCtxt::new(cx); - let recv = match (ecx.eval(lhs), ecx.eval(rhs)) { - (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs, - (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs, - _ => return, - }; - - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "ln(1 + x) can be computed more accurately", - "consider using", - format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)), - Applicability::MachineApplicable, - ); - } -} - -// Returns an integer if the float constant is a whole number and it can be -// converted to an integer without loss of precision. For now we only check -// ranges [-16777215, 16777216) for type f32 as whole number floats outside -// this range are lossy and ambiguous. -#[expect(clippy::cast_possible_truncation)] -fn get_integer_from_float_constant(value: &Constant) -> Option { - match value { - F32(num) if num.fract() == 0.0 => { - if (-16_777_215.0..16_777_216.0).contains(num) { - Some(num.round() as i32) - } else { - None - } - }, - F64(num) if num.fract() == 0.0 => { - if (-2_147_483_648.0..2_147_483_648.0).contains(num) { - Some(num.round() as i32) - } else { - None - } - }, - _ => None, - } -} - -fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - // Check receiver - if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) - && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - Some("exp") - } else if F32(2.0) == value || F64(2.0) == value { - Some("exp2") - } else { - None - } - { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "exponent for bases 2 and e can be computed more accurately", - "consider using", - format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])), - Applicability::MachineApplicable, - ); - } - - // Check argument - if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { - let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { - ( - SUBOPTIMAL_FLOPS, - "square-root of a number can be computed more efficiently and accurately", - format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), - ) - } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { - ( - IMPRECISE_FLOPS, - "cube-root of a number can be computed more accurately", - format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), - ) - } else if let Some(exponent) = get_integer_from_float_constant(&value) { - ( - SUBOPTIMAL_FLOPS, - "exponentiation with integer powers can be computed more efficiently", - format!( - "{}.powi({})", - Sugg::hir(cx, receiver, "..").maybe_paren(), - numeric_literal::format(&exponent.to_string(), None, false) - ), - ) - } else { - return; - }; - - span_lint_and_sugg( - cx, - lint, - expr.span, - help, - "consider using", - suggestion, - Applicability::MachineApplicable, - ); - } -} - -fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) - && value == Int(2) - && let Some(parent) = get_parent_expr(cx, expr) - { - if let Some(grandparent) = get_parent_expr(cx, parent) - && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = grandparent.kind - && method.name == sym::sqrt - && detect_hypot(cx, receiver).is_some() - { - return; - } - - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = parent.kind - { - let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; - - // Negate expr if original code has subtraction and expr is on the right side - let maybe_neg_sugg = |expr, hir_id| { - let sugg = Sugg::hir(cx, expr, ".."); - if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { - -sugg - } else { - sugg - } - }; - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - parent.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!( - "{}.mul_add({}, {})", - Sugg::hir(cx, receiver, "..").maybe_paren(), - maybe_neg_sugg(receiver, expr.hir_id), - maybe_neg_sugg(other_addend, other_addend.hir_id), - ), - Applicability::MachineApplicable, - ); - } - } -} - -fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Add, .. - }, - add_lhs, - add_rhs, - ) = receiver.kind - { - // check if expression of the form x * x + y * y - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - lmul_lhs, - lmul_rhs, - ) = add_lhs.kind - && let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - rmul_lhs, - rmul_rhs, - ) = add_rhs.kind - && eq_expr_value(cx, lmul_lhs, lmul_rhs) - && eq_expr_value(cx, rmul_lhs, rmul_rhs) - { - return Some(format!( - "{}.hypot({})", - Sugg::hir(cx, lmul_lhs, "..").maybe_paren(), - Sugg::hir(cx, rmul_lhs, "..") - )); - } - - // check if expression of the form x.powi(2) + y.powi(2) - if let ExprKind::MethodCall(PathSegment { ident: lmethod, .. }, largs_0, [largs_1, ..], _) = &add_lhs.kind - && let ExprKind::MethodCall(PathSegment { ident: rmethod, .. }, rargs_0, [rargs_1, ..], _) = &add_rhs.kind - && lmethod.name == sym::powi - && rmethod.name == sym::powi - && let ecx = ConstEvalCtxt::new(cx) - && let Some(lvalue) = ecx.eval(largs_1) - && let Some(rvalue) = ecx.eval(rargs_1) - && Int(2) == lvalue - && Int(2) == rvalue - { - return Some(format!( - "{}.hypot({})", - Sugg::hir(cx, largs_0, "..").maybe_paren(), - Sugg::hir(cx, rargs_0, "..") - )); - } - } - - None -} - -fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { - if let Some(message) = detect_hypot(cx, receiver) { - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "hypotenuse can be computed more accurately", - "consider using", - message, - Applicability::MachineApplicable, - ); - } -} - -// TODO: Lint expressions of the form `x.exp() - y` where y > 1 -// and suggest usage of `x.exp_m1() - (y - 1)` instead -fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Sub, .. - }, - lhs, - rhs, - ) = expr.kind - && let ExprKind::MethodCall(path, self_arg, [], _) = &lhs.kind - && path.ident.name == sym::exp - && cx.typeck_results().expr_ty(lhs).is_floating_point() - && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs) - && (F32(1.0) == value || F64(1.0) == value) - && cx.typeck_results().expr_ty(self_arg).is_floating_point() - { - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "(e.pow(x) - 1) can be computed more accurately", - "consider using", - format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_paren()), - Applicability::MachineApplicable, - ); - } -} - -fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - lhs, - rhs, - ) = &expr.kind - && cx.typeck_results().expr_ty(lhs).is_floating_point() - && cx.typeck_results().expr_ty(rhs).is_floating_point() - { - return Some((lhs, rhs)); - } - - None -} - -fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = &expr.kind - { - if let Some(parent) = get_parent_expr(cx, expr) - && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind - && method.name == sym::sqrt - && detect_hypot(cx, receiver).is_some() - { - return; - } - - let maybe_neg_sugg = |expr| { - let sugg = Sugg::hir(cx, expr, ".."); - if let BinOpKind::Sub = op { -sugg } else { sugg } - }; - - let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) - && cx.typeck_results().expr_ty(rhs).is_floating_point() - { - (inner_lhs, Sugg::hir(cx, inner_rhs, ".."), maybe_neg_sugg(rhs)) - } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) - && cx.typeck_results().expr_ty(lhs).is_floating_point() - { - (inner_lhs, maybe_neg_sugg(inner_rhs), Sugg::hir(cx, lhs, "..")) - } else { - return; - }; - - // Check if any variable in the expression has an ambiguous type (could be f32 or f64) - // see: https://github.com/rust-lang/rust-clippy/issues/14897 - if (matches!(recv.kind, ExprKind::Path(_)) || matches!(recv.kind, ExprKind::Call(_, _))) - && has_ambiguous_literal_in_expr(cx, recv) - { - return; - } - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!("{}.mul_add({arg1}, {arg2})", prepare_receiver_sugg(cx, recv)), - Applicability::MachineApplicable, - ); - } -} - -/// Returns true iff expr is an expression which tests whether or not -/// test is positive or an expression which tests whether or not test -/// is nonnegative. -/// Used for check-custom-abs function below -fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { - if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { - match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), - _ => false, - } - } else { - false - } -} - -/// See [`is_testing_positive`] -fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { - if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { - match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), - _ => false, - } - } else { - false - } -} - -/// Returns true iff expr is some zero literal -fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: SyntaxContext) -> bool { - match ConstEvalCtxt::new(cx).eval_local(expr, ctxt) { - Some(Int(i)) => i == 0, - Some(F32(f)) => f == 0.0, - Some(F64(f)) => f == 0.0, - _ => false, - } -} - -/// If the two expressions are negations of each other, then it returns -/// a tuple, in which the first element is true iff expr1 is the -/// positive expressions, and the second element is the positive -/// one of the two expressions -/// If the two expressions are not negations of each other, then it -/// returns None. -fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { - if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind - && eq_expr_value(cx, expr1_negated, expr2) - { - return Some((false, expr2)); - } - if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind - && eq_expr_value(cx, expr1, expr2_negated) - { - return Some((true, expr1)); - } - None -} - -fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let Some(higher::If { - cond, - then, - r#else: Some(r#else), - }) = higher::If::hir(expr) - && let if_body_expr = peel_blocks(then) - && let else_body_expr = peel_blocks(r#else) - && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr) - { - let positive_abs_sugg = ( - "manual implementation of `abs` method", - format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), - ); - let negative_abs_sugg = ( - "manual implementation of negation of `abs` method", - format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), - ); - let sugg = if is_testing_positive(cx, cond, body) { - if if_expr_positive { - positive_abs_sugg - } else { - negative_abs_sugg - } - } else if is_testing_negative(cx, cond, body) { - if if_expr_positive { - negative_abs_sugg - } else { - positive_abs_sugg - } - } else { - return; - }; - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - sugg.0, - "try", - sugg.1, - Applicability::MachineApplicable, - ); - } -} - -fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { - if let ExprKind::MethodCall(PathSegment { ident: method_a, .. }, _, args_a, _) = expr_a.kind - && let ExprKind::MethodCall(PathSegment { ident: method_b, .. }, _, args_b, _) = expr_b.kind - { - return method_a.name == method_b.name - && args_a.len() == args_b.len() - && (matches!(method_a.name, sym::ln | sym::log2 | sym::log10) - || method_a.name == sym::log && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); - } - - false -} - -fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { - // check if expression of the form x.logN() / y.logN() - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - lhs, - rhs, - ) = &expr.kind - && are_same_base_logs(cx, lhs, rhs) - && let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind - && let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind - { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "log base can be expressed more clearly", - "consider using", - format!( - "{}.log({})", - Sugg::hir(cx, largs_self, "..").maybe_paren(), - Sugg::hir(cx, rargs_self, ".."), - ), - Applicability::MachineApplicable, - ); - } -} - -fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - div_lhs, - div_rhs, - ) = &expr.kind - && let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - mul_lhs, - mul_rhs, - ) = &div_lhs.kind - && let ecx = ConstEvalCtxt::new(cx) - && let Some(rvalue) = ecx.eval(div_rhs) - && let Some(lvalue) = ecx.eval(mul_rhs) - { - // TODO: also check for constant values near PI/180 or 180/PI - if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) - && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) - { - let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); - if let ExprKind::Lit(literal) = mul_lhs.kind - && let ast::LitKind::Float(ref value, float_type) = literal.node - && float_type == ast::LitFloatType::Unsuffixed - { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } - } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to degrees can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); - } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) - && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) - { - let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); - if let ExprKind::Lit(literal) = mul_lhs.kind - && let ast::LitKind::Float(ref value, float_type) = literal.node - && float_type == ast::LitFloatType::Unsuffixed - { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } - } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to radians can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); - } - } -} - -impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // All of these operations are currently not const and are in std. - if is_in_const_context(cx) { - return; - } - - if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind { - let recv_ty = cx.typeck_results().expr_ty(receiver); - - if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) { - match path.ident.name { - sym::ln => check_ln1p(cx, expr, receiver), - sym::log => check_log_base(cx, expr, receiver, args), - sym::powf => check_powf(cx, expr, receiver, args), - sym::powi => check_powi(cx, expr, receiver, args), - sym::sqrt => check_hypot(cx, expr, receiver), - _ => {}, - } - } - } else { - if !is_no_std_crate(cx) { - check_expm1(cx, expr); - check_mul_add(cx, expr); - check_custom_abs(cx, expr); - check_log_division(cx, expr); - } - check_radians(cx, expr); - } - } -} diff --git a/clippy_lints/src/floating_point_arithmetic/custom_abs.rs b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs new file mode 100644 index 000000000000..d12a32e15881 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs @@ -0,0 +1,100 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64, Int}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, higher, peel_blocks}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_span::SyntaxContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +/// Returns true iff expr is an expression which tests whether or not +/// test is positive or an expression which tests whether or not test +/// is nonnegative. +/// Used for check-custom-abs function below +fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), + _ => false, + } + } else { + false + } +} + +/// See [`is_testing_positive`] +fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), + _ => false, + } + } else { + false + } +} + +/// Returns true iff expr is some zero literal +fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: SyntaxContext) -> bool { + match ConstEvalCtxt::new(cx).eval_local(expr, ctxt) { + Some(Int(i)) => i == 0, + Some(F32(f)) => f == 0.0, + Some(F64(f)) => f == 0.0, + _ => false, + } +} + +/// If the two expressions are negations of each other, then it returns +/// a tuple, in which the first element is true iff expr1 is the +/// positive expressions, and the second element is the positive +/// one of the two expressions +/// If the two expressions are not negations of each other, then it +/// returns None. +fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { + if let ExprKind::Unary(UnOp::Neg, expr1_negated) = expr1.kind + && eq_expr_value(cx, expr1_negated, expr2) + { + return Some((false, expr2)); + } + if let ExprKind::Unary(UnOp::Neg, expr2_negated) = expr2.kind + && eq_expr_value(cx, expr1, expr2_negated) + { + return Some((true, expr1)); + } + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let Some(higher::If { + cond, + then, + r#else: Some(r#else), + }) = higher::If::hir(expr) + && let if_body_expr = peel_blocks(then) + && let else_body_expr = peel_blocks(r#else) + && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr) + { + let sugg_positive_abs = if is_testing_positive(cx, cond, body) { + if_expr_positive + } else if is_testing_negative(cx, cond, body) { + !if_expr_positive + } else { + return; + }; + let mut app = Applicability::MachineApplicable; + let body = Sugg::hir_with_applicability(cx, body, "_", &mut app).maybe_paren(); + let sugg = if sugg_positive_abs { + ("manual implementation of `abs` method", format!("{body}.abs()")) + } else { + #[rustfmt::skip] + ("manual implementation of negation of `abs` method", format!("-{body}.abs()")) + }; + span_lint_and_sugg(cx, SUBOPTIMAL_FLOPS, expr.span, sugg.0, "try", sugg.1, app); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/expm1.rs b/clippy_lints/src/floating_point_arithmetic/expm1.rs new file mode 100644 index 000000000000..9a4c97569308 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/expm1.rs @@ -0,0 +1,42 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +// TODO: Lint expressions of the form `x.exp() - y` where y > 1 +// and suggest usage of `x.exp_m1() - (y - 1)` instead +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, .. + }, + lhs, + rhs, + ) = expr.kind + && let ExprKind::MethodCall(path, self_arg, [], _) = lhs.kind + && path.ident.name == sym::exp + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs) + && (F32(1.0) == value || F64(1.0) == value) + && cx.typeck_results().expr_ty(self_arg).is_floating_point() + { + span_lint_and_then( + cx, + IMPRECISE_FLOPS, + expr.span, + "(e.pow(x) - 1) can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, self_arg, "_", &mut app).maybe_paren(); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.exp_m1()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/hypot.rs b/clippy_lints/src/floating_point_arithmetic/hypot.rs new file mode 100644 index 000000000000..49f8ba4bf825 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/hypot.rs @@ -0,0 +1,82 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::Int; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +pub(super) fn detect(cx: &LateContext<'_>, receiver: &Expr<'_>, app: &mut Applicability) -> Option { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + add_lhs, + add_rhs, + ) = receiver.kind + { + // check if expression of the form x * x + y * y + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lmul_lhs, + lmul_rhs, + ) = add_lhs.kind + && let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + rmul_lhs, + rmul_rhs, + ) = add_rhs.kind + && eq_expr_value(cx, lmul_lhs, lmul_rhs) + && eq_expr_value(cx, rmul_lhs, rmul_rhs) + { + return Some(format!( + "{}.hypot({})", + Sugg::hir_with_applicability(cx, lmul_lhs, "_", app).maybe_paren(), + Sugg::hir_with_applicability(cx, rmul_lhs, "_", app) + )); + } + + // check if expression of the form x.powi(2) + y.powi(2) + if let ExprKind::MethodCall(PathSegment { ident: lmethod, .. }, largs_0, [largs_1, ..], _) = add_lhs.kind + && let ExprKind::MethodCall(PathSegment { ident: rmethod, .. }, rargs_0, [rargs_1, ..], _) = add_rhs.kind + && lmethod.name == sym::powi + && rmethod.name == sym::powi + && let ecx = ConstEvalCtxt::new(cx) + && let Some(lvalue) = ecx.eval(largs_1) + && let Some(rvalue) = ecx.eval(rargs_1) + && Int(2) == lvalue + && Int(2) == rvalue + { + return Some(format!( + "{}.hypot({})", + Sugg::hir_with_applicability(cx, largs_0, "_", app).maybe_paren(), + Sugg::hir_with_applicability(cx, rargs_0, "_", app) + )); + } + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { + let mut app = Applicability::MachineApplicable; + if let Some(message) = detect(cx, receiver, &mut app) { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "hypotenuse can be computed more accurately", + "consider using", + message, + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/lib.rs b/clippy_lints/src/floating_point_arithmetic/lib.rs new file mode 100644 index 000000000000..3fa041f97802 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/lib.rs @@ -0,0 +1,42 @@ +use clippy_utils::sugg::Sugg; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty; + +// Adds type suffixes and parenthesis to method receivers if necessary +pub(super) fn prepare_receiver_sugg<'a>( + cx: &LateContext<'_>, + mut expr: &'a Expr<'a>, + app: &mut Applicability, +) -> Sugg<'a> { + let mut suggestion = Sugg::hir_with_applicability(cx, expr, "_", app); + + if let ExprKind::Unary(UnOp::Neg, inner_expr) = expr.kind { + expr = inner_expr; + } + + if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind() + // if the expression is a float literal and it is unsuffixed then + // add a suffix so the suggestion is valid and unambiguous + && let ExprKind::Lit(lit) = expr.kind + && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node + { + let op = format!( + "{suggestion}{}{}", + // Check for float literals without numbers following the decimal + // separator such as `2.` and adds a trailing zero + if sym.as_str().ends_with('.') { "0" } else { "" }, + float_ty.name_str() + ) + .into(); + + suggestion = match suggestion { + Sugg::MaybeParen(_) | Sugg::UnOp(UnOp::Neg, _) => Sugg::MaybeParen(op), + _ => Sugg::NonParen(op), + }; + } + + suggestion.maybe_paren() +} diff --git a/clippy_lints/src/floating_point_arithmetic/ln1p.rs b/clippy_lints/src/floating_point_arithmetic/ln1p.rs new file mode 100644 index 000000000000..4c9aa96b5042 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/ln1p.rs @@ -0,0 +1,41 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and +// suggest usage of `(x + (y - 1)).ln_1p()` instead +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + lhs, + rhs, + ) = receiver.kind + { + let ecx = ConstEvalCtxt::new(cx); + let recv = match (ecx.eval(lhs), ecx.eval(rhs)) { + (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs, + (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs, + _ => return, + }; + + span_lint_and_then( + cx, + IMPRECISE_FLOPS, + expr.span, + "ln(1 + x) can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = super::lib::prepare_receiver_sugg(cx, recv, &mut app); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.ln_1p()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/log_base.rs b/clippy_lints/src/floating_point_arithmetic/log_base.rs new file mode 100644 index 000000000000..4ccc784655ed --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/log_base.rs @@ -0,0 +1,44 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::SyntaxContext; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::SUBOPTIMAL_FLOPS; + +// Returns the specialized log method for a given base if base is constant +// and is one of 2, 10 and e +fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>, ctxt: SyntaxContext) -> Option<&'static str> { + if let Some(value) = ConstEvalCtxt::new(cx).eval_local(base, ctxt) { + if F32(2.0) == value || F64(2.0) == value { + return Some("log2"); + } else if F32(10.0) == value || F64(10.0) == value { + return Some("log10"); + } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + return Some("ln"); + } + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(method) = get_specialized_log_method(cx, &args[0], expr.span.ctxt()) { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "logarithm for bases 2, 10 and e can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.{method}()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/log_division.rs b/clippy_lints/src/floating_point_arithmetic/log_division.rs new file mode 100644 index 000000000000..e3419ffad72a --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/log_division.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { + if let ExprKind::MethodCall(PathSegment { ident: method_a, .. }, _, args_a, _) = expr_a.kind + && let ExprKind::MethodCall(PathSegment { ident: method_b, .. }, _, args_b, _) = expr_b.kind + { + return method_a.name == method_b.name + && args_a.len() == args_b.len() + && (matches!(method_a.name, sym::ln | sym::log2 | sym::log10) + || method_a.name == sym::log && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); + } + + false +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + // check if expression of the form x.logN() / y.logN() + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + lhs, + rhs, + ) = expr.kind + && are_same_base_logs(cx, lhs, rhs) + && let ExprKind::MethodCall(_, largs_self, ..) = lhs.kind + && let ExprKind::MethodCall(_, rargs_self, ..) = rhs.kind + { + let mut app = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "log base can be expressed more clearly", + "consider using", + format!( + "{}.log({})", + Sugg::hir_with_applicability(cx, largs_self, "_", &mut app).maybe_paren(), + Sugg::hir_with_applicability(cx, rargs_self, "_", &mut app), + ), + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/mod.rs b/clippy_lints/src/floating_point_arithmetic/mod.rs new file mode 100644 index 000000000000..edc638c96bbf --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/mod.rs @@ -0,0 +1,141 @@ +use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::{is_in_const_context, is_no_std_crate, sym}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; + +mod custom_abs; +mod expm1; +mod hypot; +mod lib; +mod ln1p; +mod log_base; +mod log_division; +mod mul_add; +mod powf; +mod powi; +mod radians; + +declare_clippy_lint! { + /// ### What it does + /// Looks for floating-point expressions that + /// can be expressed using built-in methods to improve accuracy + /// at the cost of performance. + /// + /// ### Why is this bad? + /// Negatively impacts accuracy. + /// + /// ### Example + /// ```no_run + /// let a = 3f32; + /// let _ = a.powf(1.0 / 3.0); + /// let _ = (1.0 + a).ln(); + /// let _ = a.exp() - 1.0; + /// ``` + /// + /// Use instead: + /// ```no_run + /// let a = 3f32; + /// let _ = a.cbrt(); + /// let _ = a.ln_1p(); + /// let _ = a.exp_m1(); + /// ``` + #[clippy::version = "1.43.0"] + pub IMPRECISE_FLOPS, + nursery, + "usage of imprecise floating point operations" +} + +declare_clippy_lint! { + /// ### What it does + /// Looks for floating-point expressions that + /// can be expressed using built-in methods to improve both + /// accuracy and performance. + /// + /// ### Why is this bad? + /// Negatively impacts accuracy and performance. + /// + /// ### Example + /// ```no_run + /// use std::f32::consts::E; + /// + /// let a = 3f32; + /// let _ = (2f32).powf(a); + /// let _ = E.powf(a); + /// let _ = a.powf(1.0 / 2.0); + /// let _ = a.log(2.0); + /// let _ = a.log(10.0); + /// let _ = a.log(E); + /// let _ = a.powf(2.0); + /// let _ = a * 2.0 + 4.0; + /// let _ = if a < 0.0 { + /// -a + /// } else { + /// a + /// }; + /// let _ = if a < 0.0 { + /// a + /// } else { + /// -a + /// }; + /// ``` + /// + /// is better expressed as + /// + /// ```no_run + /// use std::f32::consts::E; + /// + /// let a = 3f32; + /// let _ = a.exp2(); + /// let _ = a.exp(); + /// let _ = a.sqrt(); + /// let _ = a.log2(); + /// let _ = a.log10(); + /// let _ = a.ln(); + /// let _ = a.powi(2); + /// let _ = a.mul_add(2.0, 4.0); + /// let _ = a.abs(); + /// let _ = -a.abs(); + /// ``` + #[clippy::version = "1.43.0"] + pub SUBOPTIMAL_FLOPS, + nursery, + "usage of sub-optimal floating point operations" +} + +declare_lint_pass!(FloatingPointArithmetic => [ + IMPRECISE_FLOPS, + SUBOPTIMAL_FLOPS +]); + +impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + // All of these operations are currently not const and are in std. + if is_in_const_context(cx) { + return; + } + + if let ExprKind::MethodCall(path, receiver, args, _) = expr.kind { + let recv_ty = cx.typeck_results().expr_ty(receiver); + + if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) { + match path.ident.name { + sym::ln => ln1p::check(cx, expr, receiver), + sym::log => log_base::check(cx, expr, receiver, args), + sym::powf => powf::check(cx, expr, receiver, args), + sym::powi => powi::check(cx, expr, receiver, args), + sym::sqrt => hypot::check(cx, expr, receiver), + _ => {}, + } + } + } else { + if !is_no_std_crate(cx) { + expm1::check(cx, expr); + mul_add::check(cx, expr); + custom_abs::check(cx, expr); + log_division::check(cx, expr); + } + radians::check(cx, expr); + } + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/mul_add.rs b/clippy_lints/src/floating_point_arithmetic/mul_add.rs new file mode 100644 index 000000000000..03a9d3b05f88 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/mul_add.rs @@ -0,0 +1,94 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_parent_expr, has_ambiguous_literal_in_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lhs, + rhs, + ) = expr.kind + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { + return Some((lhs, rhs)); + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) = &expr.kind + { + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind + && method.name == sym::sqrt + // we don't care about the applicability as this is an early-return condition + && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() + { + return; + } + + let maybe_neg_sugg = |expr, app: &mut _| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); + if let BinOpKind::Sub = op { -sugg } else { sugg } + }; + + let mut app = Applicability::MachineApplicable; + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { + ( + inner_lhs, + Sugg::hir_with_applicability(cx, inner_rhs, "_", &mut app), + maybe_neg_sugg(rhs, &mut app), + ) + } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) + && cx.typeck_results().expr_ty(lhs).is_floating_point() + { + ( + inner_lhs, + maybe_neg_sugg(inner_rhs, &mut app), + Sugg::hir_with_applicability(cx, lhs, "_", &mut app), + ) + } else { + return; + }; + + // Check if any variable in the expression has an ambiguous type (could be f32 or f64) + // see: https://github.com/rust-lang/rust-clippy/issues/14897 + if (matches!(recv.kind, ExprKind::Path(_)) || matches!(recv.kind, ExprKind::Call(_, _))) + && has_ambiguous_literal_in_expr(cx, recv) + { + return; + } + + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "multiply and add expressions can be calculated more efficiently and accurately", + "consider using", + format!( + "{}.mul_add({arg1}, {arg2})", + super::lib::prepare_receiver_sugg(cx, recv, &mut app) + ), + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/powf.rs b/clippy_lints/src/floating_point_arithmetic/powf.rs new file mode 100644 index 000000000000..8e4a7388e784 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/powf.rs @@ -0,0 +1,94 @@ +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::numeric_literal; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::{IMPRECISE_FLOPS, SUBOPTIMAL_FLOPS}; + +// Returns an integer if the float constant is a whole number and it can be +// converted to an integer without loss of precision. For now we only check +// ranges [-16777215, 16777216) for type f32 as whole number floats outside +// this range are lossy and ambiguous. +#[expect(clippy::cast_possible_truncation)] +fn get_integer_from_float_constant(value: &Constant) -> Option { + match value { + F32(num) if num.fract() == 0.0 => { + if (-16_777_215.0..16_777_216.0).contains(num) { + Some(num.round() as i32) + } else { + None + } + }, + F64(num) if num.fract() == 0.0 => { + if (-2_147_483_648.0..2_147_483_648.0).contains(num) { + Some(num.round() as i32) + } else { + None + } + }, + _ => None, + } +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + // Check receiver + if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) + && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + Some("exp") + } else if F32(2.0) == value || F64(2.0) == value { + Some("exp2") + } else { + None + } + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "exponent for bases 2 and e can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = super::lib::prepare_receiver_sugg(cx, &args[0], &mut app); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.{method}()"), app); + }, + ); + } + + // Check argument + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(); + let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { + ( + SUBOPTIMAL_FLOPS, + "square-root of a number can be computed more efficiently and accurately", + format!("{recv}.sqrt()"), + ) + } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { + ( + IMPRECISE_FLOPS, + "cube-root of a number can be computed more accurately", + format!("{recv}.cbrt()"), + ) + } else if let Some(exponent) = get_integer_from_float_constant(&value) { + ( + SUBOPTIMAL_FLOPS, + "exponentiation with integer powers can be computed more efficiently", + format!( + "{recv}.powi({})", + numeric_literal::format(&exponent.to_string(), None, false) + ), + ) + } else { + return; + }; + + span_lint_and_sugg(cx, lint, expr.span, help, "consider using", suggestion, app); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/powi.rs b/clippy_lints/src/floating_point_arithmetic/powi.rs new file mode 100644 index 000000000000..a61a2a82c023 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/powi.rs @@ -0,0 +1,70 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::Int; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_parent_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) + && value == Int(2) + && let Some(parent) = get_parent_expr(cx, expr) + { + if let Some(grandparent) = get_parent_expr(cx, parent) + && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = grandparent.kind + && method.name == sym::sqrt + // we don't care about the applicability as this is an early-return condition + && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() + { + return; + } + + if let ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) = parent.kind + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + parent.span, + "multiply and add expressions can be calculated more efficiently and accurately", + |diag| { + let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; + + // Negate expr if original code has subtraction and expr is on the right side + let maybe_neg_sugg = |expr, hir_id, app: &mut _| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); + if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { + -sugg + } else { + sugg + } + }; + + let mut app = Applicability::MachineApplicable; + diag.span_suggestion( + parent.span, + "consider using", + format!( + "{}.mul_add({}, {})", + Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(), + maybe_neg_sugg(receiver, expr.hir_id, &mut app), + maybe_neg_sugg(other_addend, other_addend.hir_id, &mut app), + ), + app, + ); + }, + ); + } + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/radians.rs b/clippy_lints/src/floating_point_arithmetic/radians.rs new file mode 100644 index 000000000000..2021f00a97e8 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/radians.rs @@ -0,0 +1,89 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::SUBOPTIMAL_FLOPS; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + div_lhs, + div_rhs, + ) = expr.kind + && let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + mul_lhs, + mul_rhs, + ) = div_lhs.kind + && let ecx = ConstEvalCtxt::new(cx) + && let Some(rvalue) = ecx.eval(div_rhs) + && let Some(lvalue) = ecx.eval(mul_rhs) + { + // TODO: also check for constant values near PI/180 or 180/PI + if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) + && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to degrees can be done more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, mul_lhs, "num", &mut app); + let proposal = if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed + { + if value.as_str().ends_with('.') { + format!("{recv}0_f64.to_degrees()") + } else { + format!("{recv}_f64.to_degrees()") + } + } else { + format!("{}.to_degrees()", recv.maybe_paren()) + }; + diag.span_suggestion(expr.span, "consider using", proposal, app); + }, + ); + } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) + && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to radians can be done more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, mul_lhs, "num", &mut app); + let proposal = if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed + { + if value.as_str().ends_with('.') { + format!("{recv}0_f64.to_radians()") + } else { + format!("{recv}_f64.to_radians()") + } + } else { + format!("{}.to_radians()", recv.maybe_paren()) + }; + diag.span_suggestion(expr.span, "consider using", proposal, app); + }, + ); + } + } +} diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 67ce57de254d..f8184b30f400 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::SpanRangeExt; -use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind}; -use rustc_ast::token; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; @@ -35,132 +35,125 @@ declare_clippy_lint! { declare_lint_pass!(IntPlusOne => [INT_PLUS_ONE]); // cases: -// BinOpKind::Ge +// LeOrGe::Ge // x >= y + 1 // x - 1 >= y // -// BinOpKind::Le +// LeOrGe::Le // x + 1 <= y // x <= y - 1 #[derive(Copy, Clone)] -enum Side { - Lhs, - Rhs, +enum LeOrGe { + Le, + Ge, +} + +impl TryFrom for LeOrGe { + type Error = (); + fn try_from(value: BinOpKind) -> Result { + match value { + BinOpKind::Le => Ok(Self::Le), + BinOpKind::Ge => Ok(Self::Ge), + _ => Err(()), + } + } } impl IntPlusOne { - #[expect(clippy::cast_sign_loss)] - fn check_lit(token_lit: token::Lit, target_value: i128) -> bool { - if let Ok(LitKind::Int(value, ..)) = LitKind::from_token_lit(token_lit) { - return value == (target_value as u128); + fn is_one(expr: &Expr) -> bool { + if let ExprKind::Lit(token_lit) = expr.kind + && matches!(LitKind::from_token_lit(token_lit), Ok(LitKind::Int(Pu128(1), ..))) + { + return true; } false } - fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { - match (binop, &lhs.kind, &rhs.kind) { - // case where `x - 1 >= ...` or `-1 + x >= ...` - (BinOpKind::Ge, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) => { - match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) { - // `-1 + x` - (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => { - Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs) - }, - // `x - 1` - (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs) - }, - _ => None, - } - }, - // case where `... >= y + 1` or `... >= 1 + y` - (BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => { - match (&rhslhs.kind, &rhsrhs.kind) { - // `y + 1` and `1 + y` - (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs) - }, - (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs) - }, - _ => None, - } - }, - // case where `x + 1 <= ...` or `1 + x <= ...` - (BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => { - match (&lhslhs.kind, &lhsrhs.kind) { - // `1 + x` and `x + 1` - (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs) - }, - (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs) - }, - _ => None, - } - }, - // case where `... >= y - 1` or `... >= -1 + y` - (BinOpKind::Le, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) => { - match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) { - // `-1 + y` - (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => { - Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs) - }, - // `y - 1` - (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs) - }, - _ => None, - } - }, - _ => None, + fn is_neg_one(expr: &Expr) -> bool { + if let ExprKind::Unary(UnOp::Neg, expr) = &expr.kind { + Self::is_one(expr) + } else { + false } } - fn generate_recommendation( - cx: &EarlyContext<'_>, - binop: BinOpKind, - node: &Expr, - other_side: &Expr, - side: Side, - ) -> Option { - let binop_string = match binop { - BinOpKind::Ge => ">", - BinOpKind::Le => "<", - _ => return None, - }; - if let Some(snippet) = node.span.get_source_text(cx) - && let Some(other_side_snippet) = other_side.span.get_source_text(cx) + /// Checks whether `expr` is `x + 1` or `1 + x`, and if so, returns `x` + fn as_x_plus_one(expr: &Expr) -> Option<&Expr> { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind + && op.node == BinOpKind::Add { - let rec = match side { - Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), - Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), - }; - return rec; + if Self::is_one(rhs) { + // x + 1 + return Some(lhs); + } else if Self::is_one(lhs) { + // 1 + x + return Some(rhs); + } } None } - fn emit_warning(cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { - span_lint_and_sugg( + /// Checks whether `expr` is `x - 1` or `-1 + x`, and if so, returns `x` + fn as_x_minus_one(expr: &Expr) -> Option<&Expr> { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind { + if op.node == BinOpKind::Sub && Self::is_one(rhs) { + // x - 1 + return Some(lhs); + } else if op.node == BinOpKind::Add && Self::is_neg_one(lhs) { + // -1 + x + return Some(rhs); + } + } + None + } + + fn check_binop<'tcx>(le_or_ge: LeOrGe, lhs: &'tcx Expr, rhs: &'tcx Expr) -> Option<(&'tcx Expr, &'tcx Expr)> { + match le_or_ge { + LeOrGe::Ge => { + // case where `x - 1 >= ...` or `-1 + x >= ...` + (Self::as_x_minus_one(lhs).map(|new_lhs| (new_lhs, rhs))) + // case where `... >= y + 1` or `... >= 1 + y` + .or_else(|| Self::as_x_plus_one(rhs).map(|new_rhs| (lhs, new_rhs))) + }, + LeOrGe::Le => { + // case where `x + 1 <= ...` or `1 + x <= ...` + (Self::as_x_plus_one(lhs).map(|new_lhs| (new_lhs, rhs))) + // case where `... <= y - 1` or `... <= -1 + y` + .or_else(|| Self::as_x_minus_one(rhs).map(|new_rhs| (lhs, new_rhs))) + }, + } + } + + fn emit_warning(cx: &EarlyContext<'_>, expr: &Expr, new_lhs: &Expr, le_or_ge: LeOrGe, new_rhs: &Expr) { + span_lint_and_then( cx, INT_PLUS_ONE, - block.span, + expr.span, "unnecessary `>= y + 1` or `x - 1 >=`", - "change it to", - recommendation, - Applicability::MachineApplicable, // snippet + |diag| { + let mut app = Applicability::MachineApplicable; + let ctxt = expr.span.ctxt(); + let new_lhs = sugg::Sugg::ast(cx, new_lhs, "_", ctxt, &mut app); + let new_rhs = sugg::Sugg::ast(cx, new_rhs, "_", ctxt, &mut app); + let new_binop = match le_or_ge { + LeOrGe::Ge => BinOpKind::Gt, + LeOrGe::Le => BinOpKind::Lt, + }; + let rec = sugg::make_binop(new_binop, &new_lhs, &new_rhs); + diag.span_suggestion(expr.span, "change it to", rec, app); + }, ); } } impl EarlyLintPass for IntPlusOne { - fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { - if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind - && let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if let ExprKind::Binary(binop, lhs, rhs) = &expr.kind + && let Ok(le_or_ge) = LeOrGe::try_from(binop.node) + && let Some((new_lhs, new_rhs)) = Self::check_binop(le_or_ge, lhs, rhs) { - Self::emit_warning(cx, item, rec); + Self::emit_warning(cx, expr, new_lhs, le_or_ge, new_rhs); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a5e5ecb5fa19..40b7c3a3fc22 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,10 +1,12 @@ #![feature(box_patterns)] -#![feature(macro_metavar_expr_concat)] +#![feature(control_flow_into_value)] +#![feature(exact_div)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] +#![feature(macro_metavar_expr_concat)] #![feature(never_type)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] @@ -110,6 +112,7 @@ mod doc; mod double_parens; mod drop_forget_ref; mod duplicate_mod; +mod duration_suboptimal_units; mod else_if_without_else; mod empty_drop; mod empty_enums; @@ -195,6 +198,7 @@ mod manual_abs_diff; mod manual_assert; mod manual_async_fn; mod manual_bits; +mod manual_checked_ops; mod manual_clamp; mod manual_float_methods; mod manual_hash_one; @@ -213,6 +217,7 @@ mod manual_rotate; mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; +mod manual_take; mod map_unit_fn; mod match_result_ok; mod matches; @@ -712,7 +717,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co Box::new(|_| Box::::default()), Box::new(move |tcx| Box::new(disallowed_types::DisallowedTypes::new(tcx, conf))), Box::new(move |tcx| Box::new(missing_enforced_import_rename::ImportRename::new(tcx, conf))), - Box::new(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings)), + Box::new(move |_| Box::new(strlen_on_c_strings::StrlenOnCStrings::new(conf))), Box::new(move |_| Box::new(self_named_constructors::SelfNamedConstructors)), Box::new(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator)), Box::new(move |_| Box::new(manual_assert::ManualAssert)), @@ -854,6 +859,9 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co Box::new(|_| Box::::default()), Box::new(move |_| Box::new(manual_ilog2::ManualIlog2::new(conf))), Box::new(|_| Box::new(same_length_and_capacity::SameLengthAndCapacity)), + Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))), + Box::new(move |_| Box::new(manual_take::ManualTake::new(conf))), + Box::new(|_| Box::new(manual_checked_ops::ManualCheckedOps)), // add late passes here, used by `cargo dev new_lint` ]; store.late_passes.extend(late_lints); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 727e9b172a87..679fb983d532 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::trait_ref_of_method; +use clippy_utils::{is_from_proc_macro, trait_ref_of_method}; use itertools::Itertools; use rustc_ast::visit::{try_visit, walk_list}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; @@ -149,9 +149,12 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { .. } = item.kind { - check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv); + check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv, || { + is_from_proc_macro(cx, item) + }); } else if let ItemKind::Impl(impl_) = &item.kind && !item.span.from_expansion() + && !is_from_proc_macro(cx, item) { report_extra_impl_lifetimes(cx, impl_); } @@ -169,6 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { item.span, report_extra_lifetimes, self.msrv, + || is_from_proc_macro(cx, item), ); } } @@ -179,7 +183,17 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { TraitFn::Required(sig) => (None, Some(sig)), TraitFn::Provided(id) => (Some(id), None), }; - check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true, self.msrv); + check_fn_inner( + cx, + sig, + body, + trait_sig, + item.generics, + item.span, + true, + self.msrv, + || is_from_proc_macro(cx, item), + ); } } } @@ -194,6 +208,7 @@ fn check_fn_inner<'tcx>( span: Span, report_extra_lifetimes: bool, msrv: Msrv, + is_from_proc_macro: impl FnOnce() -> bool, ) { if span.in_external_macro(cx.sess().source_map()) || has_where_lifetimes(cx, generics) { return; @@ -245,10 +260,19 @@ fn check_fn_inner<'tcx>( } } - if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params, msrv) { - if usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span)) { - return; - } + let elidable = could_use_elision(cx, sig.decl, body, trait_sig, generics.params, msrv); + let has_elidable_lts = elidable + .as_ref() + .is_some_and(|(_, usages)| !usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span))); + + // Only check is_from_proc_macro if we're about to emit a lint (it's an expensive check) + if (has_elidable_lts || report_extra_lifetimes) && is_from_proc_macro() { + return; + } + + if let Some((elidable_lts, usages)) = elidable + && has_elidable_lts + { // async functions have usages whose spans point at the lifetime declaration which messes up // suggestions let include_suggestions = !sig.header.is_async(); diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index d4285db0abfc..e2ea24c39980 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -40,7 +40,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo let_info, Some(if_let.if_then), ); - } else if els.and_then(|x| x.expr).is_some_and(is_simple_break_expr) + } else if els.is_some_and(is_simple_break_block) && let Some((pat, _)) = let_info { could_be_while_let(cx, expr, pat, init, has_trailing_exprs, let_info, None); @@ -61,17 +61,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo } } -/// Returns `true` if expr contains a single break expression without a label or sub-expression, -/// possibly embedded in blocks. -fn is_simple_break_expr(e: &Expr<'_>) -> bool { - if let ExprKind::Block(b, _) = e.kind { - match (b.stmts, b.expr) { - ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)), - ([], Some(e)) => is_simple_break_expr(e), - _ => false, - } - } else { - matches!(e.kind, ExprKind::Break(dest, None) if dest.label.is_none()) +/// Checks if `block` contains a single unlabeled `break` expression or statement, possibly embedded +/// inside other blocks. +fn is_simple_break_block(block: &Block<'_>) -> bool { + match (block.stmts, block.expr) { + ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)), + ([], Some(e)) => is_simple_break_expr(e), + _ => false, + } +} + +/// Checks if `expr` contains a single unlabeled `break` expression or statement, possibly embedded +/// inside other blocks. +fn is_simple_break_expr(expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Block(b, _) => is_simple_break_block(b), + ExprKind::Break(dest, None) => dest.label.is_none(), + _ => false, } } diff --git a/clippy_lints/src/manual_checked_ops.rs b/clippy_lints/src/manual_checked_ops.rs new file mode 100644 index 000000000000..6327567df336 --- /dev/null +++ b/clippy_lints/src/manual_checked_ops.rs @@ -0,0 +1,170 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; +use clippy_utils::{SpanlessEq, is_integer_literal}; +use rustc_hir::{AssignOpKind, BinOpKind, Block, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::declare_lint_pass; +use std::ops::ControlFlow; + +declare_clippy_lint! { + /// ### What it does + /// Detects manual zero checks before dividing integers, such as `if x != 0 { y / x }`. + /// + /// ### Why is this bad? + /// `checked_div` already handles the zero case and makes the intent clearer while avoiding a + /// panic from a manual division. + /// + /// ### Example + /// ```no_run + /// # let (a, b) = (10u32, 5u32); + /// if b != 0 { + /// let result = a / b; + /// println!("{result}"); + /// } + /// ``` + /// Use instead: + /// ```no_run + /// # let (a, b) = (10u32, 5u32); + /// if let Some(result) = a.checked_div(b) { + /// println!("{result}"); + /// } + /// ``` + #[clippy::version = "1.95.0"] + pub MANUAL_CHECKED_OPS, + complexity, + "manual zero checks before dividing integers" +} +declare_lint_pass!(ManualCheckedOps => [MANUAL_CHECKED_OPS]); + +#[derive(Copy, Clone)] +enum NonZeroBranch { + Then, + Else, +} + +impl LateLintPass<'_> for ManualCheckedOps { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::If(cond, then, r#else) = expr.kind + && !expr.span.from_expansion() + && let Some((divisor, branch)) = divisor_from_condition(cond) + // This lint is intended for unsigned integers only. + // + // For signed integers, the most direct refactor to `checked_div` is often not + // semantically equivalent to the original guard. For example, `rhs > 0` deliberately + // excludes negative divisors, while `checked_div` would return `Some` for `rhs = -2`. + // Also, `checked_div` can return `None` for `MIN / -1`, which requires additional + // handling beyond the zero check. + && is_unsigned_integer(cx, divisor) + && let Some(block) = branch_block(then, r#else, branch) + { + let mut eq = SpanlessEq::new(cx).deny_side_effects().paths_by_resolution(); + if !eq.eq_expr(divisor, divisor) { + return; + } + + let mut division_spans = Vec::new(); + let mut first_use = None; + + let found_early_use = for_each_expr_without_closures(block, |e| { + if let ExprKind::Binary(binop, lhs, rhs) = e.kind + && binop.node == BinOpKind::Div + && eq.eq_expr(rhs, divisor) + && is_unsigned_integer(cx, lhs) + { + match first_use { + None => first_use = Some(UseKind::Division), + Some(UseKind::Other) => return ControlFlow::Break(()), + Some(UseKind::Division) => {}, + } + + division_spans.push(e.span); + + ControlFlow::<(), _>::Continue(Descend::No) + } else if let ExprKind::AssignOp(op, lhs, rhs) = e.kind + && op.node == AssignOpKind::DivAssign + && eq.eq_expr(rhs, divisor) + && is_unsigned_integer(cx, lhs) + { + match first_use { + None => first_use = Some(UseKind::Division), + Some(UseKind::Other) => return ControlFlow::Break(()), + Some(UseKind::Division) => {}, + } + + division_spans.push(e.span); + + ControlFlow::<(), _>::Continue(Descend::No) + } else if eq.eq_expr(e, divisor) { + if first_use.is_none() { + first_use = Some(UseKind::Other); + return ControlFlow::Break(()); + } + ControlFlow::<(), _>::Continue(Descend::Yes) + } else { + ControlFlow::<(), _>::Continue(Descend::Yes) + } + }); + + if found_early_use.is_some() || first_use != Some(UseKind::Division) || division_spans.is_empty() { + return; + } + + span_lint_and_then(cx, MANUAL_CHECKED_OPS, cond.span, "manual checked division", |diag| { + diag.span_label(cond.span, "check performed here"); + if let Some((first, rest)) = division_spans.split_first() { + diag.span_label(*first, "division performed here"); + if !rest.is_empty() { + diag.span_labels(rest.to_vec(), "... and here"); + } + } + diag.help("consider using `checked_div`"); + }); + } + } +} + +#[derive(Copy, Clone, Eq, PartialEq)] +enum UseKind { + Division, + Other, +} + +fn divisor_from_condition<'tcx>(cond: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, NonZeroBranch)> { + let ExprKind::Binary(binop, lhs, rhs) = cond.kind else { + return None; + }; + + match binop.node { + BinOpKind::Ne | BinOpKind::Lt if is_zero(lhs) => Some((rhs, NonZeroBranch::Then)), + BinOpKind::Ne | BinOpKind::Gt if is_zero(rhs) => Some((lhs, NonZeroBranch::Then)), + BinOpKind::Eq if is_zero(lhs) => Some((rhs, NonZeroBranch::Else)), + BinOpKind::Eq if is_zero(rhs) => Some((lhs, NonZeroBranch::Else)), + _ => None, + } +} + +fn branch_block<'tcx>( + then: &'tcx Expr<'tcx>, + r#else: Option<&'tcx Expr<'tcx>>, + branch: NonZeroBranch, +) -> Option<&'tcx Block<'tcx>> { + match branch { + NonZeroBranch::Then => match then.kind { + ExprKind::Block(block, _) => Some(block), + _ => None, + }, + NonZeroBranch::Else => match r#else?.kind { + ExprKind::Block(block, _) => Some(block), + _ => None, + }, + } +} + +fn is_zero(expr: &Expr<'_>) -> bool { + is_integer_literal(expr, 0) +} + +fn is_unsigned_integer(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!(cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Uint(_)) +} diff --git a/clippy_lints/src/manual_take.rs b/clippy_lints/src/manual_take.rs new file mode 100644 index 000000000000..8e74d04c4556 --- /dev/null +++ b/clippy_lints/src/manual_take.rs @@ -0,0 +1,114 @@ +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{MEM_TAKE, Msrv}; +use clippy_utils::source::snippet_with_context; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Block, Expr, ExprKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::impl_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Detects manual re-implementations of `std::mem::take`. + /// + /// ### Why is this bad? + /// Because the function call is shorter and easier to read. + /// + /// ### Known issues + /// Currently the lint only detects cases involving `bool`s. + /// + /// ### Example + /// ```no_run + /// let mut x = true; + /// let _ = if x { + /// x = false; + /// true + /// } else { + /// false + /// }; + /// ``` + /// Use instead: + /// ```no_run + /// let mut x = true; + /// let _ = std::mem::take(&mut x); + /// ``` + #[clippy::version = "1.94.0"] + pub MANUAL_TAKE, + complexity, + "manual `mem::take` implementation" +} +pub struct ManualTake { + msrv: Msrv, +} + +impl ManualTake { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv } + } +} + +impl_lint_pass!(ManualTake => [MANUAL_TAKE]); + +impl LateLintPass<'_> for ManualTake { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::If(cond, then, Some(otherwise)) = expr.kind + && let ExprKind::Path(_) = cond.kind + && let ExprKind::Block( + Block { + stmts: [stmt], + expr: Some(then_expr), + .. + }, + .., + ) = then.kind + && let ExprKind::Block( + Block { + stmts: [], + expr: Some(else_expr), + .. + }, + .., + ) = otherwise.kind + && let StmtKind::Semi(assignment) = stmt.kind + && let ExprKind::Assign(mut_c, possible_false, _) = assignment.kind + && let ExprKind::Path(_) = mut_c.kind + && !expr.span.in_external_macro(cx.sess().source_map()) + && let Some(std_or_core) = clippy_utils::std_or_core(cx) + && self.msrv.meets(cx, MEM_TAKE) + && clippy_utils::SpanlessEq::new(cx).eq_expr(cond, mut_c) + && Some(false) == as_const_bool(possible_false) + && let Some(then_bool) = as_const_bool(then_expr) + && let Some(else_bool) = as_const_bool(else_expr) + && then_bool != else_bool + { + span_lint_and_then( + cx, + MANUAL_TAKE, + expr.span, + "manual implementation of `mem::take`", + |diag| { + let mut app = Applicability::MachineApplicable; + let negate = if then_bool { "" } else { "!" }; + let taken = snippet_with_context(cx, cond.span, expr.span.ctxt(), "_", &mut app).0; + diag.span_suggestion_verbose( + expr.span, + "use", + format!("{negate}{std_or_core}::mem::take(&mut {taken})"), + app, + ); + }, + ); + } + } +} + +fn as_const_bool(e: &Expr<'_>) -> Option { + if let ExprKind::Lit(lit) = e.kind + && let LitKind::Bool(b) = lit.node + { + Some(b) + } else { + None + } +} diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index 8f65858987b9..5ce9d364cdd8 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,12 +1,13 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; -use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, sym}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty; @@ -14,7 +15,37 @@ use rustc_span::{Span, Symbol}; use super::MANUAL_IS_VARIANT_AND; -pub(super) fn check( +#[derive(Clone, Copy, PartialEq)] +enum Flavor { + Option, + Result, +} + +impl Flavor { + fn new(cx: &LateContext<'_>, def_id: DefId) -> Option { + match cx.tcx.get_diagnostic_name(def_id)? { + sym::Option => Some(Self::Option), + sym::Result => Some(Self::Result), + _ => None, + } + } + + const fn diag_sym(self) -> Symbol { + match self { + Self::Option => sym::Option, + Self::Result => sym::Result, + } + } + + const fn positive_variant_name(self) -> Symbol { + match self { + Self::Option => sym::Some, + Self::Result => sym::Ok, + } + } +} + +pub(super) fn check_map_unwrap_or_default( cx: &LateContext<'_>, expr: &Expr<'_>, map_recv: &Expr<'_>, @@ -30,11 +61,13 @@ pub(super) fn check( } // 2. the caller of `map()` is neither `Option` nor `Result` - let is_option = cx.typeck_results().expr_ty(map_recv).is_diag_item(cx, sym::Option); - let is_result = cx.typeck_results().expr_ty(map_recv).is_diag_item(cx, sym::Result); - if !is_option && !is_result { + let Some(flavor) = (cx.typeck_results()) + .expr_ty(map_recv) + .opt_def_id() + .and_then(|did| Flavor::new(cx, did)) + else { return; - } + }; // 3. the caller of `unwrap_or_default` is neither `Option` nor `Result` if !cx.typeck_results().expr_ty(expr).is_bool() { @@ -46,44 +79,23 @@ pub(super) fn check( return; } - let lint_msg = if is_option { - "called `map().unwrap_or_default()` on an `Option` value" - } else { - "called `map().unwrap_or_default()` on a `Result` value" + let lint_span = expr.span.with_lo(map_span.lo()); + let lint_msg = match flavor { + Flavor::Option => "called `map().unwrap_or_default()` on an `Option` value", + Flavor::Result => "called `map().unwrap_or_default()` on a `Result` value", }; - let suggestion = if is_option { "is_some_and" } else { "is_ok_and" }; - span_lint_and_sugg( - cx, - MANUAL_IS_VARIANT_AND, - expr.span.with_lo(map_span.lo()), - lint_msg, - "use", - format!("{}({})", suggestion, snippet(cx, map_arg.span, "..")), - Applicability::MachineApplicable, - ); -} + span_lint_and_then(cx, MANUAL_IS_VARIANT_AND, lint_span, lint_msg, |diag| { + let method = match flavor { + Flavor::Option => "is_some_and", + Flavor::Result => "is_ok_and", + }; -#[derive(Clone, Copy, PartialEq)] -enum Flavor { - Option, - Result, -} + let mut app = Applicability::MachineApplicable; + let map_arg_snippet = snippet_with_applicability(cx, map_arg.span, "_", &mut app); -impl Flavor { - const fn symbol(self) -> Symbol { - match self { - Self::Option => sym::Option, - Self::Result => sym::Result, - } - } - - const fn positive(self) -> Symbol { - match self { - Self::Option => sym::Some, - Self::Result => sym::Ok, - } - } + diag.span_suggestion(lint_span, "use", format!("{method}({map_arg_snippet})"), app); + }); } #[derive(Clone, Copy, PartialEq)] @@ -178,7 +190,7 @@ fn emit_lint<'tcx>( cx, MANUAL_IS_VARIANT_AND, span, - format!("called `.map() {op} {pos}()`", pos = flavor.positive(),), + format!("called `.map() {op} {pos}()`", pos = flavor.positive_variant_name()), "use", format!( "{inversion}{recv}.{method}({body})", @@ -195,24 +207,23 @@ pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) { && op.span.eq_ctxt(expr.span) && let Ok(op) = Op::try_from(op.node) { - // Check `left` and `right` expression in any order, and for `Option` and `Result` + // Check `left` and `right` expression in any order for (expr1, expr2) in [(left, right), (right, left)] { - for flavor in [Flavor::Option, Flavor::Result] { - if let ExprKind::Call(call, [arg]) = expr1.kind - && let ExprKind::Lit(lit) = arg.kind - && let LitKind::Bool(bool_cst) = lit.node - && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind - && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res - && let ty = cx.typeck_results().expr_ty(expr1) - && let ty::Adt(adt, args) = ty.kind() - && cx.tcx.is_diagnostic_item(flavor.symbol(), adt.did()) - && args.type_at(0).is_bool() - && let ExprKind::MethodCall(_, recv, [map_expr], _) = expr2.kind - && cx.typeck_results().expr_ty(recv).is_diag_item(cx, flavor.symbol()) - && let Ok(map_func) = MapFunc::try_from(map_expr) - { - return emit_lint(cx, parent_expr.span, op, flavor, bool_cst, map_func, recv); - } + if let ExprKind::Call(call, [arg]) = expr1.kind + && let ExprKind::Lit(lit) = arg.kind + && let LitKind::Bool(bool_cst) = lit.node + && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind + && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res + && let ExprKind::MethodCall(_, recv, [map_expr], _) = expr2.kind + && let ty = cx.typeck_results().expr_ty(expr1) + && let ty::Adt(adt, args) = ty.kind() + && let Some(flavor) = Flavor::new(cx, adt.did()) + && args.type_at(0).is_bool() + && cx.typeck_results().expr_ty(recv).is_diag_item(cx, flavor.diag_sym()) + && let Ok(map_func) = MapFunc::try_from(map_expr) + { + emit_lint(cx, parent_expr.span, op, flavor, bool_cst, map_func, recv); + return; } } } diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 8eb26fb50747..ac2f99180486 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,71 +1,210 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet; -use clippy_utils::usage::mutated_variables; +use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_copy; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_path}; +use rustc_hir::{ExprKind, HirId, LangItem, Node, PatKind, Path, QPath}; use rustc_lint::LateContext; -use rustc_span::symbol::sym; +use rustc_middle::hir::nested_filter; +use rustc_span::{Span, sym}; +use std::ops::ControlFlow; use super::MAP_UNWRAP_OR; -/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s -/// -/// Returns true if the lint was emitted +/// lint use of `map().unwrap_or()` for `Option`s and `Result`s +#[expect(clippy::too_many_arguments)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - recv: &'tcx hir::Expr<'_>, - map_arg: &'tcx hir::Expr<'_>, - unwrap_arg: &'tcx hir::Expr<'_>, + expr: &rustc_hir::Expr<'_>, + recv: &rustc_hir::Expr<'_>, + map_arg: &'tcx rustc_hir::Expr<'_>, + unwrap_recv: &rustc_hir::Expr<'_>, + unwrap_arg: &'tcx rustc_hir::Expr<'_>, + map_span: Span, msrv: Msrv, -) -> bool { - // lint if the caller of `map()` is an `Option` or a `Result`. - let is_option = cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option); - let is_result = cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result); +) { + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let recv_ty_kind = match recv_ty.opt_diag_name(cx) { + Some(sym::Option) => sym::Option, + Some(sym::Result) if msrv.meets(cx, msrvs::RESULT_MAP_OR) => sym::Result, + _ => return, + }; - if is_result && !msrv.meets(cx, msrvs::RESULT_MAP_OR_ELSE) { - return false; - } + let unwrap_arg_ty = cx.typeck_results().expr_ty(unwrap_arg); + if !is_copy(cx, unwrap_arg_ty) { + // Replacing `.map().unwrap_or()` with `.map_or(, )` can sometimes lead to + // borrowck errors, see #10579 for one such instance. + // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); + // ``` + // This compiles, but changing it to `map_or` will produce a compile error: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map_or(x, |s| s.to_vec()) + // ^ moving `x` here + // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) + // ``` + // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) + // before the call to `unwrap_or`. - if is_option || is_result { - // Don't make a suggestion that may fail to compile due to mutably borrowing - // the same variable twice. - let map_mutated_vars = mutated_variables(recv, cx); - let unwrap_mutated_vars = mutated_variables(unwrap_arg, cx); - if let (Some(map_mutated_vars), Some(unwrap_mutated_vars)) = (map_mutated_vars, unwrap_mutated_vars) { - if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { - return false; - } - } else { - return false; - } - - // lint message - let msg = if is_option { - "called `map().unwrap_or_else()` on an `Option` value" - } else { - "called `map().unwrap_or_else()` on a `Result` value" + let mut unwrap_visitor = UnwrapVisitor { + cx, + identifiers: FxHashSet::default(), }; - // get snippets for args to map() and unwrap_or_else() - let map_snippet = snippet(cx, map_arg.span, ".."); - let unwrap_snippet = snippet(cx, unwrap_arg.span, ".."); - // lint, with note if both map() and unwrap_or_else() have the same span - if map_arg.span.eq_ctxt(unwrap_arg.span) { - let var_snippet = snippet(cx, recv.span, ".."); - span_lint_and_sugg( - cx, - MAP_UNWRAP_OR, - expr.span, - msg, - "try", - format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"), - Applicability::MachineApplicable, - ); - return true; + unwrap_visitor.visit_expr(unwrap_arg); + + let mut reference_visitor = ReferenceVisitor { + cx, + identifiers: unwrap_visitor.identifiers, + unwrap_or_span: unwrap_arg.span, + }; + + let body = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)); + + // Visit the body, and return if we've found a reference + if reference_visitor.visit_body(body).is_break() { + return; } } - false + if !unwrap_arg.span.eq_ctxt(map_span) { + return; + } + + let mut applicability = Applicability::MachineApplicable; + // get snippet for unwrap_or() + let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); + // lint message + + let suggest_kind = if recv_ty_kind == sym::Option + && unwrap_arg + .basic_res() + .ctor_parent(cx) + .is_lang_item(cx, LangItem::OptionNone) + { + SuggestedKind::AndThen + } + // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead + else if matches!(&unwrap_arg.kind, ExprKind::Lit(lit) + if matches!(lit.node, rustc_ast::LitKind::Bool(false))) + && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) + { + SuggestedKind::IsVariantAnd + } else { + SuggestedKind::Other + }; + + let arg = match suggest_kind { + SuggestedKind::AndThen => "None", + SuggestedKind::IsVariantAnd => "false", + SuggestedKind::Other => "", + }; + + let suggest = match (suggest_kind, recv_ty_kind) { + (SuggestedKind::AndThen, _) => "and_then()", + (SuggestedKind::IsVariantAnd, sym::Result) => "is_ok_and()", + (SuggestedKind::IsVariantAnd, sym::Option) => "is_some_and()", + _ => "map_or(, )", + }; + + let msg = format!( + "called `map().unwrap_or({arg})` on {} `{recv_ty_kind}` value", + if recv_ty_kind == sym::Option { "an" } else { "a" } + ); + + span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { + let map_arg_span = map_arg.span; + + let mut suggestion = vec![ + ( + map_span, + String::from(match (suggest_kind, recv_ty_kind) { + (SuggestedKind::AndThen, _) => "and_then", + (SuggestedKind::IsVariantAnd, sym::Result) => "is_ok_and", + (SuggestedKind::IsVariantAnd, sym::Option) => "is_some_and", + (SuggestedKind::Other, _) + if unwrap_arg_ty.peel_refs().is_array() + && cx.typeck_results().expr_ty_adjusted(unwrap_arg).peel_refs().is_slice() => + { + return; + }, + _ => "map_or", + }), + ), + (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), + ]; + + if matches!(suggest_kind, SuggestedKind::Other) { + suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); + } + + diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); + }); +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum SuggestedKind { + AndThen, + IsVariantAnd, + Other, +} + +struct UnwrapVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, +} + +impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); + } + walk_path(self, path); + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + +struct ReferenceVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, + unwrap_or_span: Span, +} + +impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> { + // If we haven't found a reference yet, check if this references + // one of the locals that was moved in the `unwrap_or` argument. + // We are only interested in exprs that appear before the `unwrap_or` call. + if expr.span < self.unwrap_or_span + && let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + return ControlFlow::Break(()); + } + walk_expr(self, expr) + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } } diff --git a/clippy_lints/src/methods/map_unwrap_or_else.rs b/clippy_lints/src/methods/map_unwrap_or_else.rs new file mode 100644 index 000000000000..8bb532b21635 --- /dev/null +++ b/clippy_lints/src/methods/map_unwrap_or_else.rs @@ -0,0 +1,68 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeDef as _; +use clippy_utils::source::snippet; +use clippy_utils::sym; +use clippy_utils::usage::mutated_variables; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::MAP_UNWRAP_OR; + +/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s +/// +/// Is part of the `map_unwrap_or` lint, split into separate files for readability. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, + unwrap_arg: &'tcx hir::Expr<'_>, + msrv: Msrv, +) -> bool { + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let recv_ty_kind = match recv_ty.opt_diag_name(cx) { + Some(sym::Option) => sym::Option, + Some(sym::Result) if msrv.meets(cx, msrvs::RESULT_MAP_OR_ELSE) => sym::Result, + _ => return false, + }; + + // Don't make a suggestion that may fail to compile due to mutably borrowing + // the same variable twice. + let Some(map_mutated_vars) = mutated_variables(recv, cx) else { + return false; + }; + let Some(unwrap_mutated_vars) = mutated_variables(unwrap_arg, cx) else { + return false; + }; + if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { + return false; + } + + // lint message + let msg = if recv_ty_kind == sym::Option { + "called `map().unwrap_or_else()` on an `Option` value" + } else { + "called `map().unwrap_or_else()` on a `Result` value" + }; + // get snippets for args to map() and unwrap_or_else() + let map_snippet = snippet(cx, map_arg.span, ".."); + let unwrap_snippet = snippet(cx, unwrap_arg.span, ".."); + // lint, with note if both map() and unwrap_or_else() have the same span + if map_arg.span.eq_ctxt(unwrap_arg.span) { + let var_snippet = snippet(cx, recv.span, ".."); + span_lint_and_sugg( + cx, + MAP_UNWRAP_OR, + expr.span, + msg, + "try", + format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"), + Applicability::MachineApplicable, + ); + return true; + } + + false +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 248a147cfd77..376e93aa7e7d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -74,6 +74,7 @@ mod map_err_ignore; mod map_flatten; mod map_identity; mod map_unwrap_or; +mod map_unwrap_or_else; mod map_with_unused_argument_over_ranges; mod mut_mutex_lock; mod needless_as_bytes; @@ -89,7 +90,6 @@ mod open_options; mod option_as_ref_cloned; mod option_as_ref_deref; mod option_map_or_none; -mod option_map_unwrap_or; mod or_fun_call; mod or_then_unwrap; mod path_buf_push_overwrite; @@ -3933,7 +3933,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where f is a function or closure that returns the `bool` type. + /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where `f` is a function or closure that returns the `bool` type. + /// /// Also checks for equality comparisons like `option.map(f) == Some(true)` and `result.map(f) == Ok(true)`. /// /// ### Why is this bad? @@ -5531,10 +5532,10 @@ impl Methods { stable_sort_primitive::check(cx, expr, recv); }, (sym::sort_by, [arg]) => { - unnecessary_sort_by::check(cx, expr, recv, arg, false); + unnecessary_sort_by::check(cx, expr, call_span, arg, false); }, (sym::sort_unstable_by, [arg]) => { - unnecessary_sort_by::check(cx, expr, recv, arg, true); + unnecessary_sort_by::check(cx, expr, call_span, arg, true); }, (sym::split, [arg]) => { str_split::check(cx, expr, recv, arg); @@ -5576,7 +5577,7 @@ impl Methods { unnecessary_fallible_conversions::check_method(cx, expr); }, (sym::to_owned, []) => { - if !suspicious_to_owned::check(cx, expr, recv) { + if !suspicious_to_owned::check(cx, expr, span) { implicit_clone::check(cx, name, expr, recv); } }, @@ -5607,7 +5608,7 @@ impl Methods { manual_saturating_arithmetic::check_unwrap_or(cx, expr, lhs, rhs, u_arg, arith); }, Some((sym::map, m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv); + map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv); }, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( @@ -5629,7 +5630,7 @@ impl Methods { manual_saturating_arithmetic::check_sub_unwrap_or_default(cx, expr, lhs, rhs); }, Some((sym::map, m_recv, [arg], span, _)) => { - manual_is_variant_and::check(cx, expr, m_recv, arg, span, self.msrv); + manual_is_variant_and::check_map_unwrap_or_default(cx, expr, m_recv, arg, span, self.msrv); }, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( @@ -5648,7 +5649,7 @@ impl Methods { (sym::unwrap_or_else, [u_arg]) => { match method_call(recv) { Some((sym::map, recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, + if map_unwrap_or_else::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( cx, diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 0e2012319147..6bdb40e46b38 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ops::ControlFlow; use super::NEEDLESS_COLLECT; @@ -16,8 +17,8 @@ use rustc_hir::{ use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, AssocTag, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::{Span, Symbol}; const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; @@ -104,16 +105,19 @@ pub(super) fn check<'tcx>( Node::LetStmt(l) => { if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind && let ty = cx.typeck_results().expr_ty(collect_expr) - && matches!( - ty.opt_diag_name(cx), - Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList) - ) + && let Some(extra_spec) = ty.opt_diag_name(cx).and_then(ExtraFunctionSpec::new) && let iter_ty = cx.typeck_results().expr_ty(iter_expr) && let Some(block) = get_enclosing_block(cx, l.hir_id) - && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty)) + && let Some((iter_calls, extra_calls)) = + detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty), extra_spec) && let [iter_call] = &*iter_calls { - let mut used_count_visitor = UsedCountVisitor { cx, id, count: 0 }; + let mut used_count_visitor = UsedCountVisitor { + cx, + id, + extra_spec, + count: 0, + }; walk_block(&mut used_count_visitor, block); if used_count_visitor.count > 1 { return; @@ -135,11 +139,24 @@ pub(super) fn check<'tcx>( span, NEEDLESS_COLLECT_MSG, |diag| { - let iter_replacement = - format!("{}{}", Sugg::hir(cx, iter_expr, ".."), iter_call.get_iter_method(cx)); + let iter_snippet = Sugg::hir(cx, iter_expr, ".."); + let mut iter_replacement = iter_snippet.to_string(); + for extra in &extra_calls { + iter_replacement = extra.apply_iter_method(cx, &iter_replacement); + } + iter_replacement.push_str(&iter_call.get_iter_method(cx)); + + let mut remove_suggestions = vec![(l.span, String::new())]; + remove_suggestions.extend( + extra_calls + .iter() + .flat_map(|extra| extra.span().map(|s| (s, String::new()))), + ); + remove_suggestions.push((iter_call.span, iter_replacement)); + diag.multipart_suggestion( iter_call.get_suggestion_text(), - vec![(l.span, String::new()), (iter_call.span, iter_replacement)], + remove_suggestions, Applicability::MaybeIncorrect, ); }, @@ -272,6 +289,7 @@ struct IterFunction { func: IterFunctionKind, span: Span, } + impl IterFunction { fn get_iter_method(&self, cx: &LateContext<'_>) -> String { match &self.func { @@ -288,6 +306,7 @@ impl IterFunction { }, } } + fn get_suggestion_text(&self) -> &'static str { match &self.func { IterFunctionKind::IntoIter(_) => { @@ -305,6 +324,7 @@ impl IterFunction { } } } + enum IterFunctionKind { IntoIter(HirId), Len, @@ -312,16 +332,119 @@ enum IterFunctionKind { Contains(Span), } +struct ExtraFunctionSpan { + /// Span of the function call + func_span: Span, + /// Span of the argument + arg_span: Span, +} + +enum ExtraFunction { + Push { + back: Vec, + front: Vec, + }, + Extend(ExtraFunctionSpan), +} + +impl ExtraFunction { + fn apply_iter_method(&self, cx: &LateContext<'_>, inner: &str) -> String { + match &self { + ExtraFunction::Push { back, front } => { + let back_sugg = back + .iter() + .map(|span| snippet(cx, span.arg_span, "..")) + .intersperse(Cow::Borrowed(", ")) + .collect::(); + let front = front + .iter() + .map(|span| snippet(cx, span.arg_span, "..")) + .intersperse(Cow::Borrowed(", ")) + .collect::(); + match (front.is_empty(), back_sugg.is_empty()) { + (true, true) => inner.to_string(), + (true, false) => format!("{inner}.chain([{back_sugg}])"), + (false, true) => format!("[{front}].into_iter().chain({inner})"), + (false, false) => format!("[{front}].into_iter().chain({inner}).chain([{back_sugg}])"), + } + }, + ExtraFunction::Extend(span) => { + let s = snippet(cx, span.arg_span, ".."); + format!("{inner}.chain({s})") + }, + } + } + + fn span(&self) -> Box + '_> { + match &self { + ExtraFunction::Push { back, front } => Box::new( + back.iter() + .map(|s| s.func_span) + .chain(front.iter().map(|s| s.func_span)), + ), + ExtraFunction::Extend(span) => Box::new(std::iter::once(span.func_span)), + } + } +} + +#[derive(Clone, Copy)] +struct ExtraFunctionPushSpec { + back: Option, + front: Option, +} + +#[derive(Clone, Copy)] +struct ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec, + extend_symbol: Option, +} + +impl ExtraFunctionSpec { + fn new(target: Symbol) -> Option { + match target { + sym::Vec => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: Some(sym::push), + front: None, + }, + extend_symbol: Some(sym::extend), + }), + sym::VecDeque | sym::LinkedList => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: Some(sym::push_back), + front: Some(sym::push_front), + }, + extend_symbol: Some(sym::extend), + }), + sym::BinaryHeap => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: None, + front: None, + }, + extend_symbol: None, + }), + _ => None, + } + } + + fn is_extra_function(self, name: Symbol) -> bool { + self.push_symbol.back == Some(name) || self.push_symbol.front == Some(name) || self.extend_symbol == Some(name) + } +} + struct IterFunctionVisitor<'a, 'tcx> { illegal_mutable_capture_ids: HirIdSet, current_mutably_captured_ids: HirIdSet, cx: &'a LateContext<'tcx>, uses: Vec>, + extras: Vec, + extra_spec: ExtraFunctionSpec, hir_id_uses_map: FxHashMap, current_statement_hir_id: Option, seen_other: bool, target: HirId, } + impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { fn visit_block(&mut self, block: &'tcx Block<'tcx>) { for (expr, hir_id) in block.stmts.iter().filter_map(get_expr_and_hir_id_from_stmt) { @@ -341,6 +464,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } } + #[expect(clippy::too_many_lines)] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind { @@ -384,6 +508,53 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { func: IterFunctionKind::Contains(args[0].span), span: expr.span, })), + name if let is_push_back = self.extra_spec.push_symbol.back.is_some_and(|sym| name == sym) + && (is_push_back || self.extra_spec.push_symbol.front.is_some_and(|sym| name == sym)) + && self.uses.is_empty() => + { + let span = get_span_of_expr_or_parent_stmt(self.cx, expr); + match self.extras.last_mut() { + Some(ExtraFunction::Push { back, .. }) if is_push_back => { + back.push(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }); + }, + Some(ExtraFunction::Push { front, .. }) => { + front.push(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }); + }, + _ if is_push_back => { + self.extras.push(ExtraFunction::Push { + back: vec![ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }], + front: Vec::new(), + }); + }, + _ => { + self.extras.push(ExtraFunction::Push { + back: Vec::new(), + front: vec![ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }], + }); + }, + } + }, + name if self.extra_spec.extend_symbol.is_some_and(|sym| name == sym) + && self.uses.is_empty() => + { + let span = get_span_of_expr_or_parent_stmt(self.cx, expr); + self.extras.push(ExtraFunction::Extend(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + })); + }, _ => { self.seen_other = true; if let Some(hir_id) = self.current_statement_hir_id { @@ -421,6 +592,16 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } } +/// If parent of the `expr` is a statement, return the span of the statement, otherwise return the +/// span of the expression. +fn get_span_of_expr_or_parent_stmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Span { + if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id) { + stmt.span + } else { + expr.span + } +} + enum LoopKind<'tcx> { Conditional(&'tcx Expr<'tcx>), Loop, @@ -468,6 +649,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> struct UsedCountVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, id: HirId, + extra_spec: ExtraFunctionSpec, count: usize, } @@ -475,11 +657,20 @@ impl<'tcx> Visitor<'tcx> for UsedCountVisitor<'_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if expr.res_local_id() == Some(self.id) { - self.count += 1; - } else { + if expr.res_local_id() != Some(self.id) { walk_expr(self, expr); + return; } + + let parent = self.cx.tcx.parent_hir_node(expr.hir_id); + if let Node::Expr(expr) = parent + && let ExprKind::MethodCall(method_name, _, _, _) = &expr.kind + && self.extra_spec.is_extra_function(method_name.ident.name) + { + return; + } + + self.count += 1; } fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { @@ -494,12 +685,15 @@ fn detect_iter_and_into_iters<'tcx: 'a, 'a>( id: HirId, cx: &'a LateContext<'tcx>, captured_ids: HirIdSet, -) -> Option> { + extra_spec: ExtraFunctionSpec, +) -> Option<(Vec, Vec)> { let mut visitor = IterFunctionVisitor { illegal_mutable_capture_ids: captured_ids, current_mutably_captured_ids: HirIdSet::default(), cx, uses: Vec::new(), + extras: Vec::new(), + extra_spec, hir_id_uses_map: FxHashMap::default(), current_statement_hir_id: None, seen_other: false, @@ -509,7 +703,7 @@ fn detect_iter_and_into_iters<'tcx: 'a, 'a>( if visitor.seen_other { None } else { - Some(visitor.uses.into_iter().flatten().collect()) + Some((visitor.uses.into_iter().flatten().collect(), visitor.extras)) } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs deleted file mode 100644 index 32a9b4fe7c58..000000000000 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ /dev/null @@ -1,180 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_copy; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::intravisit::{Visitor, walk_path}; -use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath}; -use rustc_lint::LateContext; -use rustc_middle::hir::nested_filter; -use rustc_span::{Span, sym}; -use std::ops::ControlFlow; - -use super::MAP_UNWRAP_OR; - -/// lint use of `map().unwrap_or()` for `Option`s -#[expect(clippy::too_many_arguments)] -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &rustc_hir::Expr<'_>, - recv: &rustc_hir::Expr<'_>, - map_arg: &'tcx rustc_hir::Expr<'_>, - unwrap_recv: &rustc_hir::Expr<'_>, - unwrap_arg: &'tcx rustc_hir::Expr<'_>, - map_span: Span, - msrv: Msrv, -) { - // lint if the caller of `map()` is an `Option` - if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option) { - if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { - // Replacing `.map().unwrap_or()` with `.map_or(, )` can sometimes lead to - // borrowck errors, see #10579 for one such instance. - // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: - // ``` - // let x = vec![1, 2]; - // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); - // ``` - // This compiles, but changing it to `map_or` will produce a compile error: - // ``` - // let x = vec![1, 2]; - // x.get(0..1).map_or(x, |s| s.to_vec()) - // ^ moving `x` here - // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) - // ``` - // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) - // before the call to `unwrap_or`. - - let mut unwrap_visitor = UnwrapVisitor { - cx, - identifiers: FxHashSet::default(), - }; - unwrap_visitor.visit_expr(unwrap_arg); - - let mut reference_visitor = ReferenceVisitor { - cx, - identifiers: unwrap_visitor.identifiers, - unwrap_or_span: unwrap_arg.span, - }; - - let body = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)); - - // Visit the body, and return if we've found a reference - if reference_visitor.visit_body(body).is_break() { - return; - } - } - - if !unwrap_arg.span.eq_ctxt(map_span) { - return; - } - - // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead - let suggest_is_some_and = matches!(&unwrap_arg.kind, ExprKind::Lit(lit) - if matches!(lit.node, rustc_ast::LitKind::Bool(false))) - && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND); - - let mut applicability = Applicability::MachineApplicable; - // get snippet for unwrap_or() - let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); - // lint message - // comparing the snippet from source to raw text ("None") below is safe - // because we already have checked the type. - let arg = if unwrap_snippet == "None" { - "None" - } else if suggest_is_some_and { - "false" - } else { - "" - }; - let unwrap_snippet_none = unwrap_snippet == "None"; - let suggest = if unwrap_snippet_none { - "and_then()" - } else if suggest_is_some_and { - "is_some_and()" - } else { - "map_or(, )" - }; - let msg = format!("called `map().unwrap_or({arg})` on an `Option` value"); - - span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { - let map_arg_span = map_arg.span; - - let mut suggestion = vec![ - ( - map_span, - String::from(if unwrap_snippet_none { - "and_then" - } else if suggest_is_some_and { - "is_some_and" - } else { - "map_or" - }), - ), - (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), - ]; - - if !unwrap_snippet_none && !suggest_is_some_and { - suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); - } - - diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); - }); - } -} - -struct UnwrapVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, -} - -impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> { - type NestedFilter = nested_filter::All; - - fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { - if let Res::Local(local_id) = path.res - && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) - && let PatKind::Binding(_, local_id, ..) = pat.kind - { - self.identifiers.insert(local_id); - } - walk_path(self, path); - } - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } -} - -struct ReferenceVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, - unwrap_or_span: Span, -} - -impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { - type NestedFilter = nested_filter::All; - type Result = ControlFlow<()>; - fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> { - // If we haven't found a reference yet, check if this references - // one of the locals that was moved in the `unwrap_or` argument. - // We are only interested in exprs that appear before the `unwrap_or` call. - if expr.span < self.unwrap_or_span - && let ExprKind::Path(ref path) = expr.kind - && let QPath::Resolved(_, path) = path - && let Res::Local(local_id) = path.res - && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) - && let PatKind::Binding(_, local_id, ..) = pat.kind - && self.identifiers.contains(&local_id) - { - return ControlFlow::Break(()); - } - rustc_hir::intravisit::walk_expr(self, expr) - } - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } -} diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs index bcd1f11931fc..e9a5104eb3b4 100644 --- a/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/clippy_lints/src/methods/suspicious_to_owned.rs @@ -1,15 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_span::sym; +use rustc_span::{Span, sym}; use super::SUSPICIOUS_TO_OWNED; -pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -> bool { +pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Span) -> bool { if cx .typeck_results() .type_dependent_def_id(expr.hir_id) @@ -18,28 +17,22 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) - && let input_type = cx.typeck_results().expr_ty(expr) && input_type.is_diag_item(cx, sym::Cow) { - let mut app = Applicability::MaybeIncorrect; - let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; + let app = Applicability::MaybeIncorrect; span_lint_and_then( cx, SUSPICIOUS_TO_OWNED, expr.span, with_forced_trimmed_paths!(format!( - "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned" + "this `to_owned` call clones the `{input_type}` itself and does not cause its contents to become owned" )), |diag| { diag.span_suggestion( - expr.span, - "depending on intent, either make the Cow an Owned variant", - format!("{recv_snip}.into_owned()"), - app, - ); - diag.span_suggestion( - expr.span, - "or clone the Cow itself", - format!("{recv_snip}.clone()"), + method_span, + "depending on intent, either make the `Cow` an `Owned` variant", + "into_owned".to_string(), app, ); + diag.span_suggestion(method_span, "or clone the `Cow` itself", "clone".to_string(), app); }, ); return true; diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 0c01be4b1875..21e112360aaf 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -8,7 +8,7 @@ use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::visitors::is_local_used; use clippy_utils::{get_parent_expr, is_from_proc_macro}; -use rustc_ast::LitKind::Bool; +use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind}; use rustc_lint::LateContext; @@ -48,13 +48,14 @@ pub(super) fn check<'a>( let ExprKind::Lit(def_kind) = def.kind else { return; }; - - let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); - - let Bool(def_bool) = def_kind.node else { + let LitKind::Bool(def_bool) = def_kind.node else { return; }; + let typeck = cx.typeck_results(); + + let recv_ty = typeck.expr_ty_adjusted(recv); + let variant = match recv_ty.opt_diag_name(cx) { Some(sym::Option) => Variant::Some, Some(sym::Result) => Variant::Ok, @@ -63,12 +64,12 @@ pub(super) fn check<'a>( let ext_def_span = def.span.until(map.span); - let (sugg, method, applicability) = if cx.typeck_results().expr_adjustments(recv).is_empty() + let (sugg, method, applicability): (_, Cow<'_, _>, _) = if typeck.expr_adjustments(recv).is_empty() && let ExprKind::Closure(map_closure) = map.kind && let closure_body = cx.tcx.hir_body(map_closure.body) && let closure_body_value = closure_body.value.peel_blocks() && let ExprKind::Binary(op, l, r) = closure_body_value.kind - && let Some(param) = closure_body.params.first() + && let [param] = closure_body.params && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind // checking that map_or is one of the following: // .map_or(false, |x| x == y) @@ -78,14 +79,13 @@ pub(super) fn check<'a>( && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool)) && let non_binding_location = if l.res_local_id() == Some(hir_id) { r } else { l } && switch_to_eager_eval(cx, non_binding_location) - // if its both then that's a strange edge case and + // if it's both then that's a strange edge case and // we can just ignore it, since by default clippy will error on this && (l.res_local_id() == Some(hir_id)) != (r.res_local_id() == Some(hir_id)) && !is_local_used(cx, non_binding_location, hir_id) - && let typeck_results = cx.typeck_results() - && let l_ty = typeck_results.expr_ty(l) - && l_ty == typeck_results.expr_ty(r) - && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq) + && let l_ty = typeck.expr_ty(l) + && l_ty == typeck.expr_ty(r) + && let Some(partial_eq) = cx.tcx.lang_items().eq_trait() && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()]) && is_copy(cx, l_ty) { @@ -97,12 +97,12 @@ pub(super) fn check<'a>( // being converted to `Some(5) == Some(5).then(|| 1)` isn't // the same thing + let mut app = Applicability::MachineApplicable; let inner_non_binding = Sugg::NonParen(Cow::Owned(format!( "{wrap}({})", - Sugg::hir(cx, non_binding_location, "") + Sugg::hir_with_applicability(cx, non_binding_location, "", &mut app) ))); - let mut app = Applicability::MachineApplicable; let binop = make_binop( op.node, &Sugg::hir_with_applicability(cx, recv, "..", &mut app), @@ -126,18 +126,18 @@ pub(super) fn check<'a>( } .into_string(); - (vec![(expr.span, sugg)], "a standard comparison", app) + (vec![(expr.span, sugg)], "a standard comparison".into(), app) } else if !def_bool && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { let suggested_name = variant.method_name(); ( - vec![(method_span, suggested_name.into()), (ext_def_span, String::default())], - suggested_name, + vec![(method_span, suggested_name.into()), (ext_def_span, String::new())], + format!("`{suggested_name}`").into(), Applicability::MachineApplicable, ) } else if def_bool && matches!(variant, Variant::Some) && msrv.meets(cx, msrvs::IS_NONE_OR) { ( - vec![(method_span, "is_none_or".into()), (ext_def_span, String::default())], - "is_none_or", + vec![(method_span, "is_none_or".into()), (ext_def_span, String::new())], + "`is_none_or`".into(), Applicability::MachineApplicable, ) } else { diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 7cc8c79481a0..3f81a6ecd2f8 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -1,47 +1,51 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::std_or_core; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::implements_trait; +use clippy_utils::ty::{implements_trait, is_copy, peel_n_ty_refs}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, GenericArgKind}; -use rustc_span::sym; +use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_span::symbol::Ident; +use rustc_span::{Span, sym}; use std::iter; +use std::ops::Not; use super::UNNECESSARY_SORT_BY; enum LintTrigger { - Sort(SortDetection), + Sort, SortByKey(SortByKeyDetection), } -struct SortDetection { - vec_name: String, -} - struct SortByKeyDetection { - vec_name: String, - closure_arg: String, + closure_arg: Span, closure_body: String, reverse: bool, + applicability: Applicability, } /// Detect if the two expressions are mirrored (identical, except one /// contains a and the other replaces it with b) -fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool { - match (&a_expr.kind, &b_expr.kind) { +fn mirrored_exprs( + a_expr: &Expr<'_>, + b_expr: &Expr<'_>, + binding_map: &BindingMap, + binding_source: BindingSource, +) -> bool { + match (a_expr.kind, b_expr.kind) { // Two arrays with mirrored contents - (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => { - iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - }, + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => iter::zip(left_exprs, right_exprs) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)), // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => { - mirrored_exprs(left_expr, a_ident, right_expr, b_ident) - && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) + mirrored_exprs(left_expr, right_expr, binding_map, binding_source) + && iter::zip(left_args, right_args) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)) }, // The two exprs are method calls. // Check to see that the function is the same and the arguments and receivers are mirrored @@ -50,116 +54,219 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident ExprKind::MethodCall(right_segment, right_receiver, right_args, _), ) => { left_segment.ident == right_segment.ident - && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - && mirrored_exprs(left_receiver, a_ident, right_receiver, b_ident) + && iter::zip(left_args, right_args) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)) + && mirrored_exprs(left_receiver, right_receiver, binding_map, binding_source) }, // Two tuples with mirrored contents - (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => { - iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - }, + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => iter::zip(left_exprs, right_exprs) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)), // Two binary ops, which are the same operation and which have mirrored arguments (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => { left_op.node == right_op.node - && mirrored_exprs(left_left, a_ident, right_left, b_ident) - && mirrored_exprs(left_right, a_ident, right_right, b_ident) + && mirrored_exprs(left_left, right_left, binding_map, binding_source) + && mirrored_exprs(left_right, right_right, binding_map, binding_source) }, // Two unary ops, which are the same operation and which have the same argument (ExprKind::Unary(left_op, left_expr), ExprKind::Unary(right_op, right_expr)) => { - left_op == right_op && mirrored_exprs(left_expr, a_ident, right_expr, b_ident) + left_op == right_op && mirrored_exprs(left_expr, right_expr, binding_map, binding_source) }, // The two exprs are literals of some kind (ExprKind::Lit(left_lit), ExprKind::Lit(right_lit)) => left_lit.node == right_lit.node, - (ExprKind::Cast(left, _), ExprKind::Cast(right, _)) => mirrored_exprs(left, a_ident, right, b_ident), + (ExprKind::Cast(left, _), ExprKind::Cast(right, _)) => mirrored_exprs(left, right, binding_map, binding_source), (ExprKind::DropTemps(left_block), ExprKind::DropTemps(right_block)) => { - mirrored_exprs(left_block, a_ident, right_block, b_ident) + mirrored_exprs(left_block, right_block, binding_map, binding_source) }, (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) => { - left_ident.name == right_ident.name && mirrored_exprs(left_expr, a_ident, right_expr, right_ident) + left_ident.name == right_ident.name && mirrored_exprs(left_expr, right_expr, binding_map, binding_source) }, // Two paths: either one is a and the other is b, or they're identical to each other ( ExprKind::Path(QPath::Resolved( _, - Path { + &Path { segments: left_segments, .. }, )), ExprKind::Path(QPath::Resolved( _, - Path { + &Path { segments: right_segments, .. }, )), ) => { - (iter::zip(*left_segments, *right_segments).all(|(left, right)| left.ident == right.ident) - && left_segments - .iter() - .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) + (iter::zip(left_segments, right_segments).all(|(left, right)| left.ident == right.ident) + && left_segments.iter().all(|seg| { + !binding_map.contains_key(&BindingKey { + ident: seg.ident, + source: BindingSource::Left, + }) && !binding_map.contains_key(&BindingKey { + ident: seg.ident, + source: BindingSource::Right, + }) + })) || (left_segments.len() == 1 - && &left_segments[0].ident == a_ident && right_segments.len() == 1 - && &right_segments[0].ident == b_ident) + && binding_map + .get(&BindingKey { + ident: left_segments[0].ident, + source: binding_source, + }) + .is_some_and(|value| value.mirrored.ident == right_segments[0].ident)) }, // Matching expressions, but one or both is borrowed ( ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), ExprKind::AddrOf(right_kind, Mutability::Not, right_expr), - ) => left_kind == right_kind && mirrored_exprs(left_expr, a_ident, right_expr, b_ident), - (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) => mirrored_exprs(a_expr, a_ident, right_expr, b_ident), - (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => mirrored_exprs(left_expr, a_ident, b_expr, b_ident), + ) => left_kind == right_kind && mirrored_exprs(left_expr, right_expr, binding_map, binding_source), + (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) => { + mirrored_exprs(a_expr, right_expr, binding_map, binding_source) + }, + (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => { + mirrored_exprs(left_expr, b_expr, binding_map, binding_source) + }, _ => false, } } -fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) -> Option { +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +enum BindingSource { + Left, + Right, +} + +impl Not for BindingSource { + type Output = BindingSource; + + fn not(self) -> Self::Output { + match self { + BindingSource::Left => BindingSource::Right, + BindingSource::Right => BindingSource::Left, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct BindingKey { + /// The identifier of the binding. + ident: Ident, + /// The source of the binding. + source: BindingSource, +} + +struct BindingValue { + /// The mirrored binding. + mirrored: BindingKey, + /// The number of refs the binding is wrapped in. + n_refs: usize, +} + +/// A map from binding info to the number of refs the binding is wrapped in. +type BindingMap = FxHashMap; +/// Extract the binding pairs, if the two patterns are mirrored. The pats are assumed to be used in +/// closure inputs and thus irrefutable. +fn mapping_of_mirrored_pats(a_pat: &Pat<'_>, b_pat: &Pat<'_>) -> Option { + fn mapping_of_mirrored_pats_inner( + a_pat: &Pat<'_>, + b_pat: &Pat<'_>, + mapping: &mut BindingMap, + n_refs: usize, + ) -> bool { + match (&a_pat.kind, &b_pat.kind) { + (PatKind::Tuple(a_pats, a_dots), PatKind::Tuple(b_pats, b_dots)) => { + a_dots == b_dots + && a_pats.len() == b_pats.len() + && iter::zip(a_pats.iter(), b_pats.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + (PatKind::Binding(_, _, a_ident, _), PatKind::Binding(_, _, b_ident, _)) => { + let a_key = BindingKey { + ident: *a_ident, + source: BindingSource::Left, + }; + let b_key = BindingKey { + ident: *b_ident, + source: BindingSource::Right, + }; + let a_value = BindingValue { + mirrored: b_key, + n_refs, + }; + let b_value = BindingValue { + mirrored: a_key, + n_refs, + }; + mapping.insert(a_key, a_value); + mapping.insert(b_key, b_value); + true + }, + (PatKind::Wild, PatKind::Wild) => true, + (PatKind::TupleStruct(_, a_pats, a_dots), PatKind::TupleStruct(_, b_pats, b_dots)) => { + a_dots == b_dots + && a_pats.len() == b_pats.len() + && iter::zip(a_pats.iter(), b_pats.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + (PatKind::Struct(_, a_fields, a_rest), PatKind::Struct(_, b_fields, b_rest)) => { + a_rest == b_rest + && a_fields.len() == b_fields.len() + && iter::zip(a_fields.iter(), b_fields.iter()).all(|(a_field, b_field)| { + a_field.ident == b_field.ident + && mapping_of_mirrored_pats_inner(a_field.pat, b_field.pat, mapping, n_refs) + }) + }, + (PatKind::Ref(a_inner, _, _), PatKind::Ref(b_inner, _, _)) => { + mapping_of_mirrored_pats_inner(a_inner, b_inner, mapping, n_refs + 1) + }, + (PatKind::Slice(a_elems, None, a_rest), PatKind::Slice(b_elems, None, b_rest)) => { + a_elems.len() == b_elems.len() + && iter::zip(a_elems.iter(), b_elems.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + && a_rest.len() == b_rest.len() + && iter::zip(a_rest.iter(), b_rest.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + _ => false, + } + } + + let mut mapping = FxHashMap::default(); + if mapping_of_mirrored_pats_inner(a_pat, b_pat, &mut mapping, 0) { + return Some(mapping); + } + + None +} + +fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) -> Option { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && let Some(impl_id) = cx.tcx.impl_of_assoc(method_id) && cx.tcx.type_of(impl_id).instantiate_identity().is_slice() && let ExprKind::Closure(&Closure { body, .. }) = arg.kind && let closure_body = cx.tcx.hir_body(body) - && let &[ - Param { - pat: - Pat { - kind: PatKind::Binding(_, _, left_ident, _), - .. - }, - .. - }, - Param { - pat: - Pat { - kind: PatKind::Binding(_, _, right_ident, _), - .. - }, - .. - }, - ] = &closure_body.params + && let &[Param { pat: l_pat, .. }, Param { pat: r_pat, .. }] = closure_body.params + && let Some(binding_map) = mapping_of_mirrored_pats(l_pat, r_pat) && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind && method_path.ident.name == sym::cmp - && cx - .ty_based_def(closure_body.value) - .opt_parent(cx) - .is_diag_item(cx, sym::Ord) + && let Some(ord_trait) = cx.tcx.get_diagnostic_item(sym::Ord) + && cx.ty_based_def(closure_body.value).opt_parent(cx).opt_def_id() == Some(ord_trait) { - let (closure_body, closure_arg, reverse) = if mirrored_exprs(left_expr, left_ident, right_expr, right_ident) { - ( - Sugg::hir(cx, left_expr, "..").to_string(), - left_ident.name.to_string(), - false, - ) - } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) { - ( - Sugg::hir(cx, left_expr, "..").to_string(), - right_ident.name.to_string(), - true, - ) + let (closure_body, closure_arg, reverse) = + if mirrored_exprs(left_expr, right_expr, &binding_map, BindingSource::Left) { + (left_expr, l_pat.span, false) + } else if mirrored_exprs(left_expr, right_expr, &binding_map, BindingSource::Right) { + (left_expr, r_pat.span, true) + } else { + return None; + }; + + let mut applicability = if reverse { + Applicability::MaybeIncorrect } else { - return None; + Applicability::MachineApplicable }; - let vec_name = Sugg::hir(cx, recv, "..").to_string(); if let ExprKind::Path(QPath::Resolved( _, @@ -167,22 +274,53 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp segments: [PathSegment { ident: left_name, .. }], .. }, - )) = &left_expr.kind - && left_name == left_ident - && cx - .tcx - .get_diagnostic_item(sym::Ord) - .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])) + )) = left_expr.kind { - return Some(LintTrigger::Sort(SortDetection { vec_name })); + if let PatKind::Binding(_, _, left_ident, _) = l_pat.kind + && *left_name == left_ident + && implements_trait(cx, cx.typeck_results().expr_ty(left_expr), ord_trait, &[]) + { + return Some(LintTrigger::Sort); + } + + let mut left_expr_ty = cx.typeck_results().expr_ty(left_expr); + let left_ident_n_refs = binding_map + .get(&BindingKey { + ident: *left_name, + source: BindingSource::Left, + }) + .map_or(0, |value| value.n_refs); + // Peel off the outer-most ref which is introduced by the closure, if it is not already peeled + // by the pattern + if left_ident_n_refs == 0 { + (left_expr_ty, _) = peel_n_ty_refs(left_expr_ty, 1); + } + if !reverse && is_copy(cx, left_expr_ty) { + let mut closure_body = + snippet_with_applicability(cx, closure_body.span, "_", &mut applicability).to_string(); + if left_ident_n_refs == 0 { + closure_body = format!("*{closure_body}"); + } + return Some(LintTrigger::SortByKey(SortByKeyDetection { + closure_arg, + closure_body, + reverse, + applicability, + })); + } } - if !expr_borrows(cx, left_expr) { + let left_expr_ty = cx.typeck_results().expr_ty(left_expr); + if !expr_borrows(left_expr_ty) + // Don't lint if the closure is accessing non-Copy fields + && (!expr_is_field_access(left_expr) || is_copy(cx, left_expr_ty)) + { + let closure_body = Sugg::hir_with_applicability(cx, closure_body, "_", &mut applicability).to_string(); return Some(LintTrigger::SortByKey(SortByKeyDetection { - vec_name, closure_arg, closure_body, reverse, + applicability, })); } } @@ -190,61 +328,75 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp None } -fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let ty = cx.typeck_results().expr_ty(expr); +fn expr_borrows(ty: Ty<'_>) -> bool { matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(_))) } +fn expr_is_field_access(expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Field(_, _) => true, + ExprKind::AddrOf(_, Mutability::Not, inner) => expr_is_field_access(inner), + _ => false, + } +} + pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, - recv: &'tcx Expr<'_>, + call_span: Span, arg: &'tcx Expr<'_>, is_unstable: bool, ) { - match detect_lint(cx, expr, recv, arg) { + match detect_lint(cx, expr, arg) { Some(LintTrigger::SortByKey(trigger)) => { let method = if is_unstable { "sort_unstable_by_key" } else { "sort_by_key" }; - span_lint_and_sugg( + let Some(std_or_core) = std_or_core(cx) else { + // To make it this far the crate has to reference diagnostic items defined in core. Either this is + // the `core` crate, there's an `extern crate core` somewhere, or another crate is defining the + // diagnostic items. It's fine to not lint in all those cases even if we might be able to. + return; + }; + span_lint_and_then( cx, UNNECESSARY_SORT_BY, expr.span, format!("consider using `{method}`"), - "try", - format!( - "{}.{}(|{}| {})", - trigger.vec_name, - method, - trigger.closure_arg, - if let Some(std_or_core) = std_or_core(cx) - && trigger.reverse - { - format!("{}::cmp::Reverse({})", std_or_core, trigger.closure_body) + |diag| { + let mut app = trigger.applicability; + let closure_body = if trigger.reverse { + format!("{std_or_core}::cmp::Reverse({})", trigger.closure_body) } else { trigger.closure_body - }, - ), - if trigger.reverse { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable + }; + let closure_arg = snippet_with_applicability(cx, trigger.closure_arg, "_", &mut app); + diag.span_suggestion_verbose( + call_span, + "try", + format!("{method}(|{closure_arg}| {closure_body})"), + app, + ); }, ); }, - Some(LintTrigger::Sort(trigger)) => { + Some(LintTrigger::Sort) => { let method = if is_unstable { "sort_unstable" } else { "sort" }; - span_lint_and_sugg( + span_lint_and_then( cx, UNNECESSARY_SORT_BY, expr.span, format!("consider using `{method}`"), - "try", - format!("{}.{}()", trigger.vec_name, method), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion_verbose( + call_span, + "try", + format!("{method}()"), + Applicability::MachineApplicable, + ); + }, ); }, None => {}, diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index 8e9400e9d583..7a791f949943 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use clippy_utils::macros::span_is_local; +use clippy_utils::source::snippet_opt; use rustc_hir::def_id::DefIdSet; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -84,7 +85,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { cx.tcx.def_span(item.owner_id), format!("missing trait method provided by default: `{}`", assoc.name()), |diag| { - diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method"); + if assoc.def_id.is_local() { + diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method"); + } else if let Some(snippet) = snippet_opt(cx, of_trait.trait_ref.path.span) { + diag.help(format!( + "implement the missing `{}` method of the `{snippet}` trait", + assoc.name(), + )); + } }, ); } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 55208ae708b9..d1d0d31ed91a 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -1,9 +1,9 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::higher; use clippy_utils::source::{indent_of, snippet_block, snippet_with_context}; use rustc_ast::Label; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, LoopSource, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, HirId, LoopSource, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::{ExpnKind, Span}; @@ -336,14 +336,9 @@ fn emit_warning(cx: &LateContext<'_>, data: &LintData<'_>, header: &str, typ: Li data.if_expr, ), }; - span_lint_and_help( - cx, - NEEDLESS_CONTINUE, - expr.span, - message, - None, - format!("{header}\n{snip}"), - ); + span_lint_hir_and_then(cx, NEEDLESS_CONTINUE, expr.hir_id, expr.span, message, |diag| { + diag.help(format!("{header}\n{snip}")); + }); } fn suggestion_snippet_for_continue_inside_if(cx: &LateContext<'_>, data: &LintData<'_>) -> String { @@ -424,11 +419,11 @@ fn suggestion_snippet_for_continue_inside_else(cx: &LateContext<'_>, data: &Lint fn check_last_stmt_in_expr(cx: &LateContext<'_>, inner_expr: &Expr<'_>, func: &F) where - F: Fn(Option<&Label>, Span), + F: Fn(HirId, Option<&Label>, Span), { match inner_expr.kind { ExprKind::Continue(continue_label) => { - func(continue_label.label.as_ref(), inner_expr.span); + func(inner_expr.hir_id, continue_label.label.as_ref(), inner_expr.span); }, ExprKind::If(_, then_block, else_block) if let ExprKind::Block(then_block, _) = then_block.kind => { check_last_stmt_in_block(cx, then_block, func); @@ -454,7 +449,7 @@ where fn check_last_stmt_in_block(cx: &LateContext<'_>, b: &Block<'_>, func: &F) where - F: Fn(Option<&Label>, Span), + F: Fn(HirId, Option<&Label>, Span), { if let Some(expr) = b.expr { check_last_stmt_in_expr(cx, expr, func); @@ -470,15 +465,17 @@ where fn check_and_warn(cx: &LateContext<'_>, expr: &Expr<'_>) { with_loop_block(expr, |loop_block, label| { - let p = |continue_label: Option<&Label>, span: Span| { + let p = |continue_hir_id, continue_label: Option<&Label>, span: Span| { if compare_labels(label, continue_label) { - span_lint_and_help( + span_lint_hir_and_then( cx, NEEDLESS_CONTINUE, + continue_hir_id, span, MSG_REDUNDANT_CONTINUE_EXPRESSION, - None, - DROP_CONTINUE_EXPRESSION_MSG, + |diag| { + diag.help(DROP_CONTINUE_EXPRESSION_MSG); + }, ); } }; diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 91a069559f7b..106286d16d18 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -33,7 +33,10 @@ impl ArithmeticSideEffects { allowed_binary.extend([ ("f32", FxHashSet::from_iter(["f32"])), ("f64", FxHashSet::from_iter(["f64"])), - ("std::string::String", FxHashSet::from_iter(["str"])), + ( + "std::string::String", + FxHashSet::from_iter(["str", "std::string::String"]), + ), ]); for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary { allowed_binary.entry(lhs).or_default().insert(rhs); diff --git a/clippy_lints/src/operators/double_comparison.rs b/clippy_lints/src/operators/double_comparison.rs index 71982023779e..a40a724d2da5 100644 --- a/clippy_lints/src/operators/double_comparison.rs +++ b/clippy_lints/src/operators/double_comparison.rs @@ -39,6 +39,18 @@ pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &E | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { "==" }, + // x != y && x >= y => x > y + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ge) + // x >= y && x != y => x > y + | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Ne) => { + ">" + }, + // x != y && x <= y => x < y + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Le) + // x <= y && x != y => x < y + | (BinOpKind::And, BinOpKind::Le, BinOpKind::Ne) => { + "<" + }, _ => return, }; diff --git a/clippy_lints/src/redundant_test_prefix.rs b/clippy_lints/src/redundant_test_prefix.rs index 84276e321657..602093259eae 100644 --- a/clippy_lints/src/redundant_test_prefix.rs +++ b/clippy_lints/src/redundant_test_prefix.rs @@ -47,6 +47,10 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// ### Note + /// Clippy can only lint compiled code. For this lint to trigger, you must configure `cargo clippy` + /// to include test compilation, for instance, by using flags such as `--tests` or `--all-targets`. #[clippy::version = "1.88.0"] pub REDUNDANT_TEST_PREFIX, restriction, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index fabb21f78b9e..8557e8d18d10 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeResPath; use clippy_utils::source::{indent_of, snippet}; use clippy_utils::{expr_or_init, get_builtin_attr, peel_hir_expr_unary, sym}; +use rustc_ast::BindingMode; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -89,13 +90,14 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { |diag| { match apa.counter { 0 | 1 => {}, - 2 => { + 2 if let Some(last_method_span) = apa.last_method_span => { let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); let init_method = snippet(cx, apa.first_method_span, ".."); - let usage_method = snippet(cx, apa.last_method_span, ".."); - let stmt = if let Some(last_bind_ident) = apa.last_bind_ident { + let usage_method = snippet(cx, last_method_span, ".."); + let stmt = if let Some((binding_mode, last_bind_ident)) = apa.last_bind_ident { format!( - "\n{indent}let {} = {init_method}.{usage_method};", + "\n{indent}let {}{} = {init_method}.{usage_method};", + binding_mode.prefix_str(), snippet(cx, last_bind_ident.span, ".."), ) } else { @@ -310,13 +312,13 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { }; match self.ap.curr_stmt.kind { hir::StmtKind::Let(local) => { - if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - apa.last_bind_ident = Some(ident); + if let hir::PatKind::Binding(binding_mode, _, ident, _) = local.pat.kind { + apa.last_bind_ident = Some((binding_mode, ident)); } if let Some(local_init) = local.init && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind { - apa.last_method_span = span; + apa.last_method_span = Some(span); } }, hir::StmtKind::Semi(semi_expr) => { @@ -326,7 +328,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { return; } if let hir::ExprKind::MethodCall(_, _, _, span) = semi_expr.kind { - apa.last_method_span = span; + apa.last_method_span = Some(span); } }, _ => {}, @@ -385,9 +387,9 @@ struct AuxParamsAttr { /// The last visited binding or variable span within a block that had any referenced inner type /// marked with `#[has_significant_drop]`. - last_bind_ident: Option, + last_bind_ident: Option<(BindingMode, Ident)>, /// Similar to `last_bind_span` but encompasses the right-hand method call. - last_method_span: Span, + last_method_span: Option, /// Similar to `last_bind_span` but encompasses the whole contained statement. last_stmt_span: Span, } @@ -403,7 +405,7 @@ impl Default for AuxParamsAttr { first_method_span: DUMMY_SP, first_stmt_span: DUMMY_SP, last_bind_ident: None, - last_method_span: DUMMY_SP, + last_method_span: None, last_stmt_span: DUMMY_SP, } } diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index b25fa0905feb..8524497c387c 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -150,7 +150,9 @@ impl SlowVectorInit { && func.ty_rel_def(cx).is_diag_item(cx, sym::vec_with_capacity) { Some(InitializedSize::Initialized(len_expr)) - } else if matches!(expr.kind, ExprKind::Call(func, []) if func.ty_rel_def(cx).is_diag_item(cx, sym::vec_new)) { + } else if let ExprKind::Call(func, []) = expr.kind + && func.ty_rel_def(cx).is_diag_item(cx, sym::vec_new) + { Some(InitializedSize::Uninitialized) } else { None diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index 0d50bd547652..962ab9cce14c 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -1,4 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_context; use clippy_utils::visitors::is_expr_unsafe; @@ -6,12 +8,12 @@ use clippy_utils::{match_libc_symbol, sym}; use rustc_errors::Applicability; use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, LangItem, Node, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does /// Checks for usage of `libc::strlen` on a `CString` or `CStr` value, - /// and suggest calling `as_bytes().len()` or `to_bytes().len()` respectively instead. + /// and suggest calling `count_bytes()` instead. /// /// ### Why is this bad? /// libc::strlen is an unsafe function, which we don't need to call @@ -27,15 +29,25 @@ declare_clippy_lint! { /// ```rust, no_run /// use std::ffi::CString; /// let cstring = CString::new("foo").expect("CString::new failed"); - /// let len = cstring.as_bytes().len(); + /// let len = cstring.count_bytes(); /// ``` #[clippy::version = "1.55.0"] pub STRLEN_ON_C_STRINGS, complexity, - "using `libc::strlen` on a `CString` or `CStr` value, while `as_bytes().len()` or `to_bytes().len()` respectively can be used instead" + "using `libc::strlen` on a `CString` or `CStr` value, while `count_bytes()` can be used instead" } -declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]); +pub struct StrlenOnCStrings { + msrv: Msrv, +} + +impl StrlenOnCStrings { + pub fn new(conf: &Conf) -> Self { + Self { msrv: conf.msrv } + } +} + +impl_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]); impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -47,7 +59,21 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { && let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind && !recv.span.from_expansion() && path.ident.name == sym::as_ptr + && let typeck = cx.typeck_results() + && typeck + .expr_ty_adjusted(self_arg) + .peel_refs() + .is_lang_item(cx, LangItem::CStr) { + let ty = typeck.expr_ty(self_arg).peel_refs(); + let ty_kind = if ty.is_diag_item(cx, sym::cstring_type) { + "`CString` value" + } else if ty.is_lang_item(cx, LangItem::CStr) { + "`CStr` value" + } else { + "type that dereferences to `CStr`" + }; + let ctxt = expr.span.ctxt(); let span = match cx.tcx.parent_hir_node(expr.hir_id) { Node::Block(&Block { @@ -58,25 +84,23 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { _ => expr.span, }; - let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - let mut app = Applicability::MachineApplicable; - let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; - let method_name = if ty.is_diag_item(cx, sym::cstring_type) { - "as_bytes" - } else if ty.is_lang_item(cx, LangItem::CStr) { - "to_bytes" - } else { - return; - }; - - span_lint_and_sugg( + span_lint_and_then( cx, STRLEN_ON_C_STRINGS, span, - "using `libc::strlen` on a `CString` or `CStr` value", - "try", - format!("{val_name}.{method_name}().len()"), - app, + format!("using `libc::strlen` on a {ty_kind}"), + |diag| { + let mut app = Applicability::MachineApplicable; + let val_name = snippet_with_context(cx, self_arg.span, ctxt, "_", &mut app).0; + + let suggestion = if self.msrv.meets(cx, msrvs::CSTR_COUNT_BYTES) { + format!("{val_name}.count_bytes()") + } else { + format!("{val_name}.to_bytes().len()") + }; + + diag.span_suggestion(span, "use", suggestion, app); + }, ); } } diff --git a/clippy_lints/src/transmute/transmuting_null.rs b/clippy_lints/src/transmute/transmuting_null.rs index 3f435f255d91..4f06d98703f6 100644 --- a/clippy_lints/src/transmute/transmuting_null.rs +++ b/clippy_lints/src/transmute/transmuting_null.rs @@ -42,6 +42,18 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t return true; } + // Catching: + // `std::mem::transmute(std::ptr::without_provenance::(0))` + // `std::mem::transmute(std::ptr::without_provenance_mut::(0))` + if let ExprKind::Call(func1, [arg1]) = arg.kind + && (func1.basic_res().is_diag_item(cx, sym::ptr_without_provenance) + || func1.basic_res().is_diag_item(cx, sym::ptr_without_provenance_mut)) + && is_integer_const(cx, arg1, 0) + { + span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); + return true; + } + // Catching: // `std::mem::transmute({ 0 as *const u64 })` and similar const blocks if let ExprKind::Block(block, _) = arg.kind diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 9d27a66a9ab8..1b26b1b32b80 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -115,6 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span, self.accept_comment_above_attributes) + && !block_has_inner_safety_comment(cx, block.span) && !block_parents_have_safety_comment( self.accept_comment_above_statement, self.accept_comment_above_attributes, @@ -839,6 +840,23 @@ fn text_has_safety_comment( } } } + // Check for a comment that appears after other code on the same line (e.g., `let x = // SAFETY:`) + // This handles cases in macros where the comment is on the same line as preceding code. + // We only check the first (immediate preceding) line for this pattern. + // Only whitespace is allowed between the comment marker and `SAFETY:`. + if let Some(comment_start) = [line.find("//"), line.find("/*")].into_iter().flatten().min() + && let after_marker = &line[comment_start + 2..] // skip marker + && let trimmed = after_marker.trim_start() // skip whitespace + && trimmed.get(..7).is_some_and(|s| s.eq_ignore_ascii_case("SAFETY:")) + { + let safety_offset = 2 + (after_marker.len() - trimmed.len()); + return HasSafetyComment::Yes( + start_pos + + BytePos(u32::try_from(line_start).unwrap()) + + BytePos(u32::try_from(comment_start + safety_offset).unwrap()), + false, + ); + } // No line comments; look for the start of a block comment. // This will only find them if they are at the start of a line. let (mut line_start, mut line) = (line_start, line); @@ -894,3 +912,20 @@ fn is_const_or_static(node: &Node<'_>) -> bool { }) ) } + +fn block_has_inner_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { + let source_map = cx.sess().source_map(); + if let Ok(src) = source_map.span_to_snippet(span) + && let Some(after_brace) = src + .strip_prefix("unsafe") + .and_then(|s| s.trim_start().strip_prefix('{')) + && let Some(comment) = after_brace + .trim_start() + .strip_prefix("//") + .or_else(|| after_brace.trim_start().strip_prefix("/*")) + { + comment.trim_start().to_ascii_uppercase().starts_with("SAFETY:") + } else { + false + } +} diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 975dd332ad06..12f8bd50e144 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -152,7 +152,12 @@ fn insert_necessary_parens(pat: &mut Pat) { walk_pat(self, pat); let target = match &mut pat.kind { // `i @ a | b`, `box a | b`, and `& mut? a | b`. - Ident(.., Some(p)) | Box(p) | Ref(p, _, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p, + Ident(.., Some(p)) | Box(p) | Ref(p, _, _) + if let Or(ps) = &p.kind + && ps.len() > 1 => + { + p + }, // `&(mut x)` Ref(p, Pinnedness::Not, Mutability::Not) if matches!(p.kind, Ident(BindingMode::MUT, ..)) => p, _ => return, diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 423301edfe83..4ce132e9e3ab 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -365,7 +365,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { format!("useless conversion to the same type: `{b}`"), "consider removing `.into_iter()`", sugg, - Applicability::MachineApplicable, // snippet + applicability, ); } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8243077cab89..e6fadc783621 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), - ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind") + ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind"), } } diff --git a/clippy_lints_internal/src/collapsible_calls.rs b/clippy_lints_internal/src/collapsible_span_lint_calls.rs similarity index 66% rename from clippy_lints_internal/src/collapsible_calls.rs rename to clippy_lints_internal/src/collapsible_span_lint_calls.rs index 7c9e7286925e..b048a1004b0d 100644 --- a/clippy_lints_internal/src/collapsible_calls.rs +++ b/clippy_lints_internal/src/collapsible_span_lint_calls.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet; -use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt}; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt, sym}; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_span::{Span, SyntaxContext}; use std::borrow::{Borrow, Cow}; @@ -88,33 +88,42 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind && let ExprKind::Path(..) = recv.kind { - let and_then_snippets = - get_and_then_snippets(cx, call_cx.span, call_lint.span, call_sp.span, call_msg.span); + let mut app = Applicability::MachineApplicable; + let expr_ctxt = expr.span.ctxt(); + let and_then_snippets = get_and_then_snippets( + cx, + expr_ctxt, + call_cx.span, + call_lint.span, + call_sp.span, + call_msg.span, + &mut app, + ); let mut sle = SpanlessEq::new(cx).deny_side_effects(); - match ps.ident.as_str() { - "span_suggestion" if sle.eq_expr(call_sp, &span_call_args[0]) => { - suggest_suggestion( - cx, - expr, - &and_then_snippets, - &span_suggestion_snippets(cx, span_call_args), - ); + match ps.ident.name { + sym::span_suggestion if sle.eq_expr(call_sp, &span_call_args[0]) => { + let snippets = span_suggestion_snippets(cx, expr_ctxt, span_call_args, &mut app); + suggest_suggestion(cx, expr, &and_then_snippets, &snippets, app); }, - "span_help" if sle.eq_expr(call_sp, &span_call_args[0]) => { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true); + sym::span_help if sle.eq_expr(call_sp, &span_call_args[0]) => { + let help_snippet = + snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true, app); }, - "span_note" if sle.eq_expr(call_sp, &span_call_args[0]) => { - let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); + sym::span_note if sle.eq_expr(call_sp, &span_call_args[0]) => { + let note_snippet = + snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true, app); }, - "help" => { - let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false); + sym::help => { + let help_snippet = + snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false, app); }, - "note" => { - let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); + sym::note => { + let note_snippet = + snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false, app); }, _ => (), } @@ -122,24 +131,26 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { } } -struct AndThenSnippets<'a> { - cx: Cow<'a, str>, - lint: Cow<'a, str>, - span: Cow<'a, str>, - msg: Cow<'a, str>, +struct AndThenSnippets { + cx: Cow<'static, str>, + lint: Cow<'static, str>, + span: Cow<'static, str>, + msg: Cow<'static, str>, } fn get_and_then_snippets( cx: &LateContext<'_>, + expr_ctxt: SyntaxContext, cx_span: Span, lint_span: Span, span_span: Span, msg_span: Span, -) -> AndThenSnippets<'static> { - let cx_snippet = snippet(cx, cx_span, "cx"); - let lint_snippet = snippet(cx, lint_span, ".."); - let span_snippet = snippet(cx, span_span, "span"); - let msg_snippet = snippet(cx, msg_span, r#""...""#); + app: &mut Applicability, +) -> AndThenSnippets { + let cx_snippet = snippet_with_applicability(cx, cx_span, "cx", app); + let lint_snippet = snippet_with_applicability(cx, lint_span, "..", app); + let span_snippet = snippet_with_applicability(cx, span_span, "span", app); + let msg_snippet = snippet_with_context(cx, msg_span, expr_ctxt, r#""...""#, app).0; AndThenSnippets { cx: cx_snippet, @@ -149,19 +160,22 @@ fn get_and_then_snippets( } } -struct SpanSuggestionSnippets<'a> { - help: Cow<'a, str>, - sugg: Cow<'a, str>, - applicability: Cow<'a, str>, +struct SpanSuggestionSnippets { + help: Cow<'static, str>, + sugg: Cow<'static, str>, + applicability: Cow<'static, str>, } -fn span_suggestion_snippets<'a, 'hir>( +fn span_suggestion_snippets<'hir>( cx: &LateContext<'_>, + expr_ctxt: SyntaxContext, span_call_args: &'hir [Expr<'hir>], -) -> SpanSuggestionSnippets<'a> { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - let sugg_snippet = snippet(cx, span_call_args[2].span, ".."); - let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable"); + app: &mut Applicability, +) -> SpanSuggestionSnippets { + let help_snippet = snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, app).0; + let sugg_snippet = snippet_with_context(cx, span_call_args[2].span, expr_ctxt, "..", app).0; + let applicability_snippet = + snippet_with_applicability(cx, span_call_args[3].span, "Applicability::MachineApplicable", app); SpanSuggestionSnippets { help: help_snippet, @@ -173,8 +187,9 @@ fn span_suggestion_snippets<'a, 'hir>( fn suggest_suggestion( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, - span_suggestion_snippets: &SpanSuggestionSnippets<'_>, + and_then_snippets: &AndThenSnippets, + span_suggestion_snippets: &SpanSuggestionSnippets, + app: Applicability, ) { span_lint_and_sugg( cx, @@ -192,16 +207,17 @@ fn suggest_suggestion( span_suggestion_snippets.sugg, span_suggestion_snippets.applicability ), - Applicability::MachineApplicable, + app, ); } fn suggest_help( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, + and_then_snippets: &AndThenSnippets, help: &str, with_span: bool, + app: Applicability, ) { let option_span = if with_span { format!("Some({})", and_then_snippets.span) @@ -219,16 +235,17 @@ fn suggest_help( "span_lint_and_help({}, {}, {}, {}, {}, {help})", and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span, ), - Applicability::MachineApplicable, + app, ); } fn suggest_note( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, + and_then_snippets: &AndThenSnippets, note: &str, with_span: bool, + app: Applicability, ) { let note_span = if with_span { format!("Some({})", and_then_snippets.span) @@ -246,6 +263,6 @@ fn suggest_note( "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})", and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, ), - Applicability::MachineApplicable, + app, ); } diff --git a/clippy_lints_internal/src/lib.rs b/clippy_lints_internal/src/lib.rs index e009f263f11f..502d5cd3f340 100644 --- a/clippy_lints_internal/src/lib.rs +++ b/clippy_lints_internal/src/lib.rs @@ -2,7 +2,7 @@ #![allow( clippy::missing_docs_in_private_items, clippy::must_use_candidate, - clippy::symbol_as_str, + clippy::symbol_as_str )] #![warn( trivial_casts, @@ -29,7 +29,7 @@ extern crate rustc_session; extern crate rustc_span; mod almost_standard_lint_formulation; -mod collapsible_calls; +mod collapsible_span_lint_calls; mod derive_deserialize_allowing_unknown; mod internal_paths; mod lint_without_lint_pass; @@ -46,7 +46,7 @@ use rustc_lint::{Lint, LintStore}; static LINTS: &[&Lint] = &[ almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION, - collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS, + collapsible_span_lint_calls::COLLAPSIBLE_SPAN_LINT_CALLS, derive_deserialize_allowing_unknown::DERIVE_DESERIALIZE_ALLOWING_UNKNOWN, lint_without_lint_pass::DEFAULT_LINT, lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE, @@ -67,7 +67,7 @@ pub fn register_lints(store: &mut LintStore) { store.register_early_pass(|| Box::new(unsorted_clippy_utils_paths::UnsortedClippyUtilsPaths)); store.register_early_pass(|| Box::new(produce_ice::ProduceIce)); - store.register_late_pass(|_| Box::new(collapsible_calls::CollapsibleCalls)); + store.register_late_pass(|_| Box::new(collapsible_span_lint_calls::CollapsibleCalls)); store.register_late_pass(|_| Box::new(derive_deserialize_allowing_unknown::DeriveDeserializeAllowingUnknown)); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::::default()); diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 503d581d6c7f..b61b663d1026 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.94" +version = "0.1.95" edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_utils/README.md b/clippy_utils/README.md index ecd36b157571..204a66a435ee 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-01-08 +nightly-2026-01-22 ``` diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 32f6cb4fd5e9..56490cfc8b65 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -159,7 +159,10 @@ impl LimitStack { } pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) { let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| debug_assert_eq!(stack.pop(), Some(val))); + parse_attrs(sess, attrs, name, |val| { + let popped = stack.pop(); + debug_assert_eq!(popped, Some(val)); + }); } } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c7bb3a064a09..b9f104a79a27 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -505,7 +505,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r), (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { + || swap_binop(self.inner.cx, l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, @@ -667,7 +667,7 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (ConstArgKind::Tup(l_t), ConstArgKind::Tup(r_t)) => { - l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(*l_c, *r_c)) + l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(l_c, r_c)) }, (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), @@ -689,9 +689,12 @@ impl HirEqInterExpr<'_, '_, '_> { (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() - && l_arr.elems.iter().zip(r_arr.elems.iter()) - .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) - } + && l_arr + .elems + .iter() + .zip(r_arr.elems.iter()) + .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) + }, // Use explicit match for now since ConstArg is undergoing flux. ( ConstArgKind::Path(..) @@ -955,26 +958,35 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' } fn swap_binop<'a>( + cx: &LateContext<'_>, binop: BinOpKind, lhs: &'a Expr<'a>, rhs: &'a Expr<'a>, ) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { match binop { - BinOpKind::Add | BinOpKind::Eq | BinOpKind::Ne | BinOpKind::BitAnd | BinOpKind::BitXor | BinOpKind::BitOr => { - Some((binop, rhs, lhs)) - }, + // `==` and `!=`, are commutative + BinOpKind::Eq | BinOpKind::Ne => Some((binop, rhs, lhs)), + // Comparisons can be reversed BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Mul // Not always commutative, e.g. with matrices. See issue #5698 - | BinOpKind::Shl - | BinOpKind::Shr - | BinOpKind::Rem - | BinOpKind::Sub - | BinOpKind::Div + // Non-commutative operators + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub | BinOpKind::Div => None, + // We know that those operators are commutative for primitive types, + // and we don't assume anything for other types + BinOpKind::Mul + | BinOpKind::Add | BinOpKind::And - | BinOpKind::Or => None, + | BinOpKind::Or + | BinOpKind::BitAnd + | BinOpKind::BitXor + | BinOpKind::BitOr => cx + .typeck_results() + .expr_ty_adjusted(lhs) + .peel_refs() + .is_primitive() + .then_some((binop, rhs, lhs)), } } @@ -1564,7 +1576,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Tup(tup) => { for arg in *tup { - self.hash_const_arg(*arg); + self.hash_const_arg(arg); } }, ConstArgKind::Path(path) => self.hash_qpath(path), diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 7e3b1ccd224e..6b10f4b51442 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -6,11 +6,7 @@ #![feature(assert_matches)] #![feature(unwrap_infallible)] #![recursion_limit = "512"] -#![allow( - clippy::missing_errors_doc, - clippy::missing_panics_doc, - clippy::must_use_candidate, -)] +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( trivial_casts, trivial_numeric_casts, @@ -2028,12 +2024,12 @@ pub fn is_expr_temporary_value(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { - if !is_no_std_crate(cx) { - Some("std") - } else if !is_no_core_crate(cx) { + if is_no_core_crate(cx) { + None + } else if is_no_std_crate(cx) { Some("core") } else { - None + Some("std") } } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 4a7fa3472cae..18fab6035f28 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -23,6 +23,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,91,0 { DURATION_FROM_MINUTES_HOURS } 1,88,0 { LET_CHAINS } 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST } 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL } @@ -31,7 +32,7 @@ msrv_aliases! { 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS } 1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION, DURATION_ABS_DIFF } 1,80,0 { BOX_INTO_ITER, LAZY_CELL } - 1,79,0 { CONST_BLOCKS } + 1,79,0 { CONST_BLOCKS, CSTR_COUNT_BYTES } 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } @@ -61,7 +62,7 @@ msrv_aliases! { 1,45,0 { STR_STRIP_PREFIX } 1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS } 1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS } - 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } + 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR, RESULT_MAP_OR_ELSE } 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } 1,38,0 { POINTER_CAST, REM_EUCLID } 1,37,0 { TYPE_ALIAS_ENUM_VARIANTS } @@ -69,12 +70,12 @@ msrv_aliases! { 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,33,0 { UNDERSCORE_IMPORTS } - 1,32,0 { CONST_IS_POWER_OF_TWO } + 1,32,0 { CONST_IS_POWER_OF_TWO, CONST_DURATION_FROM_NANOS_MICROS_MILLIS_SECS } 1,31,0 { OPTION_REPLACE } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,29,0 { ITER_FLATTEN } 1,28,0 { FROM_BOOL, REPEAT_WITH, SLICE_FROM_REF } - 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND } + 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND, DURATION_FROM_NANOS_MICROS } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN, POINTER_ADD_SUB_METHODS } 1,24,0 { IS_ASCII_DIGIT, PTR_NULL } 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } @@ -82,6 +83,7 @@ msrv_aliases! { 1,16,0 { STR_REPEAT, RESULT_UNWRAP_OR_DEFAULT } 1,15,0 { MAYBE_BOUND_IN_WHERE } 1,13,0 { QUESTION_MARK_OPERATOR } + 1,3,0 { DURATION_FROM_MILLIS_SECS } } /// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 94591a7ee30a..5d6f2241c7c0 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -139,6 +139,7 @@ generate! { disallowed_types, drain, dump, + duration_constructors, ends_with, enum_glob_use, enumerate, @@ -163,12 +164,20 @@ generate! { from_be_bytes, from_bytes_with_nul, from_bytes_with_nul_unchecked, + from_days, + from_hours, from_le_bytes, + from_micros, + from_millis, + from_mins, + from_nanos, from_ne_bytes, from_ptr, from_raw, from_raw_parts, + from_secs, from_str_radix, + from_weeks, fs, fuse, futures_util, @@ -179,6 +188,7 @@ generate! { get_unchecked, get_unchecked_mut, has_significant_drop, + help, hidden_glob_reexports, hygiene, ilog, @@ -271,6 +281,8 @@ generate! { powi, product, push, + push_back, + push_front, push_str, read, read_exact, @@ -325,7 +337,10 @@ generate! { sort, sort_by, sort_unstable_by, + span_help, span_lint_and_then, + span_note, + span_suggestion, split, split_at, split_at_checked, diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index c1be4acc7068..2f5f2f7d166f 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -438,6 +438,21 @@ pub fn peel_and_count_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize, Option, n: usize) -> (Ty<'_>, Option) { + let mut mutbl = None; + for _ in 0..n { + if let ty::Ref(_, dest_ty, m) = ty.kind() { + ty = *dest_ty; + mutbl.replace(mutbl.map_or(*m, |mutbl: Mutability| mutbl.min(*m))); + } else { + break; + } + } + (ty, mutbl) +} + /// Checks whether `a` and `b` are same types having same `Const` generic args, but ignores /// lifetimes. /// @@ -815,7 +830,7 @@ impl AdtVariantInfo { .enumerate() .map(|(i, f)| (i, approx_ty_size(cx, f.ty(cx.tcx, subst)))) .collect::>(); - fields_size.sort_by(|(_, a_size), (_, b_size)| a_size.cmp(b_size)); + fields_size.sort_by_key(|(_, a_size)| *a_size); Self { ind: i, @@ -824,7 +839,7 @@ impl AdtVariantInfo { } }) .collect::>(); - variants_size.sort_by(|a, b| b.size.cmp(&a.size)); + variants_size.sort_by_key(|b| std::cmp::Reverse(b.size)); variants_size } } diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index ee6d6cdbc34e..39831e2b52d6 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.94" +version = "0.1.95" edition = "2024" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/lintcheck/src/input.rs b/lintcheck/src/input.rs index 7dda2b7b25f8..ee3fcaa0a84a 100644 --- a/lintcheck/src/input.rs +++ b/lintcheck/src/input.rs @@ -281,8 +281,7 @@ impl CrateWithSource { CrateSource::Path { path } => { fn is_cache_dir(entry: &DirEntry) -> bool { fs::read(entry.path().join("CACHEDIR.TAG")) - .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) - .unwrap_or(false) + .is_ok_and(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) } // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 0755e1d29c69..c26289c23725 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-01-08" +channel = "nightly-2026-01-22" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/driver.rs b/src/driver.rs index c9ca6335de6e..7425da70df90 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -30,11 +30,10 @@ use rustc_span::symbol::Symbol; use std::env; use std::fs::read_to_string; +use std::io::Write as _; use std::path::Path; use std::process::exit; -use anstream::println; - /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. fn arg_value<'a>(args: &'a [String], find_arg: &str, pred: impl Fn(&str) -> bool) -> Option<&'a str> { @@ -184,7 +183,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } fn display_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; @@ -251,8 +252,10 @@ pub fn main() { if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); - exit(0); + match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => exit(rustc_driver::EXIT_SUCCESS), + Err(_) => exit(rustc_driver::EXIT_FAILURE), + } } // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. diff --git a/src/main.rs b/src/main.rs index 688161c7bfcb..98b888444831 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,19 +4,24 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use std::env; -use std::path::PathBuf; -use std::process::{self, Command}; +extern crate rustc_driver; -use anstream::println; +use std::env; +use std::io::Write as _; +use std::path::PathBuf; +use std::process::{self, Command, exit}; fn show_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } fn show_version() { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); + if writeln!(&mut anstream::stdout().lock(), "{version_info}").is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } pub fn main() { diff --git a/tests/ui-internal/collapsible_span_lint_calls.fixed b/tests/ui-internal/collapsible_span_lint_calls.fixed index 76f68686ee2a..2b646a38b534 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -50,6 +50,15 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}")); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}")); } } diff --git a/tests/ui-internal/collapsible_span_lint_calls.rs b/tests/ui-internal/collapsible_span_lint_calls.rs index 214c8783a669..500552370053 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/tests/ui-internal/collapsible_span_lint_calls.rs @@ -65,6 +65,35 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_suggestion( + expr.span, + format!("try using {foo}"), + format!("{foo}.use"), + Applicability::MachineApplicable, + ); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_help(expr.span, format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.help(format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_note(expr.span, format!("required because of {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.note(format!("required because of {foo}")); + }); } } diff --git a/tests/ui-internal/collapsible_span_lint_calls.stderr b/tests/ui-internal/collapsible_span_lint_calls.stderr index 9c83538947ca..76b453019270 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -49,5 +49,53 @@ LL | | db.note(note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` -error: aborting due to 5 previous errors +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:72:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_suggestion( +LL | | expr.span, +... | +LL | | ); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable)` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:81:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_help(expr.span, format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:85:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.help(format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:89:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_note(expr.span, format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:93:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.note(format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}"))` + +error: aborting due to 10 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 61e5af81d827..bcc46adda8a0 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -289,13 +313,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -303,7 +327,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -311,7 +335,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -319,7 +343,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -343,136 +367,136 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:701:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:768:5 | LL | const UNIX_EPOCH_JULIAN_DAY: i32 = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:699:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:8 | LL | // SAFETY: fail ONLY if `accept-comment-above-attribute = false` | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:746:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:813:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:744:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:811:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:759:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:826:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:757:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:824:8 | LL | // SAFETY: ... | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:774:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:841:9 | LL | let x = 34; | ^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:772:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:839:12 | LL | // SAFETY: ... | ^^^^^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 50 previous errors +error: aborting due to 52 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index e252cffea916..0de8ed716bed 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:606:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +311,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -297,13 +321,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -311,7 +335,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -319,7 +343,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:635:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:640:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:578:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:645:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +367,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:652:5 | LL | unsafe {} | ^^^^^^^^^ @@ -351,7 +375,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:590:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:5 | LL | unsafe { | ^^^^^^^^ @@ -359,7 +383,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:598:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:665:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +391,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:604:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:671:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -375,7 +399,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:678:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -383,7 +407,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:617:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:684:5 | LL | unsafe {} | ^^^^^^^^^ @@ -391,7 +415,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -399,7 +423,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -407,7 +431,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -415,7 +439,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -423,7 +447,7 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:9 | LL | unsafe { here_is_another_variable_with_long_name }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -431,7 +455,7 @@ LL | unsafe { here_is_another_variable_with_long_name }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:702:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:769:9 | LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,19 +463,19 @@ LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:735:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:802:12 | LL | return unsafe { h() }; | ^^^^^^^^^^^^^^ @@ -459,31 +483,31 @@ LL | return unsafe { h() }; = help: consider adding a safety comment on the preceding line error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:833:9 | LL | unsafe {} | ^^^^^^^^^ @@ -491,52 +515,52 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 60 previous errors +error: aborting due to 62 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index db9e81cf10a1..8032c388ccfe 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -201,6 +201,66 @@ fn comment_macro_def() { t!(); } +fn comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = + // SAFETY: here be exactly one dragon + unsafe { 1 }; + }; + } + + t!(); +} + +#[rustfmt::skip] +fn comment_macro_def_with_let_same_line() { + macro_rules! t { + () => { + let _x =// SAFETY: same line comment + unsafe { 1 }; + }; + } + + t!(); +} + +fn inner_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { + // SAFETY: inside the block + 1 + }; + }; + } + + t!(); +} + +fn no_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + +fn prefixed_safety_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x =// not a SAFETY: comment, should lint + unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + fn non_ascii_comment() { // ॐ᧻໒ SaFeTy: ௵∰ unsafe {}; @@ -263,6 +323,13 @@ fn in_closure(x: *const u32) { let _ = || unsafe { *x }; } +fn inner_block_comment_block_style(x: *const u32) { + let _ = unsafe { + /* SAFETY: block comment inside */ + *x + }; +} + // Invalid comments #[rustfmt::skip] diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index b7ed596d811e..87397a549bf4 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -174,7 +174,6 @@ pub fn hard_coded_allowed() { let _ = Saturating(0u32) + Saturating(0u32); let _ = String::new() + ""; let _ = String::new() + &String::new(); - //~^ arithmetic_side_effects let _ = Wrapping(0u32) + Wrapping(0u32); let saturating: Saturating = Saturating(0u32); diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 22742a82601a..2767a051786e 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -14,784 +14,778 @@ LL | let _ = 1f128 + 1f128; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:176:13 - | -LL | let _ = String::new() + &String::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:312:5 + --> tests/ui/arithmetic_side_effects.rs:311:5 | LL | _n += 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:314:5 + --> tests/ui/arithmetic_side_effects.rs:313:5 | LL | _n += &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:316:5 + --> tests/ui/arithmetic_side_effects.rs:315:5 | LL | _n -= 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:318:5 + --> tests/ui/arithmetic_side_effects.rs:317:5 | LL | _n -= &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:320:5 + --> tests/ui/arithmetic_side_effects.rs:319:5 | LL | _n /= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:322:5 + --> tests/ui/arithmetic_side_effects.rs:321:5 | LL | _n /= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:324:5 + --> tests/ui/arithmetic_side_effects.rs:323:5 | LL | _n %= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:326:5 + --> tests/ui/arithmetic_side_effects.rs:325:5 | LL | _n %= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:328:5 + --> tests/ui/arithmetic_side_effects.rs:327:5 | LL | _n *= 2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:330:5 + --> tests/ui/arithmetic_side_effects.rs:329:5 | LL | _n *= &2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:332:5 + --> tests/ui/arithmetic_side_effects.rs:331:5 | LL | _n += -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:334:5 + --> tests/ui/arithmetic_side_effects.rs:333:5 | LL | _n += &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:336:5 + --> tests/ui/arithmetic_side_effects.rs:335:5 | LL | _n -= -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:338:5 + --> tests/ui/arithmetic_side_effects.rs:337:5 | LL | _n -= &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:340:5 + --> tests/ui/arithmetic_side_effects.rs:339:5 | LL | _n /= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:342:5 + --> tests/ui/arithmetic_side_effects.rs:341:5 | LL | _n /= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:344:5 + --> tests/ui/arithmetic_side_effects.rs:343:5 | LL | _n %= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:346:5 + --> tests/ui/arithmetic_side_effects.rs:345:5 | LL | _n %= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:348:5 + --> tests/ui/arithmetic_side_effects.rs:347:5 | LL | _n *= -2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:350:5 + --> tests/ui/arithmetic_side_effects.rs:349:5 | LL | _n *= &-2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:352:5 + --> tests/ui/arithmetic_side_effects.rs:351:5 | LL | _custom += Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:354:5 + --> tests/ui/arithmetic_side_effects.rs:353:5 | LL | _custom += &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:356:5 + --> tests/ui/arithmetic_side_effects.rs:355:5 | LL | _custom -= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:358:5 + --> tests/ui/arithmetic_side_effects.rs:357:5 | LL | _custom -= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:360:5 + --> tests/ui/arithmetic_side_effects.rs:359:5 | LL | _custom /= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:362:5 + --> tests/ui/arithmetic_side_effects.rs:361:5 | LL | _custom /= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:364:5 + --> tests/ui/arithmetic_side_effects.rs:363:5 | LL | _custom %= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:366:5 + --> tests/ui/arithmetic_side_effects.rs:365:5 | LL | _custom %= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:368:5 + --> tests/ui/arithmetic_side_effects.rs:367:5 | LL | _custom *= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:370:5 + --> tests/ui/arithmetic_side_effects.rs:369:5 | LL | _custom *= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:372:5 + --> tests/ui/arithmetic_side_effects.rs:371:5 | LL | _custom >>= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:374:5 + --> tests/ui/arithmetic_side_effects.rs:373:5 | LL | _custom >>= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:376:5 + --> tests/ui/arithmetic_side_effects.rs:375:5 | LL | _custom <<= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:378:5 + --> tests/ui/arithmetic_side_effects.rs:377:5 | LL | _custom <<= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:380:5 + --> tests/ui/arithmetic_side_effects.rs:379:5 | LL | _custom += -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:382:5 + --> tests/ui/arithmetic_side_effects.rs:381:5 | LL | _custom += &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:384:5 + --> tests/ui/arithmetic_side_effects.rs:383:5 | LL | _custom -= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:386:5 + --> tests/ui/arithmetic_side_effects.rs:385:5 | LL | _custom -= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:388:5 + --> tests/ui/arithmetic_side_effects.rs:387:5 | LL | _custom /= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:390:5 + --> tests/ui/arithmetic_side_effects.rs:389:5 | LL | _custom /= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:392:5 + --> tests/ui/arithmetic_side_effects.rs:391:5 | LL | _custom %= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:394:5 + --> tests/ui/arithmetic_side_effects.rs:393:5 | LL | _custom %= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:396:5 + --> tests/ui/arithmetic_side_effects.rs:395:5 | LL | _custom *= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:398:5 + --> tests/ui/arithmetic_side_effects.rs:397:5 | LL | _custom *= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:400:5 + --> tests/ui/arithmetic_side_effects.rs:399:5 | LL | _custom >>= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:402:5 + --> tests/ui/arithmetic_side_effects.rs:401:5 | LL | _custom >>= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:404:5 + --> tests/ui/arithmetic_side_effects.rs:403:5 | LL | _custom <<= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:406:5 + --> tests/ui/arithmetic_side_effects.rs:405:5 | LL | _custom <<= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:410:10 + --> tests/ui/arithmetic_side_effects.rs:409:10 | LL | _n = _n + 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:412:10 + --> tests/ui/arithmetic_side_effects.rs:411:10 | LL | _n = _n + &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:414:10 + --> tests/ui/arithmetic_side_effects.rs:413:10 | LL | _n = 1 + _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:416:10 + --> tests/ui/arithmetic_side_effects.rs:415:10 | LL | _n = &1 + _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:418:10 + --> tests/ui/arithmetic_side_effects.rs:417:10 | LL | _n = _n - 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:420:10 + --> tests/ui/arithmetic_side_effects.rs:419:10 | LL | _n = _n - &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:422:10 + --> tests/ui/arithmetic_side_effects.rs:421:10 | LL | _n = 1 - _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:424:10 + --> tests/ui/arithmetic_side_effects.rs:423:10 | LL | _n = &1 - _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:426:10 + --> tests/ui/arithmetic_side_effects.rs:425:10 | LL | _n = _n / 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:428:10 + --> tests/ui/arithmetic_side_effects.rs:427:10 | LL | _n = _n / &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:430:10 + --> tests/ui/arithmetic_side_effects.rs:429:10 | LL | _n = _n % 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:432:10 + --> tests/ui/arithmetic_side_effects.rs:431:10 | LL | _n = _n % &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:434:10 + --> tests/ui/arithmetic_side_effects.rs:433:10 | LL | _n = _n * 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:436:10 + --> tests/ui/arithmetic_side_effects.rs:435:10 | LL | _n = _n * &2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:438:10 + --> tests/ui/arithmetic_side_effects.rs:437:10 | LL | _n = 2 * _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:440:10 + --> tests/ui/arithmetic_side_effects.rs:439:10 | LL | _n = &2 * _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:442:10 + --> tests/ui/arithmetic_side_effects.rs:441:10 | LL | _n = 23 + &85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:444:10 + --> tests/ui/arithmetic_side_effects.rs:443:10 | LL | _n = &23 + 85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:446:10 + --> tests/ui/arithmetic_side_effects.rs:445:10 | LL | _n = &23 + &85; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:448:15 + --> tests/ui/arithmetic_side_effects.rs:447:15 | LL | _custom = _custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:450:15 + --> tests/ui/arithmetic_side_effects.rs:449:15 | LL | _custom = _custom + &_custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:452:15 + --> tests/ui/arithmetic_side_effects.rs:451:15 | LL | _custom = Custom + _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:454:15 + --> tests/ui/arithmetic_side_effects.rs:453:15 | LL | _custom = &Custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:456:15 + --> tests/ui/arithmetic_side_effects.rs:455:15 | LL | _custom = _custom - Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:458:15 + --> tests/ui/arithmetic_side_effects.rs:457:15 | LL | _custom = _custom - &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:460:15 + --> tests/ui/arithmetic_side_effects.rs:459:15 | LL | _custom = Custom - _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:462:15 + --> tests/ui/arithmetic_side_effects.rs:461:15 | LL | _custom = &Custom - _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:464:15 + --> tests/ui/arithmetic_side_effects.rs:463:15 | LL | _custom = _custom / Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:466:15 + --> tests/ui/arithmetic_side_effects.rs:465:15 | LL | _custom = _custom / &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:468:15 + --> tests/ui/arithmetic_side_effects.rs:467:15 | LL | _custom = _custom % Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:470:15 + --> tests/ui/arithmetic_side_effects.rs:469:15 | LL | _custom = _custom % &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:472:15 + --> tests/ui/arithmetic_side_effects.rs:471:15 | LL | _custom = _custom * Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:474:15 + --> tests/ui/arithmetic_side_effects.rs:473:15 | LL | _custom = _custom * &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:476:15 + --> tests/ui/arithmetic_side_effects.rs:475:15 | LL | _custom = Custom * _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:478:15 + --> tests/ui/arithmetic_side_effects.rs:477:15 | LL | _custom = &Custom * _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:480:15 + --> tests/ui/arithmetic_side_effects.rs:479:15 | LL | _custom = Custom + &Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:482:15 + --> tests/ui/arithmetic_side_effects.rs:481:15 | LL | _custom = &Custom + Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:484:15 + --> tests/ui/arithmetic_side_effects.rs:483:15 | LL | _custom = &Custom + &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:486:15 + --> tests/ui/arithmetic_side_effects.rs:485:15 | LL | _custom = _custom >> _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:488:15 + --> tests/ui/arithmetic_side_effects.rs:487:15 | LL | _custom = _custom >> &_custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:490:15 + --> tests/ui/arithmetic_side_effects.rs:489:15 | LL | _custom = Custom << _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:492:15 + --> tests/ui/arithmetic_side_effects.rs:491:15 | LL | _custom = &Custom << _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:496:23 + --> tests/ui/arithmetic_side_effects.rs:495:23 | LL | _n.saturating_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:498:21 + --> tests/ui/arithmetic_side_effects.rs:497:21 | LL | _n.wrapping_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:500:21 + --> tests/ui/arithmetic_side_effects.rs:499:21 | LL | _n.wrapping_rem(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:502:28 + --> tests/ui/arithmetic_side_effects.rs:501:28 | LL | _n.wrapping_rem_euclid(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:505:23 + --> tests/ui/arithmetic_side_effects.rs:504:23 | LL | _n.saturating_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:507:21 + --> tests/ui/arithmetic_side_effects.rs:506:21 | LL | _n.wrapping_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:509:21 + --> tests/ui/arithmetic_side_effects.rs:508:21 | LL | _n.wrapping_rem(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:511:28 + --> tests/ui/arithmetic_side_effects.rs:510:28 | LL | _n.wrapping_rem_euclid(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:514:23 + --> tests/ui/arithmetic_side_effects.rs:513:23 | LL | _n.saturating_div(*Box::new(_n)); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:518:10 + --> tests/ui/arithmetic_side_effects.rs:517:10 | LL | _n = -_n; | ^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:520:10 + --> tests/ui/arithmetic_side_effects.rs:519:10 | LL | _n = -&_n; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:522:15 + --> tests/ui/arithmetic_side_effects.rs:521:15 | LL | _custom = -_custom; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:524:15 + --> tests/ui/arithmetic_side_effects.rs:523:15 | LL | _custom = -&_custom; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:526:9 + --> tests/ui/arithmetic_side_effects.rs:525:9 | LL | _ = -*Box::new(_n); | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:536:5 + --> tests/ui/arithmetic_side_effects.rs:535:5 | LL | 1 + i; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:538:5 + --> tests/ui/arithmetic_side_effects.rs:537:5 | LL | i * 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:540:5 + --> tests/ui/arithmetic_side_effects.rs:539:5 | LL | 1 % i / 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:542:5 + --> tests/ui/arithmetic_side_effects.rs:541:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:544:5 + --> tests/ui/arithmetic_side_effects.rs:543:5 | LL | -i; | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:556:5 + --> tests/ui/arithmetic_side_effects.rs:555:5 | LL | i += 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:558:5 + --> tests/ui/arithmetic_side_effects.rs:557:5 | LL | i -= 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:560:5 + --> tests/ui/arithmetic_side_effects.rs:559:5 | LL | i *= 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:563:5 + --> tests/ui/arithmetic_side_effects.rs:562:5 | LL | i /= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:566:5 + --> tests/ui/arithmetic_side_effects.rs:565:5 | LL | i /= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:568:5 + --> tests/ui/arithmetic_side_effects.rs:567:5 | LL | i /= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:571:5 + --> tests/ui/arithmetic_side_effects.rs:570:5 | LL | i %= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:574:5 + --> tests/ui/arithmetic_side_effects.rs:573:5 | LL | i %= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:576:5 + --> tests/ui/arithmetic_side_effects.rs:575:5 | LL | i %= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:587:5 + --> tests/ui/arithmetic_side_effects.rs:586:5 | LL | 10 / a | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:642:9 + --> tests/ui/arithmetic_side_effects.rs:641:9 | LL | x / maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:647:9 + --> tests/ui/arithmetic_side_effects.rs:646:9 | LL | x % maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:659:5 + --> tests/ui/arithmetic_side_effects.rs:658:5 | LL | one.add_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:664:5 + --> tests/ui/arithmetic_side_effects.rs:663:5 | LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:685:5 + --> tests/ui/arithmetic_side_effects.rs:684:5 | LL | one.add(&one); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:687:5 + --> tests/ui/arithmetic_side_effects.rs:686:5 | LL | Box::new(one).add(one); | ^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:696:13 + --> tests/ui/arithmetic_side_effects.rs:695:13 | LL | let _ = u128::MAX + u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:713:13 + --> tests/ui/arithmetic_side_effects.rs:712:13 | LL | let _ = u128::MAX * u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:736:33 + --> tests/ui/arithmetic_side_effects.rs:735:33 | LL | let _ = Duration::from_secs(86400 * Foo::from(1)); | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:742:33 + --> tests/ui/arithmetic_side_effects.rs:741:33 | LL | let _ = Duration::from_secs(86400 * shift(1)); | ^^^^^^^^^^^^^^^^ -error: aborting due to 132 previous errors +error: aborting due to 131 previous errors diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index 8080c6775e0b..3945028f8271 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -472,3 +472,28 @@ mod issue14422 { return; } } + +#[clippy::cognitive_complexity = "1"] +mod attribute_stacking { + fn bad() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } + + #[clippy::cognitive_complexity = "2"] + fn ok() { + if true { + println!("a"); + } + } + + // should revert to cognitive_complexity = "1" + fn bad_again() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } +} diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 67ef4e5655bd..e5f54a37229d 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -176,5 +176,21 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions -error: aborting due to 22 previous errors +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:478:8 + | +LL | fn bad() { + | ^^^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:493:8 + | +LL | fn bad_again() { + | ^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + +error: aborting due to 24 previous errors diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index 3ded902e36b1..84147d8e9c16 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,12 +1,11 @@ -//@check-pass //@ignore-target: apple - #![feature(rustc_attrs)] - #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] #[rustc_main] fn a() { - println!("Hello, World!"); a(); + //~^ main_recursion } + +fn main() {} diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr new file mode 100644 index 000000000000..d9f50d2dfc4b --- /dev/null +++ b/tests/ui/crate_level_checks/entrypoint_recursion.stderr @@ -0,0 +1,12 @@ +error: recursing into entrypoint `a` + --> tests/ui/crate_level_checks/entrypoint_recursion.rs:7:5 + | +LL | a(); + | ^ + | + = help: consider using another function for this recursion + = note: `-D clippy::main-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::main_recursion)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs new file mode 100644 index 000000000000..74763d67dd78 --- /dev/null +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -0,0 +1,13 @@ +//@check-pass +//@compile-flags: -Cpanic=abort +#![no_std] +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +fn main() { + main(); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index 0680eb35ef97..29047b8a31cb 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x < y { + //~^ double_comparisons + // do something + } + if x < y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } } diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 18ab7d2c4254..13edb2a996a1 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x != y && x <= y { + //~^ double_comparisons + // do something + } + if x <= y && x != y { + //~^ double_comparisons + // do something + } + if x != y && x >= y { + //~^ double_comparisons + // do something + } + if x >= y && x != y { + //~^ double_comparisons + // do something + } } diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 984614c203eb..be7eba611cb0 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -49,5 +49,29 @@ error: this binary expression can be simplified LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` -error: aborting due to 8 previous errors +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:38:8 + | +LL | if x != y && x <= y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:42:8 + | +LL | if x <= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:46:8 + | +LL | if x != y && x >= y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:50:8 + | +LL | if x >= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: aborting due to 12 previous errors diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed new file mode 100644 index 000000000000..98c4b6e965ba --- /dev/null +++ b/tests/ui/duration_suboptimal_units.fixed @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_mins(5) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(10); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(13); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_mins(1); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs new file mode 100644 index 000000000000..c4f33a9f92e0 --- /dev/null +++ b/tests/ui/duration_suboptimal_units.rs @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_secs(300) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(10 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_secs(60); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/tests/ui/duration_suboptimal_units.stderr b/tests/ui/duration_suboptimal_units.stderr new file mode 100644 index 000000000000..f129dbade8dc --- /dev/null +++ b/tests/ui/duration_suboptimal_units.stderr @@ -0,0 +1,152 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:26:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:28:15 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:30:15 + | +LL | let dur = Duration::from_secs(10 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(10 * 60); +LL + let dur = Duration::from_mins(10); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:32:15 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:34:15 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:36:15 + | +LL | let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_hours(13); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:47:19 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:49:19 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:51:19 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:58:5 + | +LL | std::time::Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - std::time::Duration::from_secs(60); +LL + std::time::Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:62:16 + | +LL | assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); +LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:13:9 + | +LL | Duration::from_secs(300) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | let dur = mac!(duration); + | -------------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: try using from_mins + | +LL - Duration::from_secs(300) +LL + Duration::from_mins(5) + | + +error: aborting due to 12 previous errors + diff --git a/tests/ui/duration_suboptimal_units_days_weeks.fixed b/tests/ui/duration_suboptimal_units_days_weeks.fixed new file mode 100644 index 000000000000..b0abcbb7bf03 --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.fixed @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_days(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_weeks(13); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units_days_weeks.rs b/tests/ui/duration_suboptimal_units_days_weeks.rs new file mode 100644 index 000000000000..663476905c0f --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.rs @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units_days_weeks.stderr b/tests/ui/duration_suboptimal_units_days_weeks.stderr new file mode 100644 index 000000000000..98325358bfa6 --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.stderr @@ -0,0 +1,40 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:9:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:12:15 + | +LL | let dur = Duration::from_hours(24); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_days + | +LL - let dur = Duration::from_hours(24); +LL + let dur = Duration::from_days(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:15:15 + | +LL | let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_weeks + | +LL - let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_weeks(13); + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index 5fdcd5a7e078..677523489599 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macro_derive.rs +//@aux-build:proc_macros.rs #![allow( unused, @@ -11,6 +12,7 @@ #[macro_use] extern crate proc_macro_derive; +extern crate proc_macros; fn empty() {} @@ -148,4 +150,34 @@ mod issue_13578 { impl<'a, T: 'a> Foo for Option where &'a T: Foo {} } +// no lint on proc macro generated code +mod proc_macro_generated { + use proc_macros::external; + + // no lint on external macro (extra unused lifetimes in impl block) + external! { + struct ExternalImplStruct; + + impl<'a> ExternalImplStruct { + fn foo() {} + } + } + + // no lint on external macro (extra unused lifetimes in method) + external! { + struct ExternalMethodStruct; + + impl ExternalMethodStruct { + fn bar<'a>(&self) {} + } + } + + // no lint on external macro (extra unused lifetimes in trait method) + external! { + trait ExternalUnusedLifetimeTrait { + fn unused_lt<'a>(x: u8) {} + } + } +} + fn main() {} diff --git a/tests/ui/extra_unused_lifetimes.stderr b/tests/ui/extra_unused_lifetimes.stderr index 0cecbbe80f76..d748376d476c 100644 --- a/tests/ui/extra_unused_lifetimes.stderr +++ b/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:19:14 + --> tests/ui/extra_unused_lifetimes.rs:21:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -8,37 +8,37 @@ LL | fn unused_lt<'a>(x: u8) {} = help: to override `-D warnings` add `#[allow(clippy::extra_unused_lifetimes)]` error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:47:10 + --> tests/ui/extra_unused_lifetimes.rs:49:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:74:22 + --> tests/ui/extra_unused_lifetimes.rs:76:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:86:10 + --> tests/ui/extra_unused_lifetimes.rs:88:10 | LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:93:10 + --> tests/ui/extra_unused_lifetimes.rs:95:10 | LL | impl<'b> Scalar { | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:95:26 + --> tests/ui/extra_unused_lifetimes.rs:97:26 | LL | pub fn something<'c>() -> Self { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:125:10 + --> tests/ui/extra_unused_lifetimes.rs:127:10 | LL | impl<'a, T: Source + ?Sized + 'a> Source for Box { | ^^ diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 6d2e63e7299a..6e0e2c5ea720 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -11,6 +11,8 @@ unreachable_code )] +use std::ops::*; + struct Foo { bar: u8, } @@ -133,18 +135,6 @@ fn func() { fn f(val: &[u8]) {} -mod issue_5698 { - fn mul_not_always_commutative(x: i32, y: i32) -> i32 { - if x == 42 { - x * y - } else if x == 21 { - y * x - } else { - 0 - } - } -} - mod issue_8836 { fn do_not_lint() { if true { @@ -245,3 +235,73 @@ mod issue_11213 { } fn main() {} + +fn issue16416(x: bool, a: T, b: T) +where + T: Add + Sub + Mul + Div + Rem + BitAnd + BitOr + BitXor + PartialEq + Eq + PartialOrd + Ord + Shr + Shl + Copy, +{ + // Non-guaranteed-commutative operators + _ = if x { a * b } else { b * a }; + _ = if x { a + b } else { b + a }; + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + _ = if x { a & b } else { b & a }; + _ = if x { a ^ b } else { b ^ a }; + _ = if x { a | b } else { b | a }; + + // Guaranteed commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} + +fn issue16416_prim(x: bool, a: u32, b: u32) { + // Non-commutative operators + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + + // Commutative operators on primitive types + //~v if_same_then_else + _ = if x { a * b } else { b * a }; + //~v if_same_then_else + _ = if x { a + b } else { b + a }; + //~v if_same_then_else + _ = if x { a & b } else { b & a }; + //~v if_same_then_else + _ = if x { a ^ b } else { b ^ a }; + //~v if_same_then_else + _ = if x { a | b } else { b | a }; + + // Always commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index b76da3fb1cb5..57396a566941 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:23:13 + --> tests/ui/if_same_then_else.rs:25:13 | LL | if true { | _____________^ @@ -12,7 +12,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:31:12 + --> tests/ui/if_same_then_else.rs:33:12 | LL | } else { | ____________^ @@ -27,43 +27,43 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::if_same_then_else)]` error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:67:21 + --> tests/ui/if_same_then_else.rs:69:21 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:67:34 + --> tests/ui/if_same_then_else.rs:69:34 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:70:21 + --> tests/ui/if_same_then_else.rs:72:21 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:70:35 + --> tests/ui/if_same_then_else.rs:72:35 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:82:21 + --> tests/ui/if_same_then_else.rs:84:21 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:82:33 + --> tests/ui/if_same_then_else.rs:84:33 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:85:13 + --> tests/ui/if_same_then_else.rs:87:13 | LL | if true { | _____________^ @@ -76,7 +76,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:92:12 + --> tests/ui/if_same_then_else.rs:94:12 | LL | } else { | ____________^ @@ -89,7 +89,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:238:14 + --> tests/ui/if_same_then_else.rs:228:14 | LL | if x { | ______________^ @@ -98,7 +98,7 @@ LL | | } else { | |_________^ | note: same as this - --> tests/ui/if_same_then_else.rs:240:16 + --> tests/ui/if_same_then_else.rs:230:16 | LL | } else { | ________________^ @@ -106,5 +106,209 @@ LL | | 0_u8.is_power_of_two() LL | | } | |_________^ -error: aborting due to 6 previous errors +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:257:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:257:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:259:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:259:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:263:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:263:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:265:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:265:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:267:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:267:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:269:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:269:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:282:14 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:282:29 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:284:14 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:284:29 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:286:14 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:286:29 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:288:14 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:288:29 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:290:14 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:290:29 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:294:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:294:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:296:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:296:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:300:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:300:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:302:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:302:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:304:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:304:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:306:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:306:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: aborting due to 23 previous errors diff --git a/tests/ui/int_plus_one.fixed b/tests/ui/int_plus_one.fixed index a1aba6bf7f64..cdd19515e9a7 100644 --- a/tests/ui/int_plus_one.fixed +++ b/tests/ui/int_plus_one.fixed @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index f804fc9047de..8d7d2e8982d8 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x >= y + 1; - //~^ int_plus_one - let _ = y + 1 <= x; - //~^ int_plus_one + let _ = x >= y + 1; //~ int_plus_one + let _ = x >= 1 + y; //~ int_plus_one + let _ = y + 1 <= x; //~ int_plus_one + let _ = 1 + y <= x; //~ int_plus_one - let _ = x - 1 >= y; - //~^ int_plus_one - let _ = y <= x - 1; - //~^ int_plus_one + let _ = x - 1 >= y; //~ int_plus_one + let _ = -1 + x >= y; //~ int_plus_one + let _ = y <= x - 1; //~ int_plus_one + let _ = y <= -1 + x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 052706028141..8bdff5680bdc 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -7,23 +7,47 @@ LL | let _ = x >= y + 1; = note: `-D clippy::int-plus-one` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::int_plus_one)]` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:8:13 + | +LL | let _ = x >= 1 + y; + | ^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:9:13 | LL | let _ = y + 1 <= x; | ^^^^^^^^^^ help: change it to: `y < x` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:10:13 + | +LL | let _ = 1 + y <= x; + | ^^^^^^^^^^ help: change it to: `y < x` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:12:13 | LL | let _ = x - 1 >= y; | ^^^^^^^^^^ help: change it to: `x > y` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:13:13 + | +LL | let _ = -1 + x >= y; + | ^^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:14:13 | LL | let _ = y <= x - 1; | ^^^^^^^^^^ help: change it to: `y < x` -error: aborting due to 4 previous errors +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:15:13 + | +LL | let _ = y <= -1 + x; + | ^^^^^^^^^^^ help: change it to: `y < x` + +error: aborting due to 8 previous errors diff --git a/tests/ui/manual_checked_ops.rs b/tests/ui/manual_checked_ops.rs new file mode 100644 index 000000000000..93630faa1086 --- /dev/null +++ b/tests/ui/manual_checked_ops.rs @@ -0,0 +1,72 @@ +#![warn(clippy::manual_checked_ops)] + +fn main() { + let mut a = 10u32; + let mut b = 5u32; + + // Should trigger lint + if b != 0 { + //~^ manual_checked_ops + let _result = a / b; + let _another = (a + 1) / b; + } + + // Should trigger lint (compound assignment) + if b != 0 { + //~^ manual_checked_ops + a /= b; + } + + if b > 0 { + //~^ manual_checked_ops + let _result = a / b; + } + + if b == 0 { + //~^ manual_checked_ops + println!("zero"); + } else { + let _result = a / b; + } + + // Should NOT trigger (already using checked_div) + if let Some(result) = b.checked_div(a) { + println!("{result}"); + } + + // Should NOT trigger (signed integers are not linted) + let c = -5i32; + if c != 0 { + let _result = 10 / c; + } + + // Should NOT trigger (side effects in divisor) + if counter() > 0 { + let _ = 32 / counter(); + } + + // Should NOT trigger (divisor used before division) + if b > 0 { + use_value(b); + let _ = a / b; + } + + // Should NOT trigger (divisor may change during evaluation) + if b > 0 { + g(inc_and_return_value(&mut b), a / b); + } +} + +fn counter() -> u32 { + println!("counter"); + 1 +} + +fn use_value(_v: u32) {} + +fn inc_and_return_value(x: &mut u32) -> u32 { + *x += 1; + *x +} + +fn g(_lhs: u32, _rhs: u32) {} diff --git a/tests/ui/manual_checked_ops.stderr b/tests/ui/manual_checked_ops.stderr new file mode 100644 index 000000000000..311f319bad14 --- /dev/null +++ b/tests/ui/manual_checked_ops.stderr @@ -0,0 +1,50 @@ +error: manual checked division + --> tests/ui/manual_checked_ops.rs:8:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here +LL | let _another = (a + 1) / b; + | ----------- ... and here + | + = help: consider using `checked_div` + = note: `-D clippy::manual-checked-ops` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_checked_ops)]` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:15:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | a /= b; + | ------ division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:20:8 + | +LL | if b > 0 { + | ^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:25:8 + | +LL | if b == 0 { + | ^^^^^^ check performed here +... +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/manual_take.fixed b/tests/ui/manual_take.fixed new file mode 100644 index 000000000000..5891bd49c81c --- /dev/null +++ b/tests/ui/manual_take.fixed @@ -0,0 +1,57 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = !std::mem::take(&mut x); + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + std::mem::take(&mut x) +} diff --git a/tests/ui/manual_take.rs b/tests/ui/manual_take.rs new file mode 100644 index 000000000000..89903fcb2416 --- /dev/null +++ b/tests/ui/manual_take.rs @@ -0,0 +1,69 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + if x { + //~^ manual_take + x = false; + true + } else { + false + } +} diff --git a/tests/ui/manual_take.stderr b/tests/ui/manual_take.stderr new file mode 100644 index 000000000000..69ba7778a275 --- /dev/null +++ b/tests/ui/manual_take.stderr @@ -0,0 +1,53 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:9:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !std::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:62:5 + | +LL | / if x { +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | } + | |_____^ + | +help: use + | +LL - if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - } +LL + std::mem::take(&mut x) + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/manual_take_nocore.rs b/tests/ui/manual_take_nocore.rs new file mode 100644 index 000000000000..ef4f23395028 --- /dev/null +++ b/tests/ui/manual_take_nocore.rs @@ -0,0 +1,37 @@ +//@ check-pass +#![feature(no_core, lang_items)] +#![no_core] +#![allow(clippy::missing_safety_doc)] +#![warn(clippy::manual_take)] + +#[link(name = "c")] +unsafe extern "C" {} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub unsafe trait Freeze {} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() { + let mut x = true; + // this should not lint because we don't have std nor core + let _manual_take = if x { + x = false; + true + } else { + false + }; +} diff --git a/tests/ui/manual_take_nostd.fixed b/tests/ui/manual_take_nostd.fixed new file mode 100644 index 000000000000..123c5a91998c --- /dev/null +++ b/tests/ui/manual_take_nostd.fixed @@ -0,0 +1,10 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = !core::mem::take(&mut x); + + let _lint = core::mem::take(&mut x); +} diff --git a/tests/ui/manual_take_nostd.rs b/tests/ui/manual_take_nostd.rs new file mode 100644 index 000000000000..0df352477b74 --- /dev/null +++ b/tests/ui/manual_take_nostd.rs @@ -0,0 +1,22 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _lint = if x { + //~^ manual_take + x = false; + true + } else { + false + }; +} diff --git a/tests/ui/manual_take_nostd.stderr b/tests/ui/manual_take_nostd.stderr new file mode 100644 index 000000000000..71a5066e4db3 --- /dev/null +++ b/tests/ui/manual_take_nostd.stderr @@ -0,0 +1,54 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:7:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !core::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:15:17 + | +LL | let _lint = if x { + | _________________^ +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | }; + | |_____^ + | +help: use + | +LL - let _lint = if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - }; +LL + let _lint = core::mem::take(&mut x); + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index fba81cb493cd..dccacd7df8af 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -156,3 +156,11 @@ mod issue_10579 { println!("{y:?}"); } } + +fn issue15752() { + struct Foo<'a>(&'a [u32]); + + let x = Some(Foo(&[1, 2, 3])); + x.map(|y| y.0).unwrap_or(&[]); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index df0207c420e6..bd9e0eeb0bda 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -232,5 +232,11 @@ LL - let _ = opt.map(|x| x > 5).unwrap_or(false); LL + let _ = opt.is_some_and(|x| x > 5); | -error: aborting due to 15 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or.rs:164:5 + | +LL | x.map(|y| y.0).unwrap_or(&[]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed index 90f3cf8bab04..dca2536132d7 100644 --- a/tests/ui/map_unwrap_or_fixable.fixed +++ b/tests/ui/map_unwrap_or_fixable.fixed @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -51,3 +56,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", o.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or_else(|()| 3, |y| y + 1)); + //~^ map_unwrap_or + + println!("{}", r.is_ok_and(|y| y == 1)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or_else(|_| 3, |y| y + 1)); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index 1078c7a3cf34..c60cb082ae3c 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -57,3 +62,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + //~^ map_unwrap_or + + println!("{}", r.map(|y| y == 1).unwrap_or(false)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 99e660f8dbd1..33a865d6769c 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:16:13 + --> tests/ui/map_unwrap_or_fixable.rs:21:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -11,7 +11,7 @@ LL | | .unwrap_or_else(|| 0); = help: to override `-D warnings` add `#[allow(clippy::map_unwrap_or)]` error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:47:13 + --> tests/ui/map_unwrap_or_fixable.rs:52:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -19,5 +19,89 @@ LL | let _ = res.map(|x| x + 1) LL | | .unwrap_or_else(|_e| 0); | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 2 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:69:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", o.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", o.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:71:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `o.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:73:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", r.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", r.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:75:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r.map_or_else(|()| 3, |y| y + 1)` + +error: called `map().unwrap_or(false)` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:78:20 + | +LL | println!("{}", r.map(|y| y == 1).unwrap_or(false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_ok_and()` instead + | +LL - println!("{}", r.map(|y| y == 1).unwrap_or(false)); +LL + println!("{}", r.is_ok_and(|y| y == 1)); + | + +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:84:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:88:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:92:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:96:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|_| 3, |y| y + 1)` + +error: aborting due to 11 previous errors diff --git a/tests/ui/missing_trait_methods.rs b/tests/ui/missing_trait_methods.rs index 7af186ba3322..67070a299951 100644 --- a/tests/ui/missing_trait_methods.rs +++ b/tests/ui/missing_trait_methods.rs @@ -62,3 +62,10 @@ impl MissingMultiple for Partial {} //~| missing_trait_methods fn main() {} + +//~v missing_trait_methods +impl PartialEq for Partial { + fn eq(&self, other: &Partial) -> bool { + todo!() + } +} diff --git a/tests/ui/missing_trait_methods.stderr b/tests/ui/missing_trait_methods.stderr index d9fb8951ab3d..e5155ad587cb 100644 --- a/tests/ui/missing_trait_methods.stderr +++ b/tests/ui/missing_trait_methods.stderr @@ -60,5 +60,13 @@ help: implement the method LL | fn three() {} | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: missing trait method provided by default: `ne` + --> tests/ui/missing_trait_methods.rs:67:1 + | +LL | impl PartialEq for Partial { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: implement the missing `ne` method of the `PartialEq` trait + +error: aborting due to 6 previous errors diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index 99027e79b664..2d59c1d42b05 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + + iter.chain([1, 2]).map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + + //~^ needless_collect + + iter.chain(s).map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + + //~^ needless_collect + + + [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + + //~^ needless_collect + + + + + + + + [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + } +} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 683cc49c9af3..346cddd88e70 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.push(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_back(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + let mut ll = iter.collect::>(); + //~^ needless_collect + ll.extend(s); + ll.into_iter().map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_front(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_back(2); + v.push_front(3); + v.extend(iter2); + v.push_back(4); + v.push_front(5); + v.push_back(6); + v.into_iter().map(|x| x + 1).collect() + } +} diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index c77674dc55d4..b10312224c8e 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -121,5 +121,115 @@ error: avoid using `collect()` when not needed LL | baz((0..10), (), ('a'..='z').collect::>()) | ^^^^^^^^^^^^^^^^^^^^ help: remove this call -error: aborting due to 20 previous errors +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:228:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:240:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ iter.chain([1, 2]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:248:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:268:27 + | +LL | let mut ll = iter.collect::>(); + | ^^^^^^^ +... +LL | ll.into_iter().map(|x| x + 1).collect() + | -------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain(s).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:275:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:286:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + | + +error: aborting due to 26 previous errors diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 88b7905e7fa8..3275dddf1a0f 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -342,3 +342,38 @@ fn issue15548() { } } } + +fn issue16256() { + fn some_condition() -> bool { + true + } + fn another_condition() -> bool { + true + } + + for _ in 0..5 { + if some_condition() { + // ... + continue; + } + + if another_condition() { + // ... + // "this `continue` expression is redundant" is posted on + // the `continue` node. + #[expect(clippy::needless_continue)] + continue; + } + } + + for _ in 0..5 { + // "This `else` block is redundant" is posted on the + // `else` node. + #[expect(clippy::needless_continue)] + if some_condition() { + // ... + } else { + continue; + } + } +} diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index 15ca409c95bd..90a07454b4d7 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index af9649d72987..6df38897f42d 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index 3d416056226c..559c1bb94570 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -146,3 +146,39 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + + let mut stdin = stdin().lock().take(40); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + drop(stdin); + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + drop(lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index d9c4ad543593..dff36baf383d 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -142,3 +142,36 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + let stdin = stdin().lock(); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + let mut stdin = stdin.take(40); + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index 25cd9da73a10..785bee4970ec 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -83,5 +83,74 @@ LL | LL ~ | -error: aborting due to 4 previous errors +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:151:9 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let stdin = stdin().lock(); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: merge the temporary construction with its single usage + | +LL ~ +LL + let mut stdin = stdin().lock().take(40); +LL | +LL | let mut buffer = String::with_capacity(10); +LL | +LL ~ + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:155:13 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let mut stdin = stdin.take(40); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ } +LL + drop(stdin); + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:171:9 + | +LL | fn issue16343() { + | _________________- +LL | | fn get_items(x: &()) -> Vec<()> { +LL | | vec![*x] +... | +LL | | let lock = storage.lock().unwrap(); + | | ^^^^ +... | +LL | | } + | |_- temporary `lock` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ let items = get_items(&lock); +LL + drop(lock); + | + +error: aborting due to 7 previous errors diff --git a/tests/ui/strlen_on_c_strings.fixed b/tests/ui/strlen_on_c_strings.fixed index 17c1b541f77c..6604da70874d 100644 --- a/tests/ui/strlen_on_c_strings.fixed +++ b/tests/ui/strlen_on_c_strings.fixed @@ -1,37 +1,68 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); - let _ = cstring.as_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; - let _ = unsafe { (*pcstr).to_bytes().len() }; - //~^ strlen_on_c_strings + let _ = unsafe { (*pcstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } - let _ = unsafe { unsafe_identity(cstr).to_bytes().len() }; - //~^ strlen_on_c_strings - let _ = unsafe { unsafe_identity(cstr) }.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = unsafe { unsafe_identity(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value + let _ = unsafe { unsafe_identity(cstr) }.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; - let _ = unsafe { f(cstr).to_bytes().len() }; + let _ = unsafe { f(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = box_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = box_cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = arc_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.to_bytes().len(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.to_bytes().len(); + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.count_bytes(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.count_bytes(); //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.rs b/tests/ui/strlen_on_c_strings.rs index c641422f5df4..11fbdf585064 100644 --- a/tests/ui/strlen_on_c_strings.rs +++ b/tests/ui/strlen_on_c_strings.rs @@ -1,7 +1,6 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; @@ -9,29 +8,61 @@ fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; let _ = unsafe { strlen((*pcstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; let _ = unsafe { strlen(f(cstr).as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.stderr b/tests/ui/strlen_on_c_strings.stderr index 84a93b99ee33..1f1b5ccdb0ef 100644 --- a/tests/ui/strlen_on_c_strings.stderr +++ b/tests/ui/strlen_on_c_strings.stderr @@ -1,47 +1,89 @@ -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:11:13 +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:10:13 | LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstring.as_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` | = note: `-D clippy::strlen-on-c-strings` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::strlen_on_c_strings)]` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:16:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:15:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:19:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:18:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:23:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:22:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `(*pcstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:29:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:28:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe_identity(cstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:31:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:30:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe { unsafe_identity(cstr) }.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:35:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:34:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `f(cstr).count_bytes()` -error: aborting due to 7 previous errors +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:40:13 + | +LL | let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstring.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:42:13 + | +LL | let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstr.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:44:13 + | +LL | let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `arc_cstring.count_bytes()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:51:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.to_bytes().len()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:55:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.to_bytes().len()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:62:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:66:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` + +error: aborting due to 14 previous errors diff --git a/tests/ui/suspicious_to_owned.1.fixed b/tests/ui/suspicious_to_owned.1.fixed new file mode 100644 index 000000000000..6fd536a38ed1 --- /dev/null +++ b/tests/ui/suspicious_to_owned.1.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/tests/ui/suspicious_to_owned.2.fixed b/tests/ui/suspicious_to_owned.2.fixed new file mode 100644 index 000000000000..841adf8ea274 --- /dev/null +++ b/tests/ui/suspicious_to_owned.2.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/tests/ui/suspicious_to_owned.rs b/tests/ui/suspicious_to_owned.rs index 2eec05ccaf4c..f59b3fd6ed0c 100644 --- a/tests/ui/suspicious_to_owned.rs +++ b/tests/ui/suspicious_to_owned.rs @@ -1,4 +1,3 @@ -//@no-rustfix: overlapping suggestions #![warn(clippy::suspicious_to_owned)] #![warn(clippy::implicit_clone)] #![allow(clippy::redundant_clone)] diff --git a/tests/ui/suspicious_to_owned.stderr b/tests/ui/suspicious_to_owned.stderr index f90bea5fb8ff..5fda1ed1cc9c 100644 --- a/tests/ui/suspicious_to_owned.stderr +++ b/tests/ui/suspicious_to_owned.stderr @@ -1,71 +1,71 @@ -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:17:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:16:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | = note: `-D clippy::suspicious-to-owned` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_to_owned)]` -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned - --> tests/ui/suspicious_to_owned.rs:29:13 +error: this `to_owned` call clones the `Cow<'_, [char; 3]>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:28:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, Vec> itself and does not cause the Cow<'_, Vec> contents to become owned - --> tests/ui/suspicious_to_owned.rs:41:13 +error: this `to_owned` call clones the `Cow<'_, Vec>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:40:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:53:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:52:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:69:13 + --> tests/ui/suspicious_to_owned.rs:68:13 | LL | let _ = String::from(moo).to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::from(moo).clone()` @@ -74,7 +74,7 @@ LL | let _ = String::from(moo).to_owned(); = help: to override `-D warnings` add `#[allow(clippy::implicit_clone)]` error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:72:13 + --> tests/ui/suspicious_to_owned.rs:71:13 | LL | let _ = moos_vec.to_owned(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `moos_vec.clone()` diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index 00aa35dff803..efa4c5cfdc2d 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -47,9 +47,20 @@ fn transumute_single_expr_blocks() { } } +fn transmute_pointer_creators() { + unsafe { + let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + //~^ transmuting_null + + let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + //~^ transmuting_null + } +} + fn main() { one_liners(); transmute_const(); transmute_const_int(); transumute_single_expr_blocks(); + transmute_pointer_creators(); } diff --git a/tests/ui/transmuting_null.stderr b/tests/ui/transmuting_null.stderr index e1de391813bd..3c6c28f31d0d 100644 --- a/tests/ui/transmuting_null.stderr +++ b/tests/ui/transmuting_null.stderr @@ -37,5 +37,17 @@ error: transmuting a known null pointer into a reference LL | let _: &u64 = std::mem::transmute(const { u64::MIN as *const u64 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:52:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:55:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 10552431d65d..52c114339292 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -70,7 +70,7 @@ fn main() { let _ = r.is_ok_and(|x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.is_ok_and(func); diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 4b406ec2998b..dd2e1a569469 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -74,7 +74,7 @@ fn main() { let _ = r.map_or(false, |x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.map_or(false, func); diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index b8a22346c378..d11e7179f921 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -56,7 +56,7 @@ LL | | 6 >= 5 LL | | }); | |______^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| { LL + let _ = Some(5).is_some_and(|n| { @@ -68,7 +68,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Some(vec![5]).is_some_and(|n| n == [5]); @@ -80,7 +80,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); LL + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); @@ -92,7 +92,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == n); LL + let _ = Some(5).is_some_and(|n| n == n); @@ -104,7 +104,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); LL + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); @@ -116,7 +116,7 @@ error: this `map_or` can be simplified LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); @@ -152,7 +152,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| n == 5); LL + let _ = Some(5).is_none_or(|n| n == 5); @@ -164,7 +164,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| 5 == n); LL + let _ = Some(5).is_none_or(|n| 5 == n); @@ -212,7 +212,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, |x| x == 7); LL + let _ = r.is_ok_and(|x| x == 7); @@ -224,7 +224,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, func); LL + let _ = r.is_ok_and(func); @@ -236,7 +236,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, func); LL + let _ = Some(5).is_some_and(func); @@ -248,7 +248,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, func); LL + let _ = Some(5).is_none_or(func); @@ -272,7 +272,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.is_none_or(|n| n > 5) || (o as &Option).map_or(true, |n| n < 5) @@ -284,7 +284,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.map_or(true, |n| n > 5) || (o as &Option).is_none_or(|n| n < 5) @@ -296,7 +296,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) LL + o.is_none_or(|n| n > 5) @@ -308,7 +308,7 @@ error: this `map_or` can be simplified LL | let x = a.map_or(false, |a| a == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let x = a.map_or(false, |a| a == *s); LL + let x = a.is_some_and(|a| a == *s); @@ -320,7 +320,7 @@ error: this `map_or` can be simplified LL | let y = b.map_or(true, |b| b == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let y = b.map_or(true, |b| b == *s); LL + let y = b.is_none_or(|b| b == *s); @@ -356,7 +356,7 @@ error: this `map_or` can be simplified LL | _ = s.lock().unwrap().map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.lock().unwrap().map_or(false, |s| s == "foo"); LL + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); @@ -368,7 +368,7 @@ error: this `map_or` can be simplified LL | _ = s.map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.map_or(false, |s| s == "foo"); LL + _ = s.is_some_and(|s| s == "foo"); diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 5255ab173efb..6870470e74c5 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by_key(|a| a.0); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by_key(|item1| item1.key); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by_key(|item1| item1.value.clone()); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by_key(|(_, s1)| *s1); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by_key(|Foo { bar: b1 }| *b1); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by_key(|Baz(b1)| *b1); + //~^ unnecessary_sort_by + + v.sort_by_key(|&Baz(b1)| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by_key(|&&b1| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by_key(|[a1, b1]| *a1); + //~^ unnecessary_sort_by + + v.sort_by_key(|[a1, b1]| a1 - b1); + //~^ unnecessary_sort_by +} diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 65db7ca3f137..d95306176817 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by(|a, b| a.0.cmp(&b.0)); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + //~^ unnecessary_sort_by + + v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + //~^ unnecessary_sort_by + + v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + //~^ unnecessary_sort_by +} diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index a066554037fe..cc545d604ff3 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -2,76 +2,267 @@ error: consider using `sort` --> tests/ui/unnecessary_sort_by.rs:12:5 | LL | vec.sort_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| a.cmp(b)); +LL + vec.sort(); + | error: consider using `sort_unstable` --> tests/ui/unnecessary_sort_by.rs:14:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| a.cmp(b)); +LL + vec.sort_unstable(); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); +LL + vec.sort_by_key(|a| (a + 5).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); +LL + vec.sort_unstable_by_key(|a| id(-a)); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:22:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); +LL + vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:24:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); +LL + vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b))); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:35:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_by_key(|a| (***a).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:37:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_unstable_by_key(|a| (***a).abs()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:97:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_by_key(|a| a.name()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:99:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_unstable_by_key(|a| a.name()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:102:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_by_key(|b| std::cmp::Reverse(b.name())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:104:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); + | -error: aborting due to 12 previous errors +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:118:5 + | +LL | v.sort_by(|a, b| a.0.cmp(&b.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|a, b| a.0.cmp(&b.0)); +LL + v.sort_by_key(|a| a.0); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:136:5 + | +LL | items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); +LL + items.sort_by_key(|item1| item1.key); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:141:5 + | +LL | items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); +LL + items.sort_by_key(|item1| item1.value.clone()); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:147:5 + | +LL | v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); +LL + v.sort_by_key(|(_, s1)| *s1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:154:5 + | +LL | v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); +LL + v.sort_by_key(|Foo { bar: b1 }| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:159:5 + | +LL | v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); +LL + v.sort_by_key(|Baz(b1)| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:162:5 + | +LL | v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); +LL + v.sort_by_key(|&Baz(b1)| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:166:5 + | +LL | v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); +LL + v.sort_by_key(|&&b1| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:170:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); +LL + v.sort_by_key(|[a1, b1]| *a1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:173:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); +LL + v.sort_by_key(|[a1, b1]| a1 - b1); + | + +error: aborting due to 22 previous errors diff --git a/tests/ui/unnecessary_sort_by_no_core.rs b/tests/ui/unnecessary_sort_by_no_core.rs new file mode 100644 index 000000000000..cb0da6339cb3 --- /dev/null +++ b/tests/ui/unnecessary_sort_by_no_core.rs @@ -0,0 +1,26 @@ +//@check-pass +#![feature(no_core)] +#![no_std] +#![no_core] +extern crate alloc; +extern crate core as mycore; +use alloc::vec; +use alloc::vec::Vec; +use mycore::cmp::Ord as _; + +fn issue_11524() -> Vec { + let mut vec = vec![1, 2, 3]; + + // We could lint and suggest `vec.sort_by_key(|a| a + 1);`, but we don't bother to -- see the + // comment in the lint at line 194 + vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); + vec +} + +fn issue_11524_2() -> Vec { + let mut vec = vec![1, 2, 3]; + + // Should not lint, as even `vec.sort_by_key(|b| core::cmp::Reverse(b + 1));` would not compile + vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); + vec +} diff --git a/tests/ui/unnecessary_sort_by_no_std.stderr b/tests/ui/unnecessary_sort_by_no_std.stderr index de3ef4123514..b4dd6a6dbdc5 100644 --- a/tests/ui/unnecessary_sort_by_no_std.stderr +++ b/tests/ui/unnecessary_sort_by_no_std.stderr @@ -2,16 +2,27 @@ error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:10:5 | LL | vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| a + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); +LL + vec.sort_by_key(|a| a + 1); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:19:5 | LL | vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| core::cmp::Reverse(b + 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); +LL + vec.sort_by_key(|b| core::cmp::Reverse(b + 1)); + | error: aborting due to 2 previous errors diff --git a/tests/ui/while_let_loop.rs b/tests/ui/while_let_loop.rs index f28c504742fd..b5a362669ce2 100644 --- a/tests/ui/while_let_loop.rs +++ b/tests/ui/while_let_loop.rs @@ -253,3 +253,24 @@ fn let_assign() { } } } + +fn issue16378() { + // This does not lint today because of the extra statement(s) + // before the `break`. + // TODO: When the `break` statement/expr in the `let`/`else` is the + // only way to leave the loop, the lint could trigger and move + // the statements preceeding the `break` after the loop, as in: + // ```rust + // while let Some(x) = std::hint::black_box(None::) { + // println!("x = {x}"); + // } + // println!("fail"); + // ``` + loop { + let Some(x) = std::hint::black_box(None::) else { + println!("fail"); + break; + }; + println!("x = {x}"); + } +} From 1ebafc50427639355278cbd1bf83977f8589f451 Mon Sep 17 00:00:00 2001 From: "Matheus L. P." Date: Thu, 22 Jan 2026 16:32:35 -0600 Subject: [PATCH 039/182] fix(manual_let_else): add trailing comma when necessary Adds a trailing comma to struct patterns ending with `..`. Fixes rust-lang#16433 --- clippy_lints/src/manual_let_else.rs | 2 +- tests/ui/manual_let_else_match.fixed | 15 ++++++++++++++- tests/ui/manual_let_else_match.rs | 19 ++++++++++++++++++- tests/ui/manual_let_else_match.stderr | 12 +++++++++++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 38ee4ce104a5..cb3cc999c936 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -301,7 +301,7 @@ fn replace_in_pattern( .collect::>(); let fields_string = fields.join(", "); - let dot_dot_str = if dot_dot.is_some() { " .." } else { "" }; + let dot_dot_str = if dot_dot.is_some() { ", .." } else { "" }; let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); }, diff --git a/tests/ui/manual_let_else_match.fixed b/tests/ui/manual_let_else_match.fixed index 15f604aec292..9cdf394e9ee4 100644 --- a/tests/ui/manual_let_else_match.fixed +++ b/tests/ui/manual_let_else_match.fixed @@ -1,4 +1,4 @@ -#![allow(unused_braces, unused_variables, dead_code)] +#![allow(unused_braces, unused_variables, dead_code, irrefutable_let_patterns)] #![allow( clippy::collapsible_else_if, clippy::let_unit_value, @@ -182,3 +182,16 @@ fn issue9939b() { let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") }; assert!(erosion); } + +mod issue16433 { + // https://github.com/rust-lang/rust-clippy/issues/16433 + struct A { + a: u32, + b: u32, + } + + fn foo() { + let a = A { a: 1, b: 1 }; + let A { a: first_arg, .. } = a else { return }; + } +} diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 44a044b142bd..b1a20551e584 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -1,4 +1,4 @@ -#![allow(unused_braces, unused_variables, dead_code)] +#![allow(unused_braces, unused_variables, dead_code, irrefutable_let_patterns)] #![allow( clippy::collapsible_else_if, clippy::let_unit_value, @@ -250,3 +250,20 @@ fn issue9939b() { }; assert!(erosion); } + +mod issue16433 { + // https://github.com/rust-lang/rust-clippy/issues/16433 + struct A { + a: u32, + b: u32, + } + + fn foo() { + let a = A { a: 1, b: 1 }; + let first_arg = match a { + //~^ manual_let_else + A { a, .. } => a, + _ => return, + }; + } +} diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index ed6117ebffb7..6bbfb0e84d95 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -171,5 +171,15 @@ LL | | None => unreachable!("can't happen"), LL | | }; | |______^ help: consider writing: `let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") };` -error: aborting due to 17 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:263:9 + | +LL | / let first_arg = match a { +LL | | +LL | | A { a, .. } => a, +LL | | _ => return, +LL | | }; + | |__________^ help: consider writing: `let A { a: first_arg, .. } = a else { return };` + +error: aborting due to 18 previous errors From 3157c0b674d90ced9fd6b5c8e8654b0c1a31bf5b Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 16 Jan 2026 23:02:25 +0100 Subject: [PATCH 040/182] reduce suggestion diff Now, only `call_span` is replaced, so the receiver is not a part of the diff. This also removes the need to create a snippet for the receiver. --- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/str_split.rs | 31 +++++++---- tests/ui/str_split.stderr | 79 +++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 659a704a1ecb..36f69159e847 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -5538,7 +5538,7 @@ impl Methods { unnecessary_sort_by::check(cx, expr, recv, arg, true); }, (sym::split, [arg]) => { - str_split::check(cx, expr, recv, arg); + str_split::check(cx, expr, recv, call_span, arg); }, (sym::splitn | sym::rsplitn, [count_arg, pat_arg]) => { if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) { diff --git a/clippy_lints/src/methods/str_split.rs b/clippy_lints/src/methods/str_split.rs index 9644b2c774b5..8641f7c0abec 100644 --- a/clippy_lints/src/methods/str_split.rs +++ b/clippy_lints/src/methods/str_split.rs @@ -1,20 +1,26 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_context; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sym; use clippy_utils::visitors::is_const_evaluatable; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_span::Span; use super::STR_SPLIT_AT_NEWLINE; -pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &'a Expr<'_>, split_arg: &'_ Expr<'_>) { +pub(super) fn check<'a>( + cx: &LateContext<'a>, + expr: &'_ Expr<'_>, + split_recv: &'a Expr<'_>, + split_span: Span, + split_arg: &'_ Expr<'_>, +) { // We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. an // expression returning `String`), and `B` is a `Pattern` that hard-codes a newline (either `"\n"` // or `"\r\n"`). There are a lot of ways to specify a pattern, and this lint only checks the most // basic ones: a `'\n'`, `"\n"`, and `"\r\n"`. - if let ExprKind::MethodCall(trim_method_name, trim_recv, [], _) = split_recv.kind + if let ExprKind::MethodCall(trim_method_name, trim_recv, [], trim_span) = split_recv.kind && trim_method_name.ident.name == sym::trim && cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str() && !is_const_evaluatable(cx, trim_recv) @@ -24,18 +30,19 @@ pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &' LitKind::Char('\n') | LitKind::Str(sym::LF | sym::CRLF, _) ) { - let mut app = Applicability::MaybeIncorrect; - span_lint_and_sugg( + span_lint_and_then( cx, STR_SPLIT_AT_NEWLINE, expr.span, "using `str.trim().split()` with hard-coded newlines", - "use `str.lines()` instead", - format!( - "{}.lines()", - snippet_with_context(cx, trim_recv.span, expr.span.ctxt(), "..", &mut app).0 - ), - app, + |diag| { + diag.span_suggestion_verbose( + trim_span.to(split_span), // combine the call spans of the two methods + "use `str.lines()` instead", + "lines()", + Applicability::MaybeIncorrect, + ); + }, ); } } diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr index 40202c8ac47a..1ab755008e56 100644 --- a/tests/ui/str_split.stderr +++ b/tests/ui/str_split.stderr @@ -2,64 +2,123 @@ error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:58:13 | LL | let _ = s1.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::str-split-at-newline` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]` +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split('\n'); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:61:13 | LL | let _ = s1.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split("\n"); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:63:13 | LL | let _ = s1.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split("\r\n"); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:67:13 | LL | let _ = s2.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split('\n'); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:70:13 | LL | let _ = s2.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split("\n"); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:72:13 | LL | let _ = s2.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split("\r\n"); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:77:13 | LL | let _ = s3.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split('\n'); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:80:13 | LL | let _ = s3.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split("\n"); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:82:13 | LL | let _ = s3.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split("\r\n"); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:86:13 | LL | let _ = make_str!(s1).trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = make_str!(s1).trim().split('\n'); +LL + let _ = make_str!(s1).lines(); + | error: aborting due to 10 previous errors From 4e4651b0457166674cff7dcf25410a3a9a95e811 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 25 Dec 2025 10:51:54 +0000 Subject: [PATCH 041/182] Return ExitCode from rustc_driver::main This makes rustc simply return an exit code from main rather than calling `std::process::exit` with an exit code. This means that drops run normally and the process exits cleanly. Also instead of hard coding success and failure codes this uses `ExitCode::SUCCESS` and `ExitCode::FAILURE`, which in turn effectively uses `libc::EXIT_SUCCESS` and `libc::EXIT_FAILURE` (via std). These are `0` and `1` respectively for all currently supported host platforms so it doesn't actually change the exit code. --- src/driver.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 7425da70df90..cf06f43e8d4a 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -32,7 +32,7 @@ use std::env; use std::fs::read_to_string; use std::io::Write as _; use std::path::Path; -use std::process::exit; +use std::process::ExitCode; /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. @@ -182,15 +182,17 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } } -fn display_help() { +fn display_help() -> ExitCode { if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { - exit(rustc_driver::EXIT_FAILURE); + ExitCode::FAILURE + } else { + ExitCode::SUCCESS } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; -pub fn main() { +pub fn main() -> ExitCode { let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::init_rustc_env_logger(&early_dcx); @@ -203,7 +205,7 @@ pub fn main() { dcx.handle().note(format!("Clippy version: {version_info}")); }); - exit(rustc_driver::catch_with_exit_code(move || { + rustc_driver::catch_with_exit_code(move || { let mut orig_args = rustc_driver::args::raw_args(&early_dcx); let has_sysroot_arg = |args: &mut [String]| -> bool { @@ -246,15 +248,15 @@ pub fn main() { pass_sysroot_env_if_given(&mut args, sys_root_env); rustc_driver::run_compiler(&args, &mut DefaultCallbacks); - return; + return ExitCode::SUCCESS; } if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - match writeln!(&mut anstream::stdout().lock(), "{version_info}") { - Ok(()) => exit(rustc_driver::EXIT_SUCCESS), - Err(_) => exit(rustc_driver::EXIT_FAILURE), + return match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => ExitCode::SUCCESS, + Err(_) => ExitCode::FAILURE, } } @@ -268,8 +270,7 @@ pub fn main() { } if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { - display_help(); - exit(0); + return display_help(); } let mut args: Vec = orig_args.clone(); @@ -311,7 +312,8 @@ pub fn main() { } else { rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); } - })) + ExitCode::SUCCESS + }) } #[must_use] From 0cb56dc92ca0f716a6e1512ce93ff5223bb191c9 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 13 Jan 2026 16:52:02 +0200 Subject: [PATCH 042/182] abi: add a rust-preserve-none calling convention This is the conceptual opposite of the rust-cold calling convention and is particularly useful in combination with the new `explicit_tail_calls` feature. For relatively tight loops implemented with tail calling (`become`) each of the function with the regular calling convention is still responsible for restoring the initial value of the preserved registers. So it is not unusual to end up with a situation where each step in the tail call loop is spilling and reloading registers, along the lines of: foo: push r12 ; do things pop r12 jmp next_step This adds up quickly, especially when most of the clobberable registers are already used to pass arguments or other uses. I was thinking of making the name of this ABI a little less LLVM-derived and more like a conceptual inverse of `rust-cold`, but could not come with a great name (`rust-cold` is itself not a great name: cold in what context? from which perspective? is it supposed to mean that the function is rarely called?) --- src/abi.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/abi.rs b/src/abi.rs index cc2c9fca94df..56ed7c01ed20 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -243,6 +243,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option> { let attribute = match conv { CanonAbi::C | CanonAbi::Rust => return None, + // gcc/gccjit does not have anything for this. + CanonAbi::RustPreserveNone => return None, CanonAbi::RustCold => FnAttribute::Cold, // Functions with this calling convention can only be called from assembly, but it is // possible to declare an `extern "custom"` block, so the backend still needs a calling From 58156c5cab242898ab0130b7a428b7e14bf3a066 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 24 Jan 2026 11:45:53 -0500 Subject: [PATCH 043/182] Fix segfault related to __builtin_unreachable with inline asm --- src/asm.rs | 4 +--- tests/run/unreachable-function.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/run/unreachable-function.rs diff --git a/src/asm.rs b/src/asm.rs index ceb3dd3ffedf..319f3d327873 100644 --- a/src/asm.rs +++ b/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/tests/run/unreachable-function.rs b/tests/run/unreachable-function.rs new file mode 100644 index 000000000000..0a975487dd78 --- /dev/null +++ b/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); +} From e4d146e0c315328f53edd1140e74a4ba84e6689a Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 24 Jan 2026 21:19:56 +0000 Subject: [PATCH 044/182] fix: `doc_markdown` add PowerShell to whitelist --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 2 +- tests/ui/doc/doc-fixable.fixed | 2 +- tests/ui/doc/doc-fixable.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index f81dd421f59b..68ef93d7cbf9 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -575,7 +575,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 849d9a613d80..2e7ef3a8b020 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -35,7 +35,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", - "PowerPC", "WebAssembly", + "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 46695dc929ab..58d8b8b33ade 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -75,7 +75,7 @@ fn test_units() { /// IPv4 IPv6 /// InfiniBand RoCE /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// PowerPC WebAssembly +/// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 4082fa5b56f4..0b1237f716fa 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -75,7 +75,7 @@ fn test_units() { /// IPv4 IPv6 /// InfiniBand RoCE /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// PowerPC WebAssembly +/// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml From cc299873b9cbc16392d3b19bdb64d059ef41d4f0 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 24 Jan 2026 21:29:16 +0000 Subject: [PATCH 045/182] fix: `test_attr_in_doctest` FP on `test_harness` --- clippy_lints/src/doc/mod.rs | 10 ++++++++-- tests/ui/test_attr_in_doctest.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index ecf7acbd7ce6..e7a984694831 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1016,6 +1016,7 @@ struct CodeTags { no_run: bool, ignore: bool, compile_fail: bool, + test_harness: bool, rust: bool, } @@ -1026,6 +1027,7 @@ impl Default for CodeTags { no_run: false, ignore: false, compile_fail: false, + test_harness: false, rust: true, } @@ -1059,7 +1061,11 @@ impl CodeTags { tags.compile_fail = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; }, - "test_harness" | "standalone_crate" => { + "test_harness" => { + tags.test_harness = true; + seen_rust_tags = !seen_other_tags || seen_rust_tags; + }, + "standalone_crate" => { seen_rust_tags = !seen_other_tags || seen_rust_tags; }, _ if item.starts_with("ignore-") => seen_rust_tags = true, @@ -1295,7 +1301,7 @@ fn check_doc<'a, Events: Iterator, Range Date: Sun, 25 Jan 2026 00:14:20 +0000 Subject: [PATCH 046/182] Enhance `question_mark` to cover `else if` --- clippy_lints/src/question_mark.rs | 8 ++++++-- tests/ui/question_mark.fixed | 9 +++++++++ tests/ui/question_mark.rs | 14 ++++++++++++++ tests/ui/question_mark.stderr | 14 +++++++++++++- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index e5fb3c0fa431..5517b7f260ea 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -474,7 +474,6 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: if_else, .. }) = higher::IfLet::hir(cx, expr) - && !is_else_clause(cx.tcx, expr) && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind && ddpos.as_opt_usize().is_none() && let PatKind::Binding(BindingMode(by_ref, _), bind_id, ident, None) = field.kind @@ -509,10 +508,15 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: ByRef::Yes(_, Mutability::Not) => ".as_ref()", ByRef::No => "", }; - let sugg = format!( + + let mut sugg = format!( "{receiver_str}{method_call_str}?{}", if requires_semi { ";" } else { "" } ); + if is_else_clause(cx.tcx, expr) { + sugg = format!("{{ {sugg} }}"); + } + span_lint_and_sugg( cx, QUESTION_MARK, diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index b8072932c4ea..102517d34c61 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -515,3 +515,12 @@ fn wrongly_unmangled_macros() -> Option { test_expr!(42)?; test_expr!(42) } + +fn issue16429(b: i32) -> Option { + let a = Some(5); + let _ = if b == 1 { + b + } else { a? }; + + Some(0) +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index b320dcd4b0bc..cfea1277fe76 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -635,3 +635,17 @@ fn wrongly_unmangled_macros() -> Option { } test_expr!(42) } + +fn issue16429(b: i32) -> Option { + let a = Some(5); + let _ = if b == 1 { + b + } else if let Some(x) = a { + //~^ question_mark + x + } else { + return None; + }; + + Some(0) +} diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index d645c8830adc..c243f12de040 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -350,5 +350,17 @@ LL | | return None; LL | | } | |_____^ help: replace it with: `test_expr!(42)?;` -error: aborting due to 37 previous errors +error: this block may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:643:12 + | +LL | } else if let Some(x) = a { + | ____________^ +LL | | +LL | | x +LL | | } else { +LL | | return None; +LL | | }; + | |_____^ help: replace it with: `{ a? }` + +error: aborting due to 38 previous errors From 8416c544ee6e26d628ece03391c4f661e2289727 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 25 Jan 2026 15:02:11 +0000 Subject: [PATCH 047/182] Also ignore cases with comments in `let_and_return` --- clippy_lints/src/returns/let_and_return.rs | 2 +- tests/ui/let_and_return.edition2021.fixed | 8 ++++++++ tests/ui/let_and_return.edition2024.fixed | 8 ++++++++ tests/ui/let_and_return.rs | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/returns/let_and_return.rs b/clippy_lints/src/returns/let_and_return.rs index 0a00981e15be..b19935959c4d 100644 --- a/clippy_lints/src/returns/let_and_return.rs +++ b/clippy_lints/src/returns/let_and_return.rs @@ -27,7 +27,7 @@ pub(super) fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>) && !initexpr.span.in_external_macro(cx.sess().source_map()) && !retexpr.span.in_external_macro(cx.sess().source_map()) && !local.span.from_expansion() - && !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), true) + && !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), false) { span_lint_hir_and_then( cx, diff --git a/tests/ui/let_and_return.edition2021.fixed b/tests/ui/let_and_return.edition2021.fixed index e89e4476bf82..6ca0febc2b8d 100644 --- a/tests/ui/let_and_return.edition2021.fixed +++ b/tests/ui/let_and_return.edition2021.fixed @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} diff --git a/tests/ui/let_and_return.edition2024.fixed b/tests/ui/let_and_return.edition2024.fixed index d2c76673ca03..0fce22936ae6 100644 --- a/tests/ui/let_and_return.edition2024.fixed +++ b/tests/ui/let_and_return.edition2024.fixed @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 1af5f8ba5c16..301f153ca8b1 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} From 4a6c0dea8bb523515e11a0af9a9dd234a68405bf Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 25 Jan 2026 18:38:20 +0100 Subject: [PATCH 048/182] rhs of short-circuit expression doesn't always run --- clippy_lints/src/loops/never_loop.rs | 4 ++++ tests/ui/never_loop.rs | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index e7b9b1cd3881..231388e7379a 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -6,6 +6,7 @@ use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{contains_return, sym}; +use rustc_ast::BinOpKind; use rustc_errors::Applicability; use rustc_hir::{ Block, Closure, Destination, Expr, ExprKind, HirId, InlineAsm, InlineAsmOperand, Node, Pat, Stmt, StmtKind, @@ -305,6 +306,9 @@ fn never_loop_expr<'tcx>( } }, ExprKind::Call(e, es) => never_loop_expr_all(cx, once(e).chain(es.iter()), local_labels, main_loop_id), + ExprKind::Binary(op, e1, _) if matches!(op.node, BinOpKind::And | BinOpKind::Or) => { + never_loop_expr(cx, e1, local_labels, main_loop_id) + }, ExprKind::Binary(_, e1, e2) | ExprKind::Assign(e1, e2, _) | ExprKind::AssignOp(_, e1, e2) diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 9769ee0c3a37..52470c6ee81b 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -546,3 +546,13 @@ fn issue15673() { return; } } + +#[expect(clippy::diverging_sub_expression, clippy::short_circuit_statement)] +fn issue16462() { + let mut n = 10; + loop { + println!("{n}"); + n -= 1; + n >= 0 || break; + } +} From 81acbae770748d42f5d368cf156e21fd786fa7f5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jan 2026 21:02:34 +0100 Subject: [PATCH 049/182] Add missing intrinsic translation for `llvm.sqrt.f32` --- src/intrinsic/llvm.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 72fc72d118b7..10183c5ee526 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1062,6 +1062,12 @@ 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 "llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd", + "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; + } "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", From d3df4bdba52b27d5bdace45b796177c891000f01 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jan 2026 21:02:55 +0100 Subject: [PATCH 050/182] Add regression test for --- tests/run/call-llvm-intrinsics.rs | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/run/call-llvm-intrinsics.rs diff --git a/tests/run/call-llvm-intrinsics.rs b/tests/run/call-llvm-intrinsics.rs new file mode 100644 index 000000000000..86e041c3a2fb --- /dev/null +++ b/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(); +} From 02d9865f9ecf81f12b38e6fc261888f2eae2c7aa Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 17 Jan 2026 20:47:47 +0000 Subject: [PATCH 051/182] Enhance `manual_is_variant_and` to cover manual `is_none_or` --- .../src/methods/manual_is_variant_and.rs | 66 ++++++++++++++++++- clippy_lints/src/methods/mod.rs | 3 + tests/ui/manual_is_variant_and.fixed | 19 ++++++ tests/ui/manual_is_variant_and.rs | 19 ++++++ tests/ui/manual_is_variant_and.stderr | 14 +++- 5 files changed, 118 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index 5ce9d364cdd8..d877b0a62291 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_parent_expr, sym}; +use clippy_utils::{SpanlessEq, get_parent_expr, sym}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -228,3 +228,65 @@ pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) { } } } + +pub(super) fn check_or<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + lhs: &'tcx Expr<'tcx>, + rhs: &'tcx Expr<'tcx>, + msrv: Msrv, +) { + let (some_recv, some_arg) = if let ( + ExprKind::MethodCall(none_path, none_recv, [], _), + ExprKind::MethodCall(some_path, some_recv, [some_arg], _), + ) + | ( + ExprKind::MethodCall(some_path, some_recv, [some_arg], _), + ExprKind::MethodCall(none_path, none_recv, [], _), + ) = (lhs.kind, rhs.kind) + && none_path.ident.name == sym::is_none + && some_path.ident.name == sym::is_some_and + && cx + .typeck_results() + .expr_ty_adjusted(none_recv) + .peel_refs() + .is_diag_item(cx, sym::Option) + && cx + .typeck_results() + .expr_ty_adjusted(some_recv) + .peel_refs() + .is_diag_item(cx, sym::Option) + && SpanlessEq::new(cx).eq_expr(none_recv, some_recv) + { + (some_recv, some_arg) + } else { + return; + }; + + if !msrv.meets(cx, msrvs::IS_NONE_OR) { + return; + } + + let Ok(map_func) = MapFunc::try_from(some_arg) else { + return; + }; + + span_lint_and_then( + cx, + MANUAL_IS_VARIANT_AND, + expr.span, + "manual implementation of `Option::is_none_or`", + |diag| { + let mut app = Applicability::MachineApplicable; + let (recv_snip, _) = snippet_with_context(cx, some_recv.span, expr.span.ctxt(), "_", &mut app); + let map_func_snip = map_func.sugg(cx, false, &mut app); + + diag.span_suggestion( + expr.span, + "use", + format!("{recv_snip}.is_none_or({map_func_snip})"), + app, + ); + }, + ); +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 659a704a1ecb..08a472a5d4c4 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4978,6 +4978,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { }; lint_binary_expr_with_method_call(cx, &mut info); }, + ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Or => { + manual_is_variant_and::check_or(cx, expr, lhs, rhs, self.msrv); + }, _ => (), } } diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed index 65a9cfa6e64c..884bef6af5f9 100644 --- a/tests/ui/manual_is_variant_and.fixed +++ b/tests/ui/manual_is_variant_and.fixed @@ -226,3 +226,22 @@ mod with_func { assert_eq!(a1, a2); } } + +fn issue16419() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none_or(then_fn); + //~^ manual_is_variant_and + + let _ = opt.is_none_or(then_fn); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16419_msrv() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + + let _ = opt.is_some_and(then_fn) || opt.is_none(); +} diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs index 85b45d654a7d..53aca94ea370 100644 --- a/tests/ui/manual_is_variant_and.rs +++ b/tests/ui/manual_is_variant_and.rs @@ -235,3 +235,22 @@ mod with_func { assert_eq!(a1, a2); } } + +fn issue16419() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + //~^ manual_is_variant_and + + let _ = opt.is_some_and(then_fn) || opt.is_none(); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16419_msrv() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + + let _ = opt.is_some_and(then_fn) || opt.is_none(); +} diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr index da36b5a07d21..56c3b80c0aa5 100644 --- a/tests/ui/manual_is_variant_and.stderr +++ b/tests/ui/manual_is_variant_and.stderr @@ -222,5 +222,17 @@ error: called `.map() != Ok()` LL | let a1 = b.map(iad) != Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(|x| !iad(x))` -error: aborting due to 31 previous errors +error: manual implementation of `Option::is_none_or` + --> tests/ui/manual_is_variant_and.rs:242:13 + | +LL | let _ = opt.is_none() || opt.is_some_and(then_fn); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` + +error: manual implementation of `Option::is_none_or` + --> tests/ui/manual_is_variant_and.rs:245:13 + | +LL | let _ = opt.is_some_and(then_fn) || opt.is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` + +error: aborting due to 33 previous errors From fdfbe7305d1436594ffa1570f611054555327eef Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 25 Jan 2026 19:42:40 +0100 Subject: [PATCH 052/182] Only `Duration` constructors taking `u64` are covered --- clippy_lints/src/duration_suboptimal_units.rs | 5 +++-- tests/ui/duration_suboptimal_units.fixed | 5 +++++ tests/ui/duration_suboptimal_units.rs | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs index 8140585b70d3..19f44f8e959d 100644 --- a/clippy_lints/src/duration_suboptimal_units.rs +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -9,7 +9,7 @@ use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, RustcVersion}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt, UintTy}; use rustc_session::impl_lint_pass; use rustc_span::Symbol; @@ -76,13 +76,14 @@ impl LateLintPass<'_> for DurationSuboptimalUnits { .typeck_results() .node_type(func_ty.hir_id) .is_diag_item(cx, sym::Duration) + && matches!(cx.typeck_results().expr_ty_adjusted(arg).kind(), ty::Uint(UintTy::U64)) // We intentionally don't want to evaluate referenced constants, as we don't want to // recommend a literal value over using constants: // // let dur = Duration::from_secs(SIXTY); // ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)` && let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt()) - && let value = u64::try_from(value).expect("All Duration::from_ constructors take a u64") + && let Ok(value) = u64::try_from(value) // Cannot fail // There is no need to promote e.g. 0 seconds to 0 hours && value != 0 && let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value) diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed index 98c4b6e965ba..515ec10e572b 100644 --- a/tests/ui/duration_suboptimal_units.fixed +++ b/tests/ui/duration_suboptimal_units.fixed @@ -89,3 +89,8 @@ mod my_duration { let dur = Duration::from_secs(60); } } + +fn issue16457() { + // Methods taking something else than `u64` are not covered + _ = Duration::from_nanos_u128(1 << 90); +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs index c4f33a9f92e0..357c52cffb35 100644 --- a/tests/ui/duration_suboptimal_units.rs +++ b/tests/ui/duration_suboptimal_units.rs @@ -89,3 +89,8 @@ mod my_duration { let dur = Duration::from_secs(60); } } + +fn issue16457() { + // Methods taking something else than `u64` are not covered + _ = Duration::from_nanos_u128(1 << 90); +} From 25234f8652f59a796617c44688e8d4696611c314 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Jan 2026 18:24:52 +0100 Subject: [PATCH 053/182] Add two new target-specific intrinsics mapping --- src/intrinsic/llvm.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 10183c5ee526..fbf3050a8a15 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1061,13 +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", From 436ae1e0a0d48967677bb6bf567d3d7c4697f498 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Jan 2026 18:25:25 +0100 Subject: [PATCH 054/182] Add regression test for `llvm.sqrt.v4f64` and `llvm.smax.v4i32` mapping --- tests/run/simd-ffi.rs | 102 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/run/simd-ffi.rs diff --git a/tests/run/simd-ffi.rs b/tests/run/simd-ffi.rs new file mode 100644 index 000000000000..67cc2e5b96e3 --- /dev/null +++ b/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() {} From b7728f072e3eae7c4cb0dfab62d575414c37d88f Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Mon, 26 Jan 2026 17:31:34 +0000 Subject: [PATCH 055/182] Omit standard copyright notice Remove copyright notices for files licensed under the standard terms (MIT OR Apache-2.0). --- example/alloc_system.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index 4d70122496b7..31457185f1a8 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -1,6 +1,3 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) - #![no_std] #![feature(allocator_api, rustc_private)] From 9f308b72685b460b289af189d1c255ca1b6fd9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Nov 2025 22:16:44 +0000 Subject: [PATCH 056/182] Do not mention `-Zmacro-backtrace` for std macros that are a wrapper around a compiler intrinsic --- tests/ui/recursive_format_impl.stderr | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/ui/recursive_format_impl.stderr b/tests/ui/recursive_format_impl.stderr index 31960c7193b4..4361d612bf2a 100644 --- a/tests/ui/recursive_format_impl.stderr +++ b/tests/ui/recursive_format_impl.stderr @@ -12,72 +12,54 @@ error: using `self` as `Display` in `impl Display` will cause infinite recursion | LL | write!(f, "{}", self) | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:86:9 | LL | write!(f, "{}", &self) | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:93:9 | LL | write!(f, "{:?}", &self) | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:103:9 | LL | write!(f, "{}", &&&self) | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:178:9 | LL | write!(f, "{}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:185:9 | LL | write!(f, "{:?}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:202:9 | LL | write!(f, "{}", *self) | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:219:9 | LL | write!(f, "{}", **&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:236:9 | LL | write!(f, "{}", &&**&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors From dfcfd73b2c3bc0c076226ebbb04554b689dd5041 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 26 Jan 2026 17:57:34 +0000 Subject: [PATCH 057/182] fix: `cmp_owned` FP when `to_string` comes from macro input --- clippy_lints/src/operators/cmp_owned.rs | 12 ++++++--- clippy_lints/src/operators/mod.rs | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 32 +++++++++++++++++++++++ tests/ui/cmp_owned/with_suggestion.rs | 32 +++++++++++++++++++++++ tests/ui/cmp_owned/with_suggestion.stderr | 15 ++++++++++- 5 files changed, 87 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index 39097833a6c5..db55772f4e01 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -10,10 +10,10 @@ use rustc_span::symbol::sym; use super::CMP_OWNED; -pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { if op.is_comparison() { - check_op(cx, lhs, rhs, true); - check_op(cx, rhs, lhs, false); + check_op(cx, e, lhs, rhs, true); + check_op(cx, e, rhs, lhs, false); } } @@ -35,7 +35,11 @@ fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'t }) } -fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { +fn check_op(cx: &LateContext<'_>, outer: &Expr<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { + if !outer.span.eq_ctxt(expr.span) { + return; + } + let typeck = cx.typeck_results(); let (arg, arg_span) = match expr.kind { ExprKind::MethodCall(_, arg, [], _) diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 53b8e9e5d5ae..383b135dfa50 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1038,7 +1038,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { float_equality_without_abs::check(cx, e, op.node, lhs, rhs); integer_division::check(cx, e, op.node, lhs, rhs); integer_division_remainder_used::check(cx, op.node, lhs, rhs, e.span); - cmp_owned::check(cx, op.node, lhs, rhs); + cmp_owned::check(cx, e, op.node, lhs, rhs); float_cmp::check(cx, e, op.node, lhs, rhs); modulo_one::check(cx, e, op.node, rhs); modulo_arithmetic::check( diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index 4c3b13b30043..f65339605e75 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -112,3 +112,35 @@ fn issue16322(item: String) { println!("Ja!"); } } + +fn issue16458() { + macro_rules! partly_comes_from_macro { + ($i:ident: $ty:ty, $def:expr) => { + let _ = { + let res = <$ty>::default() == $def; + let _i: $ty = $def; + res + }; + }; + } + + partly_comes_from_macro! { + required_version: String, env!("HOME").to_string() + } + + macro_rules! all_comes_from_macro { + ($($i:ident: $ty:ty, $def:expr);+ $(;)*) => { + $( + let _ = { + let res = <$ty>::default() == "$def"; + //~^ cmp_owned + let _i: $ty = $def; + res + }; + )+ + }; + } + all_comes_from_macro! { + required_version: String, env!("HOME").to_string(); + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index a9d7509feaaf..ed2300c80eaa 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -112,3 +112,35 @@ fn issue16322(item: String) { println!("Ja!"); } } + +fn issue16458() { + macro_rules! partly_comes_from_macro { + ($i:ident: $ty:ty, $def:expr) => { + let _ = { + let res = <$ty>::default() == $def; + let _i: $ty = $def; + res + }; + }; + } + + partly_comes_from_macro! { + required_version: String, env!("HOME").to_string() + } + + macro_rules! all_comes_from_macro { + ($($i:ident: $ty:ty, $def:expr);+ $(;)*) => { + $( + let _ = { + let res = <$ty>::default() == "$def".to_string(); + //~^ cmp_owned + let _i: $ty = $def; + res + }; + )+ + }; + } + all_comes_from_macro! { + required_version: String, env!("HOME").to_string(); + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 66544ce0c217..38d124baa4b5 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -55,5 +55,18 @@ error: this creates an owned instance just for comparison LL | if item == t!(frohes_neu_Jahr).to_string() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(frohes_neu_Jahr)` -error: aborting due to 9 previous errors +error: this creates an owned instance just for comparison + --> tests/ui/cmp_owned/with_suggestion.rs:135:51 + | +LL | let res = <$ty>::default() == "$def".to_string(); + | ^^^^^^^^^^^^^^^^^^ help: try: `"$def"` +... +LL | / all_comes_from_macro! { +LL | | required_version: String, env!("HOME").to_string(); +LL | | } + | |_____- in this macro invocation + | + = note: this error originates in the macro `all_comes_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors From c3ab233ca45075ec9306385633fb2f09999ac825 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 26 Jan 2026 18:27:06 +0000 Subject: [PATCH 058/182] fix: `manual_dangling_ptr` FP when pointee type is not `Sized` --- clippy_lints/src/casts/manual_dangling_ptr.rs | 2 ++ tests/ui/manual_dangling_ptr.fixed | 12 ++++++++ tests/ui/manual_dangling_ptr.rs | 12 ++++++++ tests/ui/manual_dangling_ptr.stderr | 28 +++++++++++-------- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs index be1f406770ce..56779e8ce3d9 100644 --- a/clippy_lints/src/casts/manual_dangling_ptr.rs +++ b/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -15,6 +15,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: let init_expr = expr_or_init(cx, from); if is_expr_const_aligned(cx, init_expr, ptr_ty.ty) && let Some(std_or_core) = std_or_core(cx) + && let pointee_ty = cx.typeck_results().node_type(ptr_ty.ty.hir_id) + && pointee_ty.is_sized(cx.tcx, cx.typing_env()) { let sugg_fn = match ptr_ty.mutbl { Mutability::Not => "ptr::dangling", diff --git a/tests/ui/manual_dangling_ptr.fixed b/tests/ui/manual_dangling_ptr.fixed index b6afe7898906..c6a6379194c9 100644 --- a/tests/ui/manual_dangling_ptr.fixed +++ b/tests/ui/manual_dangling_ptr.fixed @@ -1,3 +1,4 @@ +#![feature(extern_types)] #![warn(clippy::manual_dangling_ptr)] use std::mem; @@ -42,3 +43,14 @@ fn _msrv_1_84() { //~^ manual_dangling_ptr //~| manual_dangling_ptr } + +fn issue16459() { + unsafe extern "C" { + type Extern; + } + let _ = unsafe { &mut *(1 as *mut Extern) }; + + struct Empty; + let _ = unsafe { &mut *std::ptr::dangling_mut::() }; + //~^ manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.rs b/tests/ui/manual_dangling_ptr.rs index 581ad50113e2..338003fa41fd 100644 --- a/tests/ui/manual_dangling_ptr.rs +++ b/tests/ui/manual_dangling_ptr.rs @@ -1,3 +1,4 @@ +#![feature(extern_types)] #![warn(clippy::manual_dangling_ptr)] use std::mem; @@ -42,3 +43,14 @@ fn _msrv_1_84() { //~^ manual_dangling_ptr //~| manual_dangling_ptr } + +fn issue16459() { + unsafe extern "C" { + type Extern; + } + let _ = unsafe { &mut *(1 as *mut Extern) }; + + struct Empty; + let _ = unsafe { &mut *(1 as *mut Empty) }; + //~^ manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.stderr b/tests/ui/manual_dangling_ptr.stderr index e3bc9b16b0d9..7e1533f7a30d 100644 --- a/tests/ui/manual_dangling_ptr.stderr +++ b/tests/ui/manual_dangling_ptr.stderr @@ -1,5 +1,5 @@ error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:7:24 + --> tests/ui/manual_dangling_ptr.rs:8:24 | LL | let _: *const u8 = 1 as *const _; | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` @@ -8,58 +8,64 @@ LL | let _: *const u8 = 1 as *const _; = help: to override `-D warnings` add `#[allow(clippy::manual_dangling_ptr)]` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:9:13 + --> tests/ui/manual_dangling_ptr.rs:10:13 | LL | let _ = 2 as *const u32; | ^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:11:13 + --> tests/ui/manual_dangling_ptr.rs:12:13 | LL | let _ = 4 as *mut f32; | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:14:13 + --> tests/ui/manual_dangling_ptr.rs:15:13 | LL | let _ = mem::align_of::() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:16:13 + --> tests/ui/manual_dangling_ptr.rs:17:13 | LL | let _ = mem::align_of::() as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:18:13 + --> tests/ui/manual_dangling_ptr.rs:19:13 | LL | let _ = mem::align_of::() as *const usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:21:9 + --> tests/ui/manual_dangling_ptr.rs:22:9 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:21:24 + --> tests/ui/manual_dangling_ptr.rs:22:24 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:41:9 + --> tests/ui/manual_dangling_ptr.rs:42:9 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:41:24 + --> tests/ui/manual_dangling_ptr.rs:42:24 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` -error: aborting due to 10 previous errors +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:54:28 + | +LL | let _ = unsafe { &mut *(1 as *mut Empty) }; + | ^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::()` + +error: aborting due to 11 previous errors From 17f89e76abe4b4af4a2c551c3d79835df849eaa0 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 26 Jan 2026 11:11:40 -0800 Subject: [PATCH 059/182] Fix `useless_attribute` FP on `exported_private_dependencies` lint attributes. --- clippy_lints/src/attrs/useless_attribute.rs | 1 + clippy_utils/src/sym.rs | 1 + tests/ui/useless_attribute.fixed | 4 ++++ tests/ui/useless_attribute.rs | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index aa9a6654bee3..9a1e315ae530 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -31,6 +31,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { | sym::dead_code | sym::deprecated | sym::deprecated_in_future + | sym::exported_private_dependencies | sym::hidden_glob_reexports | sym::unreachable_pub | sym::unused diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 5d6f2241c7c0..e0b03ae4f7b2 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -147,6 +147,7 @@ generate! { exp, expect_err, expn_data, + exported_private_dependencies, extend, filter, filter_map, diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index e0bc23e0788c..dbe4b6fb50f3 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -42,6 +42,10 @@ mod foo { #[allow(deprecated)] pub use foo::Bar; +// don't lint on exported_private_dependencies for `use` items +#[allow(exported_private_dependencies)] +use {}; + // This should not trigger the lint. There's lint level definitions inside the external derive // that would trigger the useless_attribute lint. #[derive(DeriveSomething)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 30a4c354b238..44fb6733f054 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -42,6 +42,10 @@ mod foo { #[allow(deprecated)] pub use foo::Bar; +// don't lint on exported_private_dependencies for `use` items +#[allow(exported_private_dependencies)] +use {}; + // This should not trigger the lint. There's lint level definitions inside the external derive // that would trigger the useless_attribute lint. #[derive(DeriveSomething)] From d463a8d1729d6d94384206a9ff91e22b2fed5bcd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Jan 2026 16:24:34 +0100 Subject: [PATCH 060/182] Update `askama` version to `0.15.2` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 560f1e8d7fbe..43d6c82b34cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.15", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "0.9.7" From e88259366689a0daf0d57edfd42004f067f02dc7 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 27 Jan 2026 22:24:38 -0300 Subject: [PATCH 061/182] Fix grammar in doc comments in `conf.rs` --- book/src/lint_configuration.md | 4 ++-- clippy_config/src/conf.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 68ef93d7cbf9..57ac01828e59 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -246,7 +246,7 @@ A list of crate names to allow duplicates of ## `allowed-idents-below-min-chars` Allowed names below the minimum allowed characters. The value `".."` can be used as part of -the list to indicate, that the configured values should be appended to the default +the list to indicate that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. **Default Value:** `["i", "j", "x", "y", "z", "w", "n"]` @@ -570,7 +570,7 @@ The list of disallowed types, written as fully qualified paths. ## `doc-valid-idents` The list of words this lint should not consider as identifiers needing ticks. The value -`".."` can be used as part of the list to indicate, that the configured values should be appended to the +`".."` can be used as part of the list to indicate that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. For example: * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 2e7ef3a8b020..3f4997a395a8 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -423,7 +423,7 @@ define_Conf! { #[lints(multiple_crate_versions)] allowed_duplicate_crates: Vec = Vec::new(), /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of - /// the list to indicate, that the configured values should be appended to the default + /// the list to indicate that the configured values should be appended to the default /// configuration of Clippy. By default, any configuration will replace the default value. #[lints(min_ident_chars)] allowed_idents_below_min_chars: Vec = @@ -620,7 +620,7 @@ define_Conf! { #[lints(disallowed_types)] disallowed_types: Vec = Vec::new(), /// The list of words this lint should not consider as identifiers needing ticks. The value - /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the + /// `".."` can be used as part of the list to indicate that the configured values should be appended to the /// default configuration of Clippy. By default, any configuration will replace the default value. For example: /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. From bd1c36a115eee3542053a38be5e996b8e7908bc4 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 28 Jan 2026 11:14:09 -0600 Subject: [PATCH 062/182] rustdoc(main.js): use typeof in register_type_impls for isTrait this allows TypeScript to understand the relation between isTrait and traitName's type, getting rid of a type error. --- src/librustdoc/html/static/js/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index a26683e2e9bb..f980c92d8f7a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -973,8 +973,8 @@ function preLoadCss(cssUrl) { for (const impList of imp[nonnull(window.currentCrate)]) { const types = impList.slice(2); const text = impList[0]; - const isTrait = impList[1] !== 0; const traitName = impList[1]; + const isTrait = typeof traitName === "string"; // @ts-expect-error if (types.indexOf(selfPath) === -1) { continue; @@ -1057,7 +1057,6 @@ function preLoadCss(cssUrl) { const li = document.createElement("li"); const a = document.createElement("a"); a.href = `#${nonnull(template.content.querySelector(".impl")).id}`; - // @ts-expect-error a.textContent = traitName; li.appendChild(a); // @ts-expect-error From 4a6325de8ddea6e5a1ef148be919a12420257307 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 14:07:36 -0500 Subject: [PATCH 063/182] Set gcc language name and compilation unit name --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- libgccjit.version | 2 +- src/context.rs | 7 +++++++ src/lib.rs | 2 ++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dea1207b05da..3b497f83cc0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683" +checksum = "ef03c8ae23826a0755b980999a553a262c61f2f585245e647192d95bf09eee79" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f81d901767ddba371a619fa9bba657066a4d3c5607ee69bbb557c1c5ba9bf85" +checksum = "0ff511da413e4a5da6f09607748395ba37525e01ba7d322cbec3efc43095dd60" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 18847f50d46a..97735e49e84b 100644 --- a/Cargo.toml +++ b/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.2.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/libgccjit.version b/libgccjit.version index bab62f642365..e49b36557350 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -0081ca6631abdfa02bf42bc85aaf507b8a0e6beb +586d798e864fb33b1b4e842c5493a653841a7c02 diff --git a/src/context.rs b/src/context.rs index dbb89a4ff7db..6143d27725e8 100644 --- a/src/context.rs +++ b/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}; @@ -143,6 +145,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)) diff --git a/src/lib.rs b/src/lib.rs index 96d3a0024f41..a8265cc86fa1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -240,6 +240,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. From 49c9b0a7bf0dba213361fa181a2770c76652a0cf Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:01:51 -0500 Subject: [PATCH 064/182] Update to nightly-2026-01-28 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 86ae738d4483..2168c8e72cfb 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-12-20" +channel = "nightly-2026-01-28" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From bd71a5f4b0e38ea80ed3f0a0df33440b93d88312 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:02:09 -0500 Subject: [PATCH 065/182] Implement new f16/f128 intrinsics and implement dummy va_end --- src/intrinsic/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 7b8d8602bcae..9a08003a7fb2 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -167,6 +167,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", @@ -221,6 +222,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", @@ -287,6 +289,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 + | sym::fabsf16 | sym::floorf16 | sym::fmaf16 | sym::maxnumf16 @@ -687,7 +690,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) } } From f992358ab772ba146732024975802648eb7a490b Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 22 Dec 2025 14:45:08 +0000 Subject: [PATCH 066/182] Part 2 refactoring of moving placeholder types to `rustc_type_ir` --- clippy_utils/src/ty/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 2926a329ce16..0f11df98fc17 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -782,15 +782,15 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } } -pub fn for_each_top_level_late_bound_region( - ty: Ty<'_>, - f: impl FnMut(BoundRegion) -> ControlFlow, +pub fn for_each_top_level_late_bound_region<'cx, B>( + ty: Ty<'cx>, + f: impl FnMut(BoundRegion<'cx>) -> ControlFlow, ) -> ControlFlow { struct V { index: u32, f: F, } - impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { + impl<'tcx, B, F: FnMut(BoundRegion<'tcx>) -> ControlFlow> TypeVisitor> for V { type Result = ControlFlow; fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { if let RegionKind::ReBound(BoundVarIndexKind::Bound(idx), bound) = r.kind() From cf6625648ea97bb4951596c7b7c6038051c86113 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Jan 2026 21:58:29 +0100 Subject: [PATCH 067/182] Update `askama` to `0.15.4` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 43d6c82b34cb..8f5ef9ca2f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.4", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "0.9.7" From ee9967bac019659ce17292fa5162da9b638464ed Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:11:05 -0500 Subject: [PATCH 068/182] Fix clippy warning --- build_system/src/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index ca2a2a7dc2de..096f8c98376c 100644 --- a/build_system/src/test.rs +++ b/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. From ff4db77564dbf7c94cdda67dba687c244b888d1e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:14:27 -0500 Subject: [PATCH 069/182] Fix spelling mistake --- src/intrinsic/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 9a08003a7fb2..7140456c3754 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -618,15 +618,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; @@ -643,13 +643,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); } From d299dce03a37d01b4e25b9033de7ab2e9112a7b4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:27:55 -0500 Subject: [PATCH 070/182] Fix the name of failing UI tests --- tests/failing-ui-tests.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 99a80fa7e4f4..73d29426adf8 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -89,11 +89,11 @@ 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 From dffd4ab825020322303b5e9e287519957b4d2594 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 29 Jan 2026 17:09:53 -0500 Subject: [PATCH 071/182] Ignore failing UI test --- tests/failing-ui-tests.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 73d29426adf8..75ca1845f45e 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -97,3 +97,4 @@ tests/ui/eii/default/call_default.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 From e8282659f9683bb063396a32dbdc489736ee79e4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 08:32:03 -0500 Subject: [PATCH 072/182] Update to nightly-2026-01-30 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 2168c8e72cfb..c2179bc3ff98 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-01-28" +channel = "nightly-2026-01-30" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From fb32a3f52e1a6d54921bcd9d4976bf22421227a4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 08:32:24 -0500 Subject: [PATCH 073/182] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index e49b36557350..25e1105ab07f 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -586d798e864fb33b1b4e842c5493a653841a7c02 +896045775f7c40fafe48c6e398f6c53bf6af889e From a04934421ffa8ac4b6541772b5fef7c2778d3809 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 11:16:26 -0500 Subject: [PATCH 074/182] Switch to new_array_type_u64 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/builder.rs | 2 +- src/common.rs | 6 +++--- src/context.rs | 4 ++-- src/intrinsic/llvm.rs | 12 ++++++------ src/type_.rs | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b497f83cc0a..a283ea4cb0b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef03c8ae23826a0755b980999a553a262c61f2f585245e647192d95bf09eee79" +checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff511da413e4a5da6f09607748395ba37525e01ba7d322cbec3efc43095dd60" +checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 97735e49e84b..29af6a1fc434 100644 --- a/Cargo.toml +++ b/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.2.0", 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/src/builder.rs b/src/builder.rs index 3def9a5c015c..ea75b4294e04 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1503,7 +1503,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); + self.context.new_array_type_u64(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() } diff --git a/src/common.rs b/src/common.rs index 7c2969e58718..e71e1216dbd9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -55,7 +55,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 = context.new_array_type_u64(None, byte_type, bytes.len() as u64 / 8); let elements: Vec<_> = bytes .chunks_exact(8) .map(|arr| { @@ -76,7 +76,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 = context.new_array_type_u64(None, byte_type, bytes.len() as u64 / 4); let elements: Vec<_> = bytes .chunks_exact(4) .map(|arr| { @@ -95,7 +95,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 = context.new_array_type_u64(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/src/context.rs b/src/context.rs index 988743d0aef5..d4d4c490e75e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -201,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 = context.new_array_type_u64(None, i64_type, 2)/*.get_aligned(i128_align)*/; + let u128_type = context.new_array_type_u64(None, u64_type, 2)/*.get_aligned(u128_align)*/; (i128_type, u128_type) }; diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index fbf3050a8a15..5c8bc5a4791c 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -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 = builder.context.new_array_type_u64(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 = builder.context.new_array_type_u64(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 = builder.context.new_array_type_u64(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 = builder.context.new_array_type_u64(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 = builder.context.new_array_type_u64(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 = builder.context.new_array_type_u64(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()); diff --git a/src/type_.rs b/src/type_.rs index d356b6af260a..7a6a5d3a10ea 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -311,7 +311,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { len = 0; } - self.context.new_array_type(None, ty, len) + self.context.new_array_type_u64(None, ty, len) } } From e4b746486c91de2a50eafadb9be71512aa149e73 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 11:32:29 -0500 Subject: [PATCH 075/182] Ignore test when 128-bit integers are disabled --- .github/workflows/ci.yml | 4 ++++ tests/failing-ui-tests-without-128bit-integers.txt | 1 + 2 files changed, 5 insertions(+) create mode 100644 tests/failing-ui-tests-without-128bit-integers.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c8e7d628169..840c09409bba 100644 --- a/.github/workflows/ci.yml +++ b/.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/tests/failing-ui-tests-without-128bit-integers.txt b/tests/failing-ui-tests-without-128bit-integers.txt new file mode 100644 index 000000000000..1dc3859b335e --- /dev/null +++ b/tests/failing-ui-tests-without-128bit-integers.txt @@ -0,0 +1 @@ +tests/ui/simd/intrinsic/splat.rs From cdee2fbff588eed1d399897263e8dcafd51f86df Mon Sep 17 00:00:00 2001 From: Frank King Date: Fri, 30 Jan 2026 11:06:27 +0800 Subject: [PATCH 076/182] refactor: add an `enum DerefAdjustKind` in favor of `Option` --- clippy_lints/src/eta_reduction.rs | 4 ++-- clippy_lints/src/format_args.rs | 6 +++--- clippy_lints/src/loops/while_let_on_iterator.rs | 4 ++-- clippy_lints/src/methods/map_clone.rs | 4 ++-- clippy_lints/src/methods/option_as_ref_deref.rs | 2 +- clippy_lints/src/methods/swap_with_temporary.rs | 4 ++-- clippy_lints/src/methods/type_id_on_box.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 10 +++++----- clippy_lints/src/methods/useless_asref.rs | 4 ++-- clippy_lints/src/non_copy_const.rs | 4 ++-- clippy_utils/src/eager_or_lazy.rs | 11 +++-------- clippy_utils/src/lib.rs | 10 ++++++---- clippy_utils/src/ty/mod.rs | 5 +++-- 13 files changed, 35 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 21385ee4fdc7..3e46c370fb70 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -10,7 +10,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{ self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults, }; @@ -236,7 +236,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx .iter() .rev() .fold(0, |acc, adjustment| match adjustment.kind { - Adjust::Deref(Some(_)) => acc + 1, + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1, Adjust::Deref(_) if acc > 0 => acc + 1, _ => acc, }) diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 011cbf8c5d41..5fb1a0b80f1a 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -24,7 +24,7 @@ use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; @@ -704,12 +704,12 @@ where let mut n_needed = 0; loop { if let Some(Adjustment { - kind: Adjust::Deref(overloaded_deref), + kind: Adjust::Deref(deref), target, }) = iter.next() { n_total += 1; - if overloaded_deref.is_some() { + if let DerefAdjustKind::Overloaded(..) = deref { n_needed = n_total; } ty = *target; diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index 6c95c7b54c50..fc0789894cc2 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Closure, Expr, ExprKind, HirId, LetStmt, Mutability, UnOp}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use rustc_span::symbol::sym; @@ -88,7 +88,7 @@ fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option, e: &hir::Expr<'_>, recv: &hir::Expr<'_ && cx.tcx.lang_items().clone_trait() == Some(trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) { let obj_ty = cx.typeck_results().expr_ty(obj); if let ty::Ref(_, ty, mutability) = obj_ty.kind() { diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 3d489075ce8a..1239d8927acf 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -58,7 +58,7 @@ pub(super) fn check( .iter() .map(|x| &x.kind) .collect::>() - && let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj + && let [ty::adjustment::Adjust::Deref(ty::adjustment::DerefAdjustKind::Builtin), ty::adjustment::Adjust::Borrow(_)] = *adj && let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap() && let Some(method_name) = cx.tcx.get_diagnostic_name(method_did) { diff --git a/clippy_lints/src/methods/swap_with_temporary.rs b/clippy_lints/src/methods/swap_with_temporary.rs index e378cbd6ae0a..0b8f6ae9f277 100644 --- a/clippy_lints/src/methods/swap_with_temporary.rs +++ b/clippy_lints/src/methods/swap_with_temporary.rs @@ -4,7 +4,7 @@ use rustc_ast::BorrowKind; use rustc_errors::{Applicability, Diag}; use rustc_hir::{Expr, ExprKind, Node, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::sym; use super::SWAP_WITH_TEMPORARY; @@ -47,7 +47,7 @@ impl<'tcx> ArgKind<'tcx> { && let adjustments = cx.typeck_results().expr_adjustments(arg) && adjustments .first() - .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(None))) + .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) && adjustments .last() .is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_))) diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index e67ba5c4d314..98f319be7a45 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{Span, sym}; @@ -58,7 +58,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) |diag| { let derefs = recv_adjusts .iter() - .filter(|adj| matches!(adj.kind, Adjust::Deref(None))) + .filter(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) .count(); diag.note( diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 74e8dbc15a6c..607aaef9627b 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref}; use rustc_middle::ty::{ self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty, }; @@ -78,7 +78,7 @@ fn check_addr_of_expr( // For matching uses of `Cow::from` [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -89,7 +89,7 @@ fn check_addr_of_expr( // For matching uses of arrays | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -104,11 +104,11 @@ fn check_addr_of_expr( // For matching everything else | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { - kind: Adjust::Deref(Some(OverloadedDeref { .. })), + kind: Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { .. })), .. }, Adjustment { diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index f852080d0f2a..3737249a40cb 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, LangItem, Node}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::{Span, Symbol, sym}; @@ -161,7 +161,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) && obj.res_local_id() == Some(local_id) { true diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 9b0008a29c6b..f99748127a8f 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -33,7 +33,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::mir::{ConstValue, UnevaluatedConst}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{ self, AliasTyKind, EarlyBinder, GenericArgs, GenericArgsRef, Instance, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeckResults, TypingEnv, @@ -907,7 +907,7 @@ fn does_adjust_borrow(adjust: &Adjustment<'_>) -> Option { match adjust.kind { Adjust::Borrow(_) => Some(BorrowCause::AutoBorrow), // Custom deref calls `::deref(&x)` resulting in a borrow. - Adjust::Deref(Some(_)) => Some(BorrowCause::AutoDeref), + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => Some(BorrowCause::AutoDeref), // All other adjustments read the value. _ => None, } diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 2bdd5739a557..d184744162e4 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -19,7 +19,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use std::{cmp, ops}; @@ -132,7 +132,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS .typeck_results() .expr_adjustments(e) .iter() - .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) + .any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))) { self.eagerness |= NoChange; return; @@ -211,12 +211,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS // Custom `Deref` impl might have side effects ExprKind::Unary(UnOp::Deref, e) - if self - .cx - .typeck_results() - .expr_ty(e) - .builtin_deref(true) - .is_none() => + if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => { self.eagerness |= NoChange; }, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 6b10f4b51442..16bedf199e20 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -108,7 +108,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::hir::place::PlaceBase; use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, PointerCoercion}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind, PointerCoercion}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt, @@ -477,8 +477,8 @@ pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Optio .expr_adjustments(e) .iter() .find_map(|a| match a.kind { - Adjust::Deref(Some(d)) => Some(Some(d.mutbl)), - Adjust::Deref(None) => None, + Adjust::Deref(DerefAdjustKind::Overloaded(d)) => Some(Some(d.mutbl)), + Adjust::Deref(DerefAdjustKind::Builtin) => None, _ => Some(None), }) .and_then(|x| x) @@ -3537,7 +3537,9 @@ pub fn expr_adjustment_requires_coercion(cx: &LateContext<'_>, expr: &Expr<'_>) cx.typeck_results().expr_adjustments(expr).iter().any(|adj| { matches!( adj.kind, - Adjust::Deref(Some(_)) | Adjust::Pointer(PointerCoercion::Unsize) | Adjust::NeverToAny + Adjust::Deref(DerefAdjustKind::Overloaded(_)) + | Adjust::Pointer(PointerCoercion::Unsize) + | Adjust::NeverToAny ) }) } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 0f11df98fc17..46456528fdf8 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, @@ -1345,6 +1345,7 @@ pub fn get_field_idx_by_name(ty: Ty<'_>, name: Symbol) -> Option { pub fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool { adjustments.iter().any(|a| { let ty = mem::replace(&mut ty, a.target); - matches!(a.kind, Adjust::Deref(Some(op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty) + matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(op)) if op.mutbl == Mutability::Mut) + && is_manually_drop(ty) }) } From 9c1ca3a2456c9ed021312f030af27ffec7bb7e7d Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:37:39 +0100 Subject: [PATCH 077/182] doc_paragraphs_missing_punctuation: allow some non-punctuated paragraphs --- .../doc/doc_paragraphs_missing_punctuation.rs | 22 ++++++++----- .../doc_paragraphs_missing_punctuation.fixed | 25 +++++++++++---- .../doc/doc_paragraphs_missing_punctuation.rs | 25 +++++++++++---- .../doc_paragraphs_missing_punctuation.stderr | 32 ++++++++----------- 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs index a8f734637672..605d35f48baf 100644 --- a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs +++ b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs @@ -53,21 +53,26 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { let mut no_report_depth = 0; let mut missing_punctuation = Vec::new(); let mut current_paragraph = None; + let mut current_event_is_missing_punctuation = false; for (event, offset) in Parser::new_ext(doc_string, main_body_opts() - Options::ENABLE_SMART_PUNCTUATION).into_offset_iter() { + let last_event_was_missing_punctuation = current_event_is_missing_punctuation; + current_event_is_missing_punctuation = false; + match event { - Event::Start( - Tag::CodeBlock(..) - | Tag::FootnoteDefinition(_) - | Tag::Heading { .. } - | Tag::HtmlBlock - | Tag::List(..) - | Tag::Table(_), - ) => { + Event::Start(Tag::FootnoteDefinition(_) | Tag::Heading { .. } | Tag::HtmlBlock | Tag::Table(_)) => { no_report_depth += 1; }, + Event::Start(Tag::CodeBlock(..) | Tag::List(..)) => { + no_report_depth += 1; + if last_event_was_missing_punctuation { + // Remove the error from the previous paragraph as it is followed by a code + // block or a list. + missing_punctuation.pop(); + } + }, Event::End(TagEnd::FootnoteDefinition) => { no_report_depth -= 1; }, @@ -83,6 +88,7 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { Event::End(TagEnd::Paragraph) => { if let Some(mp) = current_paragraph { missing_punctuation.push(mp); + current_event_is_missing_punctuation = true; } }, Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed index 95d65039440b..faabbb381318 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed @@ -46,13 +46,6 @@ enum Exceptions { /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, - /// Here is a snippet. - //~^ doc_paragraphs_missing_punctuation - /// - /// ``` - /// // Code blocks are no issues. - /// ``` - CodeBlock, } // Check the lint can be expected on a whole enum at once. @@ -130,6 +123,24 @@ enum OrderedLists { Paren, } +/// Some elements do not have to be introduced by an independent clause. +enum NotIndependentClause { + /// Lists are allowed to be introduced by a clause that is not independent: this usually + /// requires that + /// + /// - items end with a comma or a semicolon, which is not enforced; + /// - the last item end with a period, which is also not enforced. + List, + /// For instance, the function + /// + /// ``` + /// fn answer() {} + /// ``` + /// + /// returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + CodeBlock, +} + /// Doc comments with trailing blank lines are supported. //~^ doc_paragraphs_missing_punctuation /// diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.rs b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs index 35b74d7d13b9..9821115601a6 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.rs +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs @@ -46,13 +46,6 @@ enum Exceptions { /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, - /// Here is a snippet - //~^ doc_paragraphs_missing_punctuation - /// - /// ``` - /// // Code blocks are no issues. - /// ``` - CodeBlock, } // Check the lint can be expected on a whole enum at once. @@ -130,6 +123,24 @@ enum OrderedLists { Paren, } +/// Some elements do not have to be introduced by an independent clause. +enum NotIndependentClause { + /// Lists are allowed to be introduced by a clause that is not independent: this usually + /// requires that + /// + /// - items end with a comma or a semicolon, which is not enforced; + /// - the last item end with a period, which is also not enforced. + List, + /// For instance, the function + /// + /// ``` + /// fn answer() {} + /// ``` + /// + /// returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + CodeBlock, +} + /// Doc comments with trailing blank lines are supported //~^ doc_paragraphs_missing_punctuation /// diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr index 49aa4e8aeb88..6645e771c6d3 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr @@ -32,82 +32,76 @@ LL | /// | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:49:26 - | -LL | /// Here is a snippet - | ^ help: end the paragraph with some punctuation: `.` - -error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:15 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:65:15 | LL | /// U+0001 | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:79:29 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:29 | LL | //! inner attributes too | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:90:47 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:83:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:95:46 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:88:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:104:56 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:97:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:108:65 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:101:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:133:57 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:144:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:139:48 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:150:48 | LL | /// This first paragraph is missing punctuation | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:143:34 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:154:34 | LL | /// And it has multiple sentences | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:146:37 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:157:37 | LL | /// Same for this third and last one | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:153:33 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:164:33 | LL | /// This ends with a code `span` | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:162:27 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:173:27 | LL | * Block doc comments work | ^ help: end the paragraph with some punctuation: `.` -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors From 631120b803ddf096922832d41ea88afd212e5ed0 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 31 Jan 2026 17:48:26 +0000 Subject: [PATCH 078/182] fix: `unwrap_used` and `expect_used` FN when using fully qualified syntax --- clippy_lints/src/methods/mod.rs | 10 +++ .../src/methods/unwrap_expect_used.rs | 68 +++++++++++++++++++ tests/ui/unwrap_expect_used.rs | 12 ++++ tests/ui/unwrap_expect_used.stderr | 50 +++++++++++++- 4 files changed, 139 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3ca7f6bc29c5..355b34d195da 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4965,6 +4965,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods { io_other_error::check(cx, expr, func, args, self.msrv); swap_with_temporary::check(cx, expr, func, args); ip_constant::check(cx, expr, func, args); + unwrap_expect_used::check_call( + cx, + expr, + func, + args, + self.allow_unwrap_in_tests, + self.allow_expect_in_tests, + self.allow_unwrap_in_consts, + self.allow_expect_in_consts, + ); }, ExprKind::MethodCall(..) => { self.check_methods(cx, expr); diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 30db2a75df57..4effab3a5e63 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -3,6 +3,7 @@ use clippy_utils::res::MaybeDef; use clippy_utils::ty::is_never_like; use clippy_utils::{is_in_test, is_inside_always_const_context, is_lint_allowed}; use rustc_hir::Expr; +use rustc_hir::def::DefKind; use rustc_lint::{LateContext, Lint}; use rustc_middle::ty; use rustc_span::sym; @@ -87,3 +88,70 @@ pub(super) fn check( }, ); } + +#[expect(clippy::too_many_arguments, clippy::fn_params_excessive_bools)] +pub(super) fn check_call( + cx: &LateContext<'_>, + expr: &Expr<'_>, + func: &Expr<'_>, + args: &[Expr<'_>], + allow_unwrap_in_consts: bool, + allow_unwrap_in_tests: bool, + allow_expect_in_consts: bool, + allow_expect_in_tests: bool, +) { + let Some(recv) = args.first() else { + return; + }; + let Some((DefKind::AssocFn, def_id)) = cx.typeck_results().type_dependent_def(func.hir_id) else { + return; + }; + + match cx.tcx.item_name(def_id) { + sym::unwrap => { + check( + cx, + expr, + recv, + false, + allow_unwrap_in_consts, + allow_unwrap_in_tests, + Variant::Unwrap, + ); + }, + sym::expect => { + check( + cx, + expr, + recv, + false, + allow_expect_in_consts, + allow_expect_in_tests, + Variant::Expect, + ); + }, + clippy_utils::sym::unwrap_err => { + check( + cx, + expr, + recv, + true, + allow_unwrap_in_consts, + allow_unwrap_in_tests, + Variant::Unwrap, + ); + }, + clippy_utils::sym::expect_err => { + check( + cx, + expr, + recv, + true, + allow_expect_in_consts, + allow_expect_in_tests, + Variant::Expect, + ); + }, + _ => (), + } +} diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs index b429f3a8a0bb..207d4dd815be 100644 --- a/tests/ui/unwrap_expect_used.rs +++ b/tests/ui/unwrap_expect_used.rs @@ -83,3 +83,15 @@ mod with_expansion { let _ = open!(file).expect_err("can open"); //~ expect_used } } + +fn issue16484() { + let opt = Some(()); + Option::unwrap(opt); //~ unwrap_used + Option::expect(opt, "error message"); //~ expect_used + + let res: Result<(), i32> = Ok(()); + Result::unwrap(res); //~ unwrap_used + Result::expect(res, "error message"); //~ expect_used + Result::unwrap_err(res); //~ unwrap_used + Result::expect_err(res, "error message"); //~ expect_used +} diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr index 6fd1b84d8123..b9a2844b284c 100644 --- a/tests/ui/unwrap_expect_used.stderr +++ b/tests/ui/unwrap_expect_used.stderr @@ -82,5 +82,53 @@ LL | let _ = open!(file).expect_err("can open"); | = note: if this value is an `Ok`, it will panic -error: aborting due to 10 previous errors +error: used `unwrap()` on an `Option` value + --> tests/ui/unwrap_expect_used.rs:89:5 + | +LL | Option::unwrap(opt); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui/unwrap_expect_used.rs:90:5 + | +LL | Option::expect(opt, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `unwrap()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:93:5 + | +LL | Result::unwrap(res); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Err`, it will panic + +error: used `expect()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:94:5 + | +LL | Result::expect(res, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Err`, it will panic + +error: used `unwrap_err()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:95:5 + | +LL | Result::unwrap_err(res); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Ok`, it will panic + +error: used `expect_err()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:96:5 + | +LL | Result::expect_err(res, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Ok`, it will panic + +error: aborting due to 16 previous errors From 992a6f6c891aeb39b38e99f9e8de4e0cbd867f4a Mon Sep 17 00:00:00 2001 From: vishnupoddar12 Date: Mon, 2 Feb 2026 12:46:57 +0530 Subject: [PATCH 079/182] fix: allow_attributes false negative on attributes with whitespace --- clippy_utils/src/check_proc_macro.rs | 23 +++++++++++------------ tests/ui/allow_attributes.fixed | 5 +++++ tests/ui/allow_attributes.rs | 5 +++++ tests/ui/allow_attributes.stderr | 8 +++++++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 7fb8616072a5..def5d968b063 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -45,6 +45,8 @@ pub enum Pat { Sym(Symbol), /// Any decimal or hexadecimal digit depending on the location. Num, + /// An attribute. + Attr(Symbol), } /// Checks if the start and the end of the span's text matches the patterns. This will return false @@ -65,12 +67,20 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), Pat::Num => start_str.as_bytes().first().is_some_and(u8::is_ascii_digit), + Pat::Attr(sym) => { + let start_str = start_str + .strip_prefix("#[") + .or_else(|| start_str.strip_prefix("#![")) + .unwrap_or(start_str); + start_str.trim_start().starts_with(sym.as_str()) + }, } && match end_pat { Pat::Str(text) => end_str.ends_with(text), Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), Pat::Num => end_str.as_bytes().last().is_some_and(u8::is_ascii_hexdigit), + Pat::Attr(_) => false, }) }) } @@ -350,18 +360,7 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { AttrKind::Normal(..) => { if let Some(name) = attr.name() { // NOTE: This will likely have false positives, like `allow = 1` - let ident_string = name.to_string(); - if attr.style == AttrStyle::Outer { - ( - Pat::OwnedMultiStr(vec!["#[".to_owned() + &ident_string, ident_string]), - Pat::Str(""), - ) - } else { - ( - Pat::OwnedMultiStr(vec!["#![".to_owned() + &ident_string, ident_string]), - Pat::Str(""), - ) - } + (Pat::Attr(name), Pat::Str("")) } else { (Pat::Str("#"), Pat::Str("]")) } diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index 56a98cca3404..ecc9f08c1968 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -63,6 +63,11 @@ fn msrv_1_80() { let x = 1; } +#[rustfmt::skip] +#[ expect ( dead_code ) ] +//~^ allow_attributes +struct Spaced; + #[deny(clippy::allow_attributes)] fn deny_allow_attributes() -> Option { let allow = None; diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 65a0a6b5a108..3ab328b25aff 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -63,6 +63,11 @@ fn msrv_1_80() { let x = 1; } +#[rustfmt::skip] +#[ allow ( dead_code ) ] +//~^ allow_attributes +struct Spaced; + #[deny(clippy::allow_attributes)] fn deny_allow_attributes() -> Option { let allow = None; diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index dd5fb21ffeaf..67a70aac8a86 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -19,5 +19,11 @@ error: #[allow] attribute found LL | #[allow(unused)] | ^^^^^ help: replace it with: `expect` -error: aborting due to 3 previous errors +error: #[allow] attribute found + --> tests/ui/allow_attributes.rs:67:4 + | +LL | #[ allow ( dead_code ) ] + | ^^^^^ help: replace it with: `expect` + +error: aborting due to 4 previous errors From 267f40dbb42e7bb6a18e83091d95297f277a5782 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 2 Feb 2026 09:38:07 +0000 Subject: [PATCH 080/182] Fix missing unused_variables lint when using a match guard Within a binding pattern match guard, only real reads of a bound local impact its liveness analysis - not the fake read that is injected. --- clippy_lints/src/time_subtraction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/time_subtraction.rs b/clippy_lints/src/time_subtraction.rs index 3ba59aefea06..ca8378ba7c6a 100644 --- a/clippy_lints/src/time_subtraction.rs +++ b/clippy_lints/src/time_subtraction.rs @@ -85,7 +85,7 @@ impl LateLintPass<'_> for UncheckedTimeSubtraction { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { let (lhs, rhs) = match expr.kind { ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Sub,) => (lhs, rhs), - ExprKind::MethodCall(fn_name, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { + ExprKind::MethodCall(_, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { (lhs, rhs) }, _ => return, From 73d06be9f3eaf94960ac95f8d5986b5eddfe1008 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Jan 2026 09:18:09 +0100 Subject: [PATCH 081/182] Set hidden visibility on naked functions in compiler-builtins 88b46460fa1483b3283b7f1e37c7abd033610a68 made builtin functions hidden, but it doesn't apply to naked functions, which are generated through a different code path. --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) 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 } From 81c0218ae8d0b9d3895974d2945ac836113f2371 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 27 Jan 2026 19:06:53 +0100 Subject: [PATCH 082/182] aarch64: use `read_unaligned` for `vld1_*` --- .../src/arm_shared/neon/generated.rs | 734 ++++++------------ .../spec/neon/arm_shared.spec.yml | 92 +-- 2 files changed, 266 insertions(+), 560 deletions(-) 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 2f52e3b52b07..c2e90d41eff0 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 @@ -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,7 +16964,7 @@ 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)"] @@ -17072,7 +16976,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_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"), @@ -17083,7 +16987,7 @@ 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))) + 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)"] @@ -17095,7 +16999,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_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"), @@ -17106,7 +17010,7 @@ 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))) + 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)"] @@ -17118,7 +17022,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_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"), @@ -17129,7 +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))) + 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)"] @@ -17242,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"), @@ -17256,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)"] @@ -17273,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"), @@ -17287,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)"] @@ -17304,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"), @@ -17318,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)"] @@ -17335,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"), @@ -17349,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)"] @@ -17366,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"), @@ -17380,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)"] @@ -17397,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"), @@ -17411,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)"] @@ -17428,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"), @@ -17442,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)"] @@ -17459,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"), @@ -17473,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)"] @@ -17490,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"), @@ -17504,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)"] @@ -17521,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"), @@ -17535,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)"] @@ -17552,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"), @@ -17566,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)"] @@ -17583,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"), @@ -17597,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)"] @@ -17614,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"), @@ -17628,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)"] @@ -17645,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"), @@ -17659,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)"] @@ -17676,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"), @@ -17690,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)"] @@ -17707,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"), @@ -17721,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)"] @@ -17738,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"), @@ -17752,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)"] @@ -17769,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"), @@ -17783,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)"] @@ -17800,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"), @@ -17814,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)"] @@ -17831,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"), @@ -17845,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)"] @@ -17862,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"), @@ -17876,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)"] @@ -17893,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"), @@ -17907,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)"] @@ -17924,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"), @@ -17938,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)"] @@ -17955,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"), @@ -17969,15 +17689,7 @@ 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)"] @@ -17986,10 +17698,10 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_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"), @@ -18000,7 +17712,7 @@ 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))) + 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)"] @@ -18009,10 +17721,10 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_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"), @@ -18023,7 +17735,7 @@ 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))) + 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)"] @@ -18032,10 +17744,10 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_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"), @@ -18046,7 +17758,7 @@ 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))) + 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)"] @@ -18055,10 +17767,10 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_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"), @@ -18069,7 +17781,7 @@ 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))) + 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)"] @@ -18078,10 +17790,10 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_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"), @@ -18092,7 +17804,7 @@ 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))) + 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)"] @@ -18101,10 +17813,10 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_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"), @@ -18115,7 +17827,7 @@ 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))) + 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)"] @@ -18124,10 +17836,10 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_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"), @@ -18138,7 +17850,7 @@ 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))) + 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)"] @@ -18147,10 +17859,10 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_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"), @@ -18161,7 +17873,7 @@ 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))) + 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)"] @@ -18170,10 +17882,10 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_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"), @@ -18184,7 +17896,7 @@ 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))) + 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)"] @@ -18193,10 +17905,10 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_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"), @@ -18207,7 +17919,7 @@ 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))) + 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)"] @@ -18216,10 +17928,10 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_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"), @@ -18230,7 +17942,7 @@ 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))) + 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)"] @@ -18239,10 +17951,10 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_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"), @@ -18253,7 +17965,7 @@ 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))) + 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)"] @@ -18262,10 +17974,10 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_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"), @@ -18276,7 +17988,7 @@ 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))) + 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)"] @@ -18285,10 +17997,10 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_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"), @@ -18299,7 +18011,7 @@ 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))) + 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)"] @@ -18308,10 +18020,10 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_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"), @@ -18322,7 +18034,7 @@ 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))) + 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)"] @@ -18331,10 +18043,10 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_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"), @@ -18345,7 +18057,7 @@ 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))) + 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)"] @@ -18354,10 +18066,10 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_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"), @@ -18368,7 +18080,7 @@ 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))) + 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)"] @@ -18377,10 +18089,10 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_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"), @@ -18391,7 +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))) + 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)"] @@ -18400,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"), @@ -18414,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)"] @@ -18423,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"), @@ -18437,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)"] @@ -18446,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"), @@ -18460,7 +18172,7 @@ 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)"] @@ -18469,10 +18181,10 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_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"), @@ -18483,7 +18195,7 @@ 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))) + 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)"] @@ -18492,10 +18204,10 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_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"), @@ -18506,7 +18218,7 @@ 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))) + 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)"] @@ -18515,10 +18227,10 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_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"), @@ -18529,7 +18241,7 @@ 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))) + 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)"] @@ -18538,10 +18250,10 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_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"), @@ -18552,7 +18264,7 @@ 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))) + 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)"] @@ -18561,10 +18273,10 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_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"), @@ -18575,7 +18287,7 @@ 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))) + 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)"] @@ -18584,10 +18296,10 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_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"), @@ -18598,7 +18310,7 @@ 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))) + 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)"] @@ -18607,10 +18319,10 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_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"), @@ -18621,7 +18333,7 @@ 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))) + 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)"] @@ -18630,10 +18342,10 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_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"), @@ -18644,7 +18356,7 @@ 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))) + 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)"] @@ -18653,10 +18365,10 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_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"), @@ -18667,7 +18379,7 @@ 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))) + 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)"] @@ -18676,10 +18388,10 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_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"), @@ -18690,7 +18402,7 @@ 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))) + 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)"] @@ -18699,10 +18411,10 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_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"), @@ -18713,7 +18425,7 @@ 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))) + 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)"] @@ -18722,10 +18434,10 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_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"), @@ -18736,7 +18448,7 @@ 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))) + 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)"] @@ -18745,10 +18457,10 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_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"), @@ -18759,7 +18471,7 @@ 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))) + 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)"] @@ -18768,10 +18480,10 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_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"), @@ -18782,7 +18494,7 @@ 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))) + 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)"] @@ -18791,10 +18503,10 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_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"), @@ -18805,7 +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))) + crate::ptr::read_unaligned(a.cast()) } #[inline(always)] #[rustc_legacy_const_generics(1)] 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 3ec7ba8814e5..c726d1a028a5 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 @@ -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,8 +2675,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 big_endian_inverse: false @@ -2723,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" @@ -2738,7 +2735,7 @@ 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 @@ -2752,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" @@ -2766,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: @@ -2776,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" @@ -2790,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 @@ -2804,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" From 5e5772d11f3ffd6e9dc4e5e14dd075db8f10976f Mon Sep 17 00:00:00 2001 From: Snehal Date: Tue, 3 Feb 2026 15:32:52 +0000 Subject: [PATCH 083/182] aarch64: Guard RCPC3 intrinsics with target_has_atomic = "64" The `vldap1` and `vstl1` RCPC3 intrinsics introduced in standard library unconditionally use `AtomicI64`. This breaks builds on target that do not support 64-bit atomics, such as `aarch64-unknown-none` with `max-atomic-width` set to 0. This commit adds a `#[cfg(target_has_atomic = "64")]` guard to these intrinsics --- .../core_arch/src/aarch64/neon/generated.rs | 15 +++++++++++++++ .../stdarch-gen-arm/spec/neon/aarch64.spec.yml | 8 ++++++++ 2 files changed, 23 insertions(+) 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 3d5d07ac1b4e..a81914af7838 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -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))) @@ -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; 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 a099c2c8d694..1c95bbe3d3a6 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 @@ -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',''] From baca8648563b4b71113c051a2d5e3636c11f5c87 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 4 Feb 2026 13:13:44 +0100 Subject: [PATCH 084/182] Set hidden visibility for compiler-builtins statics too. --- compiler/rustc_codegen_llvm/src/mono_item.rs | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) 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); From e4e725aec63cc773acf74b27e91dfc0630a8724f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:35:28 +0000 Subject: [PATCH 085/182] Convert to inline diagnostics in all codegen backends --- messages.ftl | 8 -------- src/errors.rs | 8 ++++---- src/lib.rs | 7 ------- 3 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 messages.ftl diff --git a/messages.ftl b/messages.ftl deleted file mode 100644 index b9b77b7d18c6..000000000000 --- a/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/src/errors.rs b/src/errors.rs index b252c39c0c05..f5815e723392 100644 --- a/src/errors.rs +++ b/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/src/lib.rs b/src/lib.rs index 00bea0222622..cc88fd02435e 100644 --- a/src/lib.rs +++ b/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; @@ -105,8 +104,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 { @@ -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" } From 691e2263690537f825e217d9ae03b45ad2637a5c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 5 Feb 2026 00:35:07 -0500 Subject: [PATCH 086/182] fix: handle false negative for `str_to_string` Replace `ToString::to_string` with `ToOwned::to_owned` when the function is passed as is: ```rust fn issue16511(x: Option<&str>) -> String { // Replace with ToOwned::to_owned x.map(ToString::to_string) } ``` --- clippy_lints/src/strings.rs | 18 ++++++++++++++++++ tests/ui/str_to_string.fixed | 29 +++++++++++++++++++++++++++++ tests/ui/str_to_string.rs | 29 +++++++++++++++++++++++++++++ tests/ui/str_to_string.stderr | 32 +++++++++++++++++++++++++++++++- 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index c0be724bcdee..509ad4e4fcb3 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -5,6 +5,7 @@ use clippy_utils::{ SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, method_calls, peel_blocks, sym, }; use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -410,6 +411,23 @@ impl<'tcx> LateLintPass<'tcx> for StrToString { diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability); }, ); + } else if let ExprKind::Path(_) = expr.kind + && let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) = &parent.kind + && args.iter().any(|a| a.hir_id == expr.hir_id) + && let Res::Def(DefKind::AssocFn, def_id) = expr.res(cx) + && cx.tcx.is_diagnostic_item(sym::to_string_method, def_id) + { + // Detected `ToString::to_string` passed as an argument (generic: any call or method call) + span_lint_and_sugg( + cx, + STR_TO_STRING, + expr.span, + "`ToString::to_string` used as `&str` to `String` converter", + "try", + "ToOwned::to_owned".to_string(), + Applicability::MachineApplicable, + ); } } } diff --git a/tests/ui/str_to_string.fixed b/tests/ui/str_to_string.fixed index 8713c4f9bc86..5b76cf78f069 100644 --- a/tests/ui/str_to_string.fixed +++ b/tests/ui/str_to_string.fixed @@ -22,3 +22,32 @@ fn issue16271(key: &[u8]) { let _value = t!(str::from_utf8(key)).to_owned(); //~^ str_to_string } + +struct GenericWrapper(T); + +impl GenericWrapper { + fn mapper U>(self, f: F) -> U { + f(self.0) + } +} + +fn issue16511(x: Option<&str>) { + let _ = x.map(ToOwned::to_owned); + //~^ str_to_string + + let _ = x.map(ToOwned::to_owned); + //~^ str_to_string + + let _ = ["a", "b"].iter().map(ToOwned::to_owned); + //~^ str_to_string + + fn mapper String>(f: F) -> String { + f("hello") + } + let _ = mapper(ToOwned::to_owned); + //~^ str_to_string + + let w = GenericWrapper("hello"); + let _ = w.mapper(ToOwned::to_owned); + //~^ str_to_string +} diff --git a/tests/ui/str_to_string.rs b/tests/ui/str_to_string.rs index b81759e1037b..f099eb29b1b5 100644 --- a/tests/ui/str_to_string.rs +++ b/tests/ui/str_to_string.rs @@ -22,3 +22,32 @@ fn issue16271(key: &[u8]) { let _value = t!(str::from_utf8(key)).to_string(); //~^ str_to_string } + +struct GenericWrapper(T); + +impl GenericWrapper { + fn mapper U>(self, f: F) -> U { + f(self.0) + } +} + +fn issue16511(x: Option<&str>) { + let _ = x.map(ToString::to_string); + //~^ str_to_string + + let _ = x.map(str::to_string); + //~^ str_to_string + + let _ = ["a", "b"].iter().map(ToString::to_string); + //~^ str_to_string + + fn mapper String>(f: F) -> String { + f("hello") + } + let _ = mapper(ToString::to_string); + //~^ str_to_string + + let w = GenericWrapper("hello"); + let _ = w.mapper(ToString::to_string); + //~^ str_to_string +} diff --git a/tests/ui/str_to_string.stderr b/tests/ui/str_to_string.stderr index c0a38c8ebe46..296b8e36f28c 100644 --- a/tests/ui/str_to_string.stderr +++ b/tests/ui/str_to_string.stderr @@ -19,5 +19,35 @@ error: `to_string()` called on a `&str` LL | let _value = t!(str::from_utf8(key)).to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(str::from_utf8(key)).to_owned()` -error: aborting due to 3 previous errors +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:35:19 + | +LL | let _ = x.map(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:38:19 + | +LL | let _ = x.map(str::to_string); + | ^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:41:35 + | +LL | let _ = ["a", "b"].iter().map(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:47:20 + | +LL | let _ = mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:51:22 + | +LL | let _ = w.mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: aborting due to 8 previous errors From e94a62d8001b1c12b317174ae887c5d619294254 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:04:55 +0100 Subject: [PATCH 087/182] mGCA: Support directly represented negated literals --- clippy_lints/src/utils/author.rs | 2 +- clippy_utils/src/consts.rs | 2 +- clippy_utils/src/hir_utils.rs | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e6fadc783621..d5191794b6b0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), - ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind"), + ConstArgKind::Literal { .. } => chain!(self, "let ConstArgKind::Literal {{ .. }} = {const_arg}.kind"), } } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index e2ada37d53b3..8177a5806d78 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -1142,7 +1142,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::TupleCall(..) | ConstArgKind::Array(..) | ConstArgKind::Path(_) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index b9f104a79a27..abc6885bef2d 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -686,7 +686,16 @@ impl HirEqInterExpr<'_, '_, '_> { .zip(*args_b) .all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b)) }, - (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, + ( + ConstArgKind::Literal { + lit: kind_l, + negated: negated_l, + }, + ConstArgKind::Literal { + lit: kind_r, + negated: negated_r, + }, + ) => kind_l == kind_r && negated_l == negated_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() && l_arr @@ -703,7 +712,7 @@ impl HirEqInterExpr<'_, '_, '_> { | ConstArgKind::TupleCall(..) | ConstArgKind::Infer(..) | ConstArgKind::Struct(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::Array(..) | ConstArgKind::Error(..), _, @@ -1599,7 +1608,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {}, - ConstArgKind::Literal(lit) => lit.hash(&mut self.s), + ConstArgKind::Literal { lit, negated } => { + lit.hash(&mut self.s); + negated.hash(&mut self.s); + }, } } From f090e9ce83e0873591e5faca204cfb68da93ff67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:02:06 +0100 Subject: [PATCH 088/182] Port rustc_intrinsic to the new attribute parser --- clippy_lints/src/loops/empty_loop.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops/empty_loop.rs b/clippy_lints/src/loops/empty_loop.rs index e809987d75a0..0a5b26bfa689 100644 --- a/clippy_lints/src/loops/empty_loop.rs +++ b/clippy_lints/src/loops/empty_loop.rs @@ -1,8 +1,9 @@ use super::EMPTY_LOOP; use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_in_panic_handler, is_no_std_crate, sym}; +use clippy_utils::{is_in_panic_handler, is_no_std_crate}; -use rustc_hir::{Block, Expr, ItemKind, Node}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; use rustc_lint::LateContext; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_>) { @@ -10,7 +11,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_ if let Node::Item(parent_node) = cx.tcx.hir_node(parent_hir_id) && matches!(parent_node.kind, ItemKind::Fn { .. }) && let attrs = cx.tcx.hir_attrs(parent_hir_id) - && attrs.iter().any(|attr| attr.has_name(sym::rustc_intrinsic)) + && find_attr!(attrs, AttributeKind::RustcIntrinsic) { // Intrinsic functions are expanded into an empty loop when lowering the AST // to simplify the job of later passes which might expect any function to have a body. From 236dac8d0e41ae9d4e31908c9a0a3fdf2789f5f6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 7 Feb 2026 14:02:33 -0500 Subject: [PATCH 089/182] fix: remove unnecessary trailing commas in format strings This PR makes the new comma-removing lint PR less noisy, allowing it focus only on the new functionality --- clippy_dev/src/new_lint.rs | 4 ++-- clippy_lints/src/cargo/lint_groups_priority.rs | 2 +- clippy_lints/src/casts/cast_possible_truncation.rs | 2 +- clippy_lints/src/doc/doc_suspicious_footnotes.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/implicit_hasher.rs | 4 ++-- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- clippy_lints/src/matches/match_like_matches.rs | 2 +- clippy_lints/src/methods/bytes_nth.rs | 2 +- clippy_lints/src/methods/into_iter_on_ref.rs | 2 +- clippy_lints/src/methods/manual_try_fold.rs | 2 +- clippy_lints/src/methods/unit_hash.rs | 2 +- clippy_lints/src/missing_asserts_for_indexing.rs | 6 +++--- clippy_lints/src/missing_enforced_import_rename.rs | 2 +- clippy_lints/src/ptr/cmp_null.rs | 2 +- clippy_lints/src/toplevel_ref_arg.rs | 2 +- clippy_lints/src/zero_div_zero.rs | 2 +- clippy_lints/src/zero_repeat_side_effects.rs | 2 +- rustc_tools_util/src/lib.rs | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 0b6d702d7721..72f281ca4d9d 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -167,9 +167,9 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let camel_name = to_camel_case(lint.name); let new_lint = if enable_msrv { - format!("Box::new(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf))),\n ",) + format!("Box::new(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf))),\n ") } else { - format!("Box::new(|{ctor_arg}| Box::new({module_name}::{camel_name})),\n ",) + format!("Box::new(|{ctor_arg}| Box::new({module_name}::{camel_name})),\n ") }; lib_rs.insert_str(comment_start, &new_lint); diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs index 14c5e22fb9cd..f937f065d6e0 100644 --- a/clippy_lints/src/cargo/lint_groups_priority.rs +++ b/clippy_lints/src/cargo/lint_groups_priority.rs @@ -100,7 +100,7 @@ fn check_table(cx: &LateContext<'_>, table: &DeTable<'_>, known_groups: &FxHashS "to have lints override the group set `{}` to a lower priority", group.as_ref() ), - format!("{{ level = {:?}, priority = {low_priority} }}", group_config.level,), + format!("{{ level = {:?}, priority = {low_priority} }}", group_config.level), Applicability::MaybeIncorrect, ); }, diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 2eebe8492327..0591afaa6c58 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -117,7 +117,7 @@ pub(super) fn check( return; } - format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",) + format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}") }, (ty::Adt(def, _), Some(to_nbits)) if def.is_enum() => { diff --git a/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/clippy_lints/src/doc/doc_suspicious_footnotes.rs index deca29a1885f..dfa6c9637864 100644 --- a/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -91,7 +91,7 @@ pub fn check(cx: &LateContext<'_>, doc: &str, range: Range, fragments: &F diag.span_suggestion_verbose( this_fragment.span.shrink_to_hi(), "add footnote definition", - format!("\n\n{label}: ", label = &doc[start..end],), + format!("\n\n{label}: ", label = &doc[start..end]), Applicability::HasPlaceholders, ); } else { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 3b9c70e23e20..7a64d3135fa5 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -337,7 +337,7 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { else_span, format!("this looks like {looks_like} but the `else` is missing"), None, - format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",), + format!("to remove this lint, add the missing `else` or add a new line before {next_thing}"), ); } } diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 9dc74a157cbf..70176c62772b 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { ), ( target.span(), - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + format!("{}<{}, S>", target.type_name(), target.type_arguments()), ), ]; suggestions.extend(vis.suggestions); @@ -352,7 +352,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { ); self.suggestions.insert( e.span, - format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())",), + format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())"), ); }, _ => {}, diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index abbc43d8e9b0..421c6064284d 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -173,7 +173,7 @@ fn handle( expr.span, format!("this pattern reimplements `{ty_name}::unwrap_or`"), "replace with", - format!("{suggestion}.unwrap_or({reindented_or_body})",), + format!("{suggestion}.unwrap_or({reindented_or_body})"), app, ); } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index c26b2dbde7fc..347560b14eea 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -187,7 +187,7 @@ pub(super) fn check_match<'tcx>( diag.span_suggestion_verbose( e.span, "use `matches!` directly", - format!("{}matches!({snippet}, {pat_and_guard})", if b0 { "" } else { "!" },), + format!("{}matches!({snippet}, {pat_and_guard})", if b0 { "" } else { "!" }), applicability, ); }, diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs index 40d521d61c11..0a3ea3005e72 100644 --- a/clippy_lints/src/methods/bytes_nth.rs +++ b/clippy_lints/src/methods/bytes_nth.rs @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E parent.span, format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"), "try", - format!("{receiver}.as_bytes()[{n}]",), + format!("{receiver}.as_bytes()[{n}]"), applicability, ); } else { diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index c4b116af4871..5a062732721e 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa cx, INTO_ITER_ON_REF, method_span, - format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",), + format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`"), "call directly", method_name.to_string(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index f2e127bedde5..5f5944d5d423 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>( fold_span, "usage of `Iterator::fold` on a type that implements `Try`", "use `try_fold` instead", - format!("try_fold({init_snip}, {args_snip} ...)",), + format!("try_fold({init_snip}, {args_snip} ...)"), Applicability::HasPlaceholders, ); } diff --git a/clippy_lints/src/methods/unit_hash.rs b/clippy_lints/src/methods/unit_hash.rs index 9defd5626eb4..fb447a99abdc 100644 --- a/clippy_lints/src/methods/unit_hash.rs +++ b/clippy_lints/src/methods/unit_hash.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' diag.span_suggestion( expr.span, "remove the call to `hash` or consider using", - format!("0_u8.hash({})", snippet(cx, arg.span, ".."),), + format!("0_u8.hash({})", snippet(cx, arg.span, "..")), Applicability::MaybeIncorrect, ); diag.note("the implementation of `Hash` for `()` is a no-op"); diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index 87ee164a1760..651382fb4bfe 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -364,15 +364,15 @@ fn report_indexes(cx: &LateContext<'_>, map: UnindexMap> // `v.len() < 5` and `v.len() <= 5` does nothing in terms of bounds checks. // The user probably meant `v.len() > 5` LengthComparison::LengthLessThanInt | LengthComparison::LengthLessThanOrEqualInt => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `5 < v.len()` == `v.len() > 5` LengthComparison::IntLessThanLength if asserted_len < highest_index => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `5 <= v.len() == `v.len() >= 5` LengthComparison::IntLessThanOrEqualLength if asserted_len <= highest_index => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `highest_index` here is rather a length, so we need to add 1 to it LengthComparison::LengthEqualInt if asserted_len < highest_index + 1 => match macro_call { diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs index 5dd38cf059c2..1f9652a2bd38 100644 --- a/clippy_lints/src/missing_enforced_import_rename.rs +++ b/clippy_lints/src/missing_enforced_import_rename.rs @@ -97,7 +97,7 @@ impl LateLintPass<'_> for ImportRename { span_without_semi, "this import should be renamed", "try", - format!("{import} as {name}",), + format!("{import} as {name}"), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/ptr/cmp_null.rs b/clippy_lints/src/ptr/cmp_null.rs index f2d1c855eddd..5e1c62316b7d 100644 --- a/clippy_lints/src/ptr/cmp_null.rs +++ b/clippy_lints/src/ptr/cmp_null.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( expr.span, "comparing with null is better expressed by the `.is_null()` method", "try", - format!("{invert}{non_null_path_snippet}.is_null()",), + format!("{invert}{non_null_path_snippet}.is_null()"), applicability, ); true diff --git a/clippy_lints/src/toplevel_ref_arg.rs b/clippy_lints/src/toplevel_ref_arg.rs index 250c277ab5e1..bce2ede6589b 100644 --- a/clippy_lints/src/toplevel_ref_arg.rs +++ b/clippy_lints/src/toplevel_ref_arg.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ToplevelRefArg { diag.span_suggestion( stmt.span, "try", - format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, ".."),), + format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, "..")), app, ); }, diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index bb0cab3a3075..e44c4dc9776e 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { expr.span, "constant division of `0.0` with `0.0` will always result in NaN", None, - format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",), + format!("consider using `{float_type}::NAN` if you would like a constant representing NaN"), ); } } diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs index 95085161c09c..cb254cc15629 100644 --- a/clippy_lints/src/zero_repeat_side_effects.rs +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -168,7 +168,7 @@ fn assign_expr_suggestion( let indent = snippet_indent(cx, outer_expr.span).unwrap_or_default(); let var_name = snippet(cx, assign_expr_span.source_callsite(), ".."); if needs_curly { - format!("{{\n {indent}{inner_expr};\n {indent}{var_name} = {vec_str}[] as {return_type}\n{indent}}}",) + format!("{{\n {indent}{inner_expr};\n {indent}{var_name} = {vec_str}[] as {return_type}\n{indent}}}") } else { format!("{inner_expr};\n{indent}{var_name} = {vec_str}[] as {return_type}") } diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 194ed84d04c2..3b7d2d4085d9 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -91,7 +91,7 @@ impl std::fmt::Debug for VersionInfo { self.crate_name, self.major, self.minor, self.patch, )?; if let Some(ref commit_hash) = self.commit_hash { - write!(f, ", commit_hash: \"{}\"", commit_hash.trim(),)?; + write!(f, ", commit_hash: \"{}\"", commit_hash.trim())?; } if let Some(ref commit_date) = self.commit_date { write!(f, ", commit_date: \"{}\"", commit_date.trim())?; From 7c95f57bc95c36f44a50fffb07cb2b933184ee2b Mon Sep 17 00:00:00 2001 From: mikhailofff Date: Sun, 8 Feb 2026 11:25:51 +0400 Subject: [PATCH 090/182] fix outdated doc comments --- book/src/development/type_checking.md | 2 +- tests/ui/unconditional_recursion.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 578836ecc568..d1c88619d598 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -154,7 +154,7 @@ in this chapter: [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type [is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char -[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834 +[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1429-1432 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index d9f4c07dc902..09a0de21ccd0 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -334,7 +334,7 @@ mod issue12154 { } // Not necessarily related to the issue but another FP from the http crate that was fixed with it: - // https://docs.rs/http/latest/src/http/header/name.rs.html#1424 + // https://docs.rs/http/latest/src/http/header/name.rs.html#1408 // We used to simply peel refs from the LHS and RHS, so we couldn't differentiate // between `PartialEq for &T` and `PartialEq<&T> for T` impls. #[derive(PartialEq)] From dfef1209b1ed4d4bb9eee0d00fe3df1154e3edf7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 22:33:56 +0100 Subject: [PATCH 091/182] x86: use `intrinsics::simd` for masked truncated saturating stores --- .../crates/core_arch/src/x86/avx512bw.rs | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) 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)] From eb2ba7d6b9429297c582fed42fd5da5e5a51cd8f Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 9 Feb 2026 18:18:24 +0900 Subject: [PATCH 092/182] fix ICE in supertrait_vtable_slot when supertrait has missing generics --- .../src/traits/vtable.rs | 11 +++- .../vtable/missing-generics-issue-151330.rs | 23 ++++++++ .../missing-generics-issue-151330.stderr | 53 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/vtable/missing-generics-issue-151330.rs create mode 100644 tests/ui/traits/vtable/missing-generics-issue-151330.stderr diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 584c8e2a27c8..539c1d3a35ba 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -434,7 +434,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/tests/ui/traits/vtable/missing-generics-issue-151330.rs b/tests/ui/traits/vtable/missing-generics-issue-151330.rs new file mode 100644 index 000000000000..352ad7be3d3a --- /dev/null +++ b/tests/ui/traits/vtable/missing-generics-issue-151330.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver=globally +// Regression test for issue https://github.com/rust-lang/rust/issues/151330 + +trait Supertrait {} + +trait Trait

: Supertrait {} +//~^ ERROR missing generics for trait `Supertrait` +//~| ERROR missing generics for trait `Supertrait` +//~| ERROR missing generics for trait `Supertrait` + +impl

Trait

for () {} + +const fn upcast

(x: &dyn Trait

) -> &dyn Trait

{ + x +} + +const fn foo() -> &'static dyn Supertrait<()> { + upcast::<()>(&()) +} + +const _: &'static dyn Supertrait<()> = foo(); + +fn main() {} diff --git a/tests/ui/traits/vtable/missing-generics-issue-151330.stderr b/tests/ui/traits/vtable/missing-generics-issue-151330.stderr new file mode 100644 index 000000000000..65ef08cad32a --- /dev/null +++ b/tests/ui/traits/vtable/missing-generics-issue-151330.stderr @@ -0,0 +1,53 @@ +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. From 3339b061af6a9c37ae326f60895048ddbbf3cd6d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 7 Feb 2026 19:24:59 +0000 Subject: [PATCH 093/182] Do not require `'static` for obtaining reflection information. --- library/core/src/intrinsics/mod.rs | 2 +- library/core/src/mem/type_info.rs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 051dda731881..094def9796db 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2887,7 +2887,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/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b30803c97c9..d3a7421ff2ee 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() } } } From 389294dcde4f50e9c910e5da6aca0582ced13796 Mon Sep 17 00:00:00 2001 From: Nora Breitmoser-Widdecke <23097564+puzzlewolf@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:35:09 +0100 Subject: [PATCH 094/182] Fix documentation for `indexing_slicing` Replace typo'd name with link to the lint. --- clippy_lints/src/indexing_slicing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index a2fcdb4a54b4..e9ddd3ca8ede 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { /// Checks for usage of indexing or slicing that may panic at runtime. /// /// This lint does not report on indexing or slicing operations - /// that always panic, clippy's `out_of_bound_indexing` already + /// that always panic, [out_of_bounds_indexing](#out_of_bounds_indexing) already /// handles those cases. /// /// ### Why restrict this? From 00432c0b85ecd3a099fbe4b0f867f3929b099366 Mon Sep 17 00:00:00 2001 From: mikhailofff Date: Mon, 9 Feb 2026 18:54:17 +0400 Subject: [PATCH 095/182] fix dead links in type checking section of the doc --- book/src/development/type_checking.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 578836ecc568..55adb0aceadd 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -146,7 +146,7 @@ in this chapter: - [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) - [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html) -- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) +- [Type checking](https://rustc-dev-guide.rust-lang.org/hir-typeck/summary.html) - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) [Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html#variant.Adt @@ -163,5 +163,5 @@ in this chapter: [TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html [middle_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html -[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Ty.html +[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Ty.html [lower_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/fn.lower_ty.html From 9bf9a12381bfab41c5d7c7a1d3f5c1457064575d Mon Sep 17 00:00:00 2001 From: Keith-Cancel Date: Thu, 5 Feb 2026 22:01:57 -0800 Subject: [PATCH 096/182] Allow provisional mgca syntax of type const = to be reconized. Revert, but without type const. Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those. Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added. Fix for tidyfmt and some errors when manually resolving a merge conflicts. Update these tests to use update error messages and type const syntax. Update comments and error message to use new syntax instead of old type_const attribute. Remove the type_const attribute update some more tests to use the new syntax. Update these test cases. update feature gate test Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled. Create a new feature gate that checks for the feature before expansion. Make rustfmt handle the `type const` syntax correctly. Add a convience method to check if a RhsKind is type const. Rename `Const` discriminant to `Body` for `ConstItemRhsKind` Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for. Update formatting for these match statements. Update clippy test to use type const syntax. Update test to use type const syntax. update rustfmt to match ast items. Update clippy to match ast and hir items. Few more test cases that used old attribute, instead of 'type const' Update to match the output from the feature gate checks. tidyfmt adjustments. Update the is_type_const, so I can constrain record!(..) in encoder.rs Update conditional compilation test. Move the feature gate to after expansion to allow for cfg(...) to work. Update some more tests to use the new syntax. Update type const tests in associated-const-bindings to use new syntax. Don't check based off the attribute, but the item here. Update some tests outside of the const_generics folder that were using #[type_const] update the tests in associated consts that use #[type_const] to use type const Update these mgca tests with the type const syntax. Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code. Don't need into for these now that it's a query. Add is_type_const query to handle foreign def ids. update this test to use type const syntax. Fix logic here, we only want to lower if there is expression in this case. Update built-in macros to use ConstItemRhsKind Update more instance of the old ConstItemRhs. Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion. Update lower to use ConstItemKind Add an other helper method to check if the rhs kinda has an expr. Update item parse to use ConstItemKind enum. Felt the field name could a be little clear when editing a few other things. Change the ConstItem struct see know if we have a type const or regular const. Make sure this syntax is properly feature gated. --- clippy_lints/src/non_copy_const.rs | 4 +-- clippy_lints/src/types/mod.rs | 2 +- clippy_utils/src/ast_utils/mod.rs | 28 +++++++++++-------- ...duplication_in_bounds_assoc_const_eq.fixed | 4 +-- ...it_duplication_in_bounds_assoc_const_eq.rs | 4 +-- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index f99748127a8f..e09fc0a76366 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -739,7 +739,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Const(_, ct_rhs_opt) = item.kind + if let TraitItemKind::Const(_, ct_rhs_opt, _) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) { IsFreeze::No => true, @@ -931,7 +931,7 @@ fn get_const_hir_value<'tcx>( { match tcx.hir_node(tcx.local_def_id_to_hir_id(did)) { Node::ImplItem(item) if let ImplItemKind::Const(.., ct_rhs) = item.kind => (did, ct_rhs), - Node::TraitItem(item) if let TraitItemKind::Const(.., Some(ct_rhs)) = item.kind => (did, ct_rhs), + Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs), _) = item.kind => (did, ct_rhs), _ => return None, } }, diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 7018146f184b..7d97ce97f487 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { }; match item.kind { - TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { + TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => { self.check_ty(cx, ty, context); }, TraitItemKind::Fn(ref sig, trait_method) => { diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index cf8716398efb..3b043f7565ef 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -355,7 +355,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -363,7 +363,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -371,7 +371,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -615,7 +615,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -623,7 +623,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -631,7 +631,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -791,12 +791,18 @@ pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { eq_expr(&l.value, &r.value) } -pub fn eq_const_item_rhs(l: &ConstItemRhs, r: &ConstItemRhs) -> bool { - use ConstItemRhs::*; +pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { + use ConstItemRhsKind::*; match (l, r) { - (TypeConst(l), TypeConst(r)) => eq_anon_const(l, r), - (Body(l), Body(r)) => eq_expr(l, r), - (TypeConst(..), Body(..)) | (Body(..), TypeConst(..)) => false, + (TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r), + (TypeConst { rhs: None }, TypeConst { rhs: None }) => true, + (TypeConst { rhs: Some(..) }, TypeConst { rhs: None }) => false, + (TypeConst { rhs: None }, TypeConst { rhs: Some(..) }) => false, + (Body { rhs: Some(l) }, Body { rhs: Some(r) }) => eq_expr(l, r), + (Body { rhs: None }, Body { rhs: None }) => true, + (Body { rhs: None }, Body { rhs: Some(..) }) => false, + (Body { rhs: Some(..) }, Body { rhs: None }) => false, + (TypeConst {..}, Body { .. }) | ( Body { .. }, TypeConst { .. }) => false, } } diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed index f8be3331317c..8d63fc44e7f8 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs index a0d7a653993f..36a83619c0f9 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where From 41e0e0690f74685f094d88ae2a0f05379e38873f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 9 Feb 2026 19:12:13 +0100 Subject: [PATCH 097/182] Move `inline_fluent` to a proc macro --- compiler/rustc_macros/src/diagnostics/inline_fluent.rs | 10 ++++++++++ compiler/rustc_macros/src/diagnostics/mod.rs | 2 ++ compiler/rustc_macros/src/lib.rs | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 compiler/rustc_macros/src/diagnostics/inline_fluent.rs diff --git a/compiler/rustc_macros/src/diagnostics/inline_fluent.rs b/compiler/rustc_macros/src/diagnostics/inline_fluent.rs new file mode 100644 index 000000000000..ab0ed6aa6e0e --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/inline_fluent.rs @@ -0,0 +1,10 @@ +use syn::{LitStr, parse_macro_input}; + +use crate::diagnostics::message::Message; + +pub(crate) fn inline_fluent(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/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 09f05ce972f1..d9168939dd48 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,11 +1,13 @@ mod diagnostic; mod diagnostic_builder; mod error; +mod inline_fluent; mod message; mod subdiagnostic; mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; +pub(super) use inline_fluent::inline_fluent; use proc_macro2::TokenStream; use subdiagnostic::SubdiagnosticDerive; use synstructure::Structure; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 8cd6c0264448..3d2111b86881 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -241,6 +241,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 inline_fluent(input: TokenStream) -> TokenStream { + diagnostics::inline_fluent(input) +} + decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. From 6eb2a8fa9ef2b35d34b021550942cc327fa93b3a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 9 Feb 2026 19:12:22 +0100 Subject: [PATCH 098/182] Reformat existing error messages --- .../src/const_eval/eval_queries.rs | 6 +- .../src/const_eval/machine.rs | 16 +- compiler/rustc_const_eval/src/errors.rs | 212 +++++++++--------- .../src/interpret/intrinsics.rs | 10 +- .../rustc_const_eval/src/interpret/memory.rs | 56 ++--- compiler/rustc_errors/src/diagnostic_impls.rs | 12 +- compiler/rustc_errors/src/lib.rs | 3 +- compiler/rustc_errors/src/translation.rs | 11 - .../rustc_lint/src/impl_trait_overcaptures.rs | 2 +- compiler/rustc_lint/src/lints.rs | 16 +- compiler/rustc_lint/src/non_fmt_panic.rs | 10 +- compiler/rustc_middle/src/middle/stability.rs | 28 ++- .../src/lint_tail_expr_drop_order.rs | 10 +- compiler/rustc_passes/src/errors.rs | 6 +- .../src/error_reporting/infer/region.rs | 10 +- compiler/rustc_trait_selection/src/errors.rs | 104 +++++---- .../src/errors/note_and_explain.rs | 62 ++--- 17 files changed, 299 insertions(+), 275 deletions(-) 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 25da90298791..131e17ac3173 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -471,9 +471,9 @@ fn report_eval_error<'tcx>( span, inline_fluent!( "evaluation of `{$instance}` failed {$num_frames -> - [0] here - *[other] inside this call -}" + [0] here + *[other] inside this call + }" ), ); for frame in frames { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index da4f97db1c59..8bc515a8b1b5 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -491,10 +491,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Err(err) => throw_ub_custom!( inline_fluent!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} -}" + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" ), name = "const_allocate", err_kind = err.diag_ident(), @@ -521,10 +521,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Err(err) => throw_ub_custom!( inline_fluent!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} -}" + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" ), name = "const_deallocate", err_kind = err.diag_ident(), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index a673e0cb1efb..cba2c462bf22 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -393,16 +393,17 @@ impl Subdiagnostic for FrameNote { } let msg = diag.eagerly_translate(inline_fluent!( r#"{$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] {""} -} -"# + [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_"); @@ -663,89 +664,96 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { 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(_, _) => inline_fluent!("{$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 { .. } => inline_fluent!("{$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, .. } => inline_fluent!("{$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 { .. } => inline_fluent!("{$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 { .. } => inline_fluent!("{$msg -> - [AccessedPtr] accessing memory - *[other] accessing memory based on pointer -} with alignment {$has}, but alignment {$required} is required"), + PointerUseAfterFree(_, _) => inline_fluent!( + "{$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 { .. } => inline_fluent!( + "{$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, .. } => inline_fluent!( + "{$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 { .. } => inline_fluent!( + "{$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 { .. } => inline_fluent!( + "{$msg -> + [AccessedPtr] accessing memory + *[other] accessing memory based on pointer + } with alignment {$has}, but alignment {$required} is required" + ), WriteToReadOnly(_) => inline_fluent!("writing to {$allocation} which is read-only"), DerefFunctionPointer(_) => inline_fluent!("accessing {$allocation} which contains a function"), DerefVTablePointer(_) => inline_fluent!("accessing {$allocation} which contains a vtable"), @@ -936,9 +944,9 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { NullFnPtr { .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} function pointer" + [true] maybe-null + *[false] null + } function pointer" ) } NeverVal => { @@ -1021,17 +1029,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { NullPtr { ptr_kind: PointerKind::Box, .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} box" + [true] maybe-null + *[false] null + } box" ) } NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} reference" + [true] maybe-null + *[false] null + } reference" ) } DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 2ea5e4a25c11..7c49ba79a342 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -461,10 +461,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( - inline_fluent!("`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> - [true] address - *[false] offset -} than second: {$a_offset} < {$b_offset}"), + inline_fluent!( + "`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, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 28dae2ef3b8b..200155ab010e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -293,10 +293,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub_custom!( inline_fluent!( "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} -} {$ptr} which does not point to the beginning of an object" + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" ), ptr = format!("{ptr:?}"), kind = "realloc" @@ -379,10 +379,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub_custom!( inline_fluent!( "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} -} {$ptr} which does not point to the beginning of an object" + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" ), ptr = format!("{ptr:?}"), kind = "dealloc", @@ -396,11 +396,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "fn", @@ -410,11 +410,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "vtable", @@ -424,11 +424,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "typeid", @@ -438,11 +438,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "static_mem" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index c36afc6fc889..ae3e33498ea1 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -60,11 +60,13 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { .with_arg("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - Diag::new(dcx, level, inline_fluent!("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] {\"\"} - }")) + Diag::new(dcx, level, inline_fluent!( + "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()) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2e0afb8fc4c2..4eadb8249405 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -63,6 +63,7 @@ pub use rustc_error_messages::{ use rustc_hashes::Hash128; use rustc_lint_defs::LintExpectationId; pub use rustc_lint_defs::{Applicability, listify, pluralize}; +pub use rustc_macros::inline_fluent; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors}; @@ -1562,7 +1563,7 @@ impl DelayedDiagInner { let msg = match self.note.status() { BacktraceStatus::Captured => inline_fluent!( "delayed at {$emitted_at} -{$note}" + {$note}" ), // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index b5de3f87e9f3..c6d30032f1af 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -90,14 +90,3 @@ impl Translator { } } } - -/// This macro creates a translatable `DiagMessage` from a literal string. -/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired. -/// -/// This is a macro because in the future we may want to globally register these messages. -#[macro_export] -macro_rules! inline_fluent { - ($inline: literal) => { - rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline)) - }; -} diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 087403719968..aef0021d0660 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -446,7 +446,7 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { "specifically, {$num_captured -> [one] this lifetime is *[other] these lifetimes are - } in scope but not mentioned in the type's bounds" + } in scope but not mentioned in the type's bounds" ), ) .note(inline_fluent!( diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0aa5199cffc6..4ec59a3cb98f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -353,8 +353,10 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { self.label, inline_fluent!("will not be checked at usage sites of the type alias"), ); - diag.note(inline_fluent!("this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information")); + diag.note(inline_fluent!( + "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(inline_fluent!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); } @@ -1748,10 +1750,12 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { if doctest { diag.help(inline_fluent!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); } else { - diag.help(inline_fluent!("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.help(inline_fluent!( + "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(inline_fluent!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index daf62277693a..10a37637400b 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -196,10 +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( - inline_fluent!("{$already_suggested -> - [true] or use - *[false] use - } std::panic::panic_any instead"), + inline_fluent!( + "{$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_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fce0158aa511..903ef645207d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -128,19 +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 => inline_fluent!("use of deprecated {$kind} `{$path}`{$has_note -> - [true] : {$note} - *[other] {\"\"} - }"), - DeprecatedSinceKind::InFuture => inline_fluent!("use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> - [true] : {$note} - *[other] {\"\"} - }"), - DeprecatedSinceKind::InVersion(_) => { - inline_fluent!("use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + DeprecatedSinceKind::InEffect => inline_fluent!( + "use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} *[other] {\"\"} - }") + }" + ), + DeprecatedSinceKind::InFuture => inline_fluent!( + "use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ), + DeprecatedSinceKind::InVersion(_) => { + inline_fluent!( + "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_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 789398c58880..448ed78702b7 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 @@ -542,10 +542,12 @@ impl Subdiagnostic for LocalLabel<'_> { dtor.add_to_diag(diag); } let msg = - diag.eagerly_translate(inline_fluent!("{$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.eagerly_translate(inline_fluent!( + "{$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); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f420bba9b4e9..8a70302c4c4e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -684,9 +684,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { // There were some functions named `main` though. Try to give the user a hint. inline_fluent!( "the main function must be defined at the crate level{$has_filename -> - [true] {\" \"}(in `{$filename}`) - *[false] {\"\"} - }" + [true] {\" \"}(in `{$filename}`) + *[false] {\"\"} + }" ) } else if self.has_filename { inline_fluent!("consider adding a `main` function to `{$filename}`") 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 d15fb40dd1cb..c99dde6d45b9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -252,10 +252,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues -> -[true] ... -*[false] {\"\"} -}"), + msg: inline_fluent!( + "...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(), } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 013e4b522fb5..529a7fcf5f1c 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -102,10 +102,16 @@ 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, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> -[none] {\"\"} -*[default] {\" \"}for type `{$self_desc}` -}:")); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!( + "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); @@ -157,9 +163,9 @@ impl Subdiagnostic for AdjustSignatureBorrow { diag.multipart_suggestion_verbose( inline_fluent!( "consider adjusting the signature so it borrows its {$borrow_len -> -[one] argument -*[other] arguments -}" + [one] argument + *[other] arguments + }" ), to_borrow, Applicability::MaybeIncorrect, @@ -170,9 +176,9 @@ impl Subdiagnostic for AdjustSignatureBorrow { diag.multipart_suggestion_verbose( inline_fluent!( "consider adjusting the signature so it does not borrow its {$remove_borrow_len -> -[one] argument -*[other] arguments -}" + [one] argument + *[other] arguments + }" ), remove_borrow, Applicability::MaybeIncorrect, @@ -505,18 +511,18 @@ impl Subdiagnostic for RegionOriginNote<'_> { span, inline_fluent!( "...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 -}" + [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); @@ -531,18 +537,18 @@ impl Subdiagnostic for RegionOriginNote<'_> { span, inline_fluent!( "...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 -}" + [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); @@ -578,9 +584,9 @@ impl Subdiagnostic for LifetimeMismatchLabels { span, inline_fluent!( "...but data{$label_var1_exists -> -[true] {\" \"}from `{$label_var1}` -*[false] {\"\"} -} is returned here" + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } is returned here" ), ); diag.arg("label_var1_exists", label_var1.is_some()); @@ -614,12 +620,12 @@ impl Subdiagnostic for LifetimeMismatchLabels { span, inline_fluent!( "...but data{$label_var1_exists -> -[true] {\" \"}from `{$label_var1}` -*[false] {\"\"} -} flows{$label_var2_exists -> -[true] {\" \"}into `{$label_var2}` -*[false] {\"\"} -} here" + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } flows{$label_var2_exists -> + [true] {\" \"}into `{$label_var2}` + *[false] {\"\"} + } here" ), ); diag.arg("label_var1_exists", label_var1.is_some()); @@ -789,12 +795,12 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { diag.multipart_suggestion_verbose( inline_fluent!( "consider {$is_reuse -> -[true] reusing -*[false] introducing -} a named lifetime parameter{$is_impl -> -[true] {\" \"}and update trait if needed -*[false] {\"\"} -}" + [true] reusing + *[false] introducing + } a named lifetime parameter{$is_impl -> + [true] {\" \"}and update trait if needed + *[false] {\"\"} + }" ), visitor.suggestions, Applicability::MaybeIncorrect, 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 8e86b8fae157..6a7e1d252806 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -171,37 +171,37 @@ impl Subdiagnostic for RegionExplanation<'_> { let msg = diag.eagerly_translate(inline_fluent!( "{$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 -}" + *[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 { From aefb9a9ae261dae8d84b801c9396dd571a75339a Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 9 Feb 2026 14:07:30 -0500 Subject: [PATCH 099/182] tests: adapt align-offset.rs for InstCombine improvements in LLVM 23 Upstream has improved InstCombine so that it can shrink added constants using known zeroes, which caused a little bit of change in this test. As far as I can tell either output is fine, so we just accept both. --- tests/assembly-llvm/align_offset.rs | 8 ++++---- tests/codegen-llvm/align-offset.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/assembly-llvm/align_offset.rs b/tests/assembly-llvm/align_offset.rs index d9902ce336b0..5663dca30b25 100644 --- a/tests/assembly-llvm/align_offset.rs +++ b/tests/assembly-llvm/align_offset.rs @@ -4,7 +4,7 @@ #![crate_type = "rlib"] // CHECK-LABEL: align_offset_byte_ptr -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq #[no_mangle] @@ -13,7 +13,7 @@ pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { } // CHECK-LABEL: align_offset_byte_slice -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq #[no_mangle] @@ -22,7 +22,7 @@ pub fn align_offset_byte_slice(slice: &[u8]) -> usize { } // CHECK-LABEL: align_offset_word_ptr -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq // CHECK: shrq @@ -35,7 +35,7 @@ pub fn align_offset_word_ptr(ptr: *const u32) -> usize { } // CHECK-LABEL: align_offset_word_slice -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq // CHECK: shrq diff --git a/tests/codegen-llvm/align-offset.rs b/tests/codegen-llvm/align-offset.rs index 21062cc0a914..383e9dd45dab 100644 --- a/tests/codegen-llvm/align-offset.rs +++ b/tests/codegen-llvm/align-offset.rs @@ -24,7 +24,7 @@ pub fn align_to4(x: &[u8]) -> bool { #[no_mangle] pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE:i[0-9]+]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[OFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] @@ -41,7 +41,7 @@ pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { #[no_mangle] pub fn align_offset_word_slice(slice: &[Align4]) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %slice.0 to [[USIZE]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2 @@ -57,7 +57,7 @@ pub fn align_offset_word_slice(slice: &[Align4]) -> usize { #[no_mangle] pub fn align_offset_word_ptr(ptr: *const Align4) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] From c750a1f5c49ba99f15de43fb651c7958012a12f2 Mon Sep 17 00:00:00 2001 From: AprilNEA Date: Mon, 9 Feb 2026 19:31:25 +0000 Subject: [PATCH 100/182] Add regression test for type_const with unit struct ctor under mGCA Unit struct constructors used as the RHS of a `type const` associated const used to ICE during normalization because they were lowered as `Const::new_unevaluated` with a Ctor def_id. The compiler now properly constructs a concrete ValTree value for const constructors. --- .../mgca/type-const-ctor-148953.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-ctor-148953.rs diff --git a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs new file mode 100644 index 000000000000..bdd3dcf8618f --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs @@ -0,0 +1,31 @@ +//! Regression test for +//! +//! Unit struct constructors used as the RHS of a `type const` associated +//! const used to ICE during normalization because they were lowered as +//! `Const::new_unevaluated` with a Ctor def_id. Fixed by adding proper const +//! constructor support that produces a concrete ValTree value instead. + +//@ check-pass + +#![feature(min_generic_const_args, adt_const_params)] +#![expect(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +struct S; + +impl S { + type const N: S = S; +} + +#[derive(ConstParamTy, PartialEq, Eq)] +enum E { + V, +} + +impl E { + type const M: E = { E::V }; +} + +fn main() {} From b1847b59cc0fecb8973d82366b72f994e8841331 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 10 Feb 2026 09:13:45 +0000 Subject: [PATCH 101/182] Remove SubdiagMessage in favour of the identical DiagMessage --- clippy_utils/src/diagnostics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 8a19039a7fe7..4ba9af58f90a 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage}; +use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan}; #[cfg(debug_assertions)] use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions}; use rustc_hir::HirId; @@ -155,7 +155,7 @@ pub fn span_lint_and_help( span: impl Into, msg: impl Into, help_span: Option, - help: impl Into, + help: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -216,7 +216,7 @@ pub fn span_lint_and_note( span: impl Into, msg: impl Into, note_span: Option, - note: impl Into, + note: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -390,7 +390,7 @@ pub fn span_lint_and_sugg( lint: &'static Lint, sp: Span, msg: impl Into, - help: impl Into, + help: impl Into, sugg: String, applicability: Applicability, ) { From 11e4873b96961d14202a8c63d83a21be5b7f7b82 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 10 Feb 2026 10:22:05 -0500 Subject: [PATCH 102/182] Fix typos and grammar in compiler and build documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - compiler/rustc_codegen_llvm/src/debuginfo/doc.md: fix 5 issues (adaption → adaptation, "allow to" → "allow V-ing" x3, later → latter + plural) - compiler/rustc_thread_pool/src/sleep/README.md: fix 2 issues (idle → active per context, then → than) - src/bootstrap/README.md: fix 2 issues (rust → Rust, add missing article "the") - src/ci/docker/README.md: fix 2 issues ("come form" → "come from", grammar) --- compiler/rustc_codegen_llvm/src/debuginfo/doc.md | 10 +++++----- compiler/rustc_thread_pool/src/sleep/README.md | 4 ++-- src/bootstrap/README.md | 4 ++-- src/ci/docker/README.md | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) 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_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/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/ci/docker/README.md b/src/ci/docker/README.md index 4ee02e9bf005..5d3a74edc995 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 From d74b276d1d0f79b90a92084a0fc20bcaacdcc417 Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Sat, 18 Oct 2025 01:21:47 +0100 Subject: [PATCH 103/182] Precommit tests for `SliceIndex` method codegen Add a `codegen-llvm` test to check the number of `icmp` instrucitons generated for each `SliceIndex` method on the various range types. This will be updated in the next commit when `SliceIndex::get` is optimized for `RangeInclusive`. --- tests/codegen-llvm/slice-range-indexing.rs | 96 ++++++++++++++++++++++ tests/codegen-llvm/str-range-indexing.rs | 94 +++++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 tests/codegen-llvm/slice-range-indexing.rs create mode 100644 tests/codegen-llvm/str-range-indexing.rs diff --git a/tests/codegen-llvm/slice-range-indexing.rs b/tests/codegen-llvm/slice-range-indexing.rs new file mode 100644 index 000000000000..5c47cab6234e --- /dev/null +++ b/tests/codegen-llvm/slice-range-indexing.rs @@ -0,0 +1,96 @@ +//@ compile-flags: -Copt-level=3 +//@ min-llvm-version: 21 + +#![crate_type = "lib"] + +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; + +macro_rules! tests { + ($range_ty:ty, $get_func_name:ident, $index_func_name:ident) => { + #[no_mangle] + pub fn $get_func_name(slice: &[u32], range: $range_ty) -> Option<&[u32]> { + slice.get(range) + } + + #[no_mangle] + pub fn $index_func_name(slice: &[u32], range: $range_ty) -> &[u32] { + &slice[range] + } + }; +} + +// 2 comparisons required: +// end <= len && start <= end + +// CHECK-LABEL: @get_range +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(Range, get_range, index_range); + +// 3 comparisons required: +// end != usize::MAX && end + 1 <= len && start <= end + 1 + +// CHECK-LABEL: @get_range_inclusive +// CHECK-COUNT-3: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// 2 comparisons required: +// end < len && start <= end + 1 + +// CHECK-LABEL: @index_range_inclusive +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); + +// 1 comparison required: +// end <= len + +// CHECK-LABEL: @get_range_to +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeTo, get_range_to, index_range_to); + +// 2 comparisons required: +// end != usize::MAX && end + 1 <= len + +// CHECK-LABEL: @get_range_to_inclusive +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// 1 comparison required: +// end < len + +// CHECK-LABEL: @index_range_to_inclusive +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeToInclusive, get_range_to_inclusive, index_range_to_inclusive); + +// 1 comparison required: +// start <= len + +// CHECK-LABEL: @get_range_from +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_from +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeFrom, get_range_from, index_range_from); diff --git a/tests/codegen-llvm/str-range-indexing.rs b/tests/codegen-llvm/str-range-indexing.rs new file mode 100644 index 000000000000..3c35b26773cb --- /dev/null +++ b/tests/codegen-llvm/str-range-indexing.rs @@ -0,0 +1,94 @@ +//@ compile-flags: -Copt-level=3 +//@ min-llvm-version: 21 + +#![crate_type = "lib"] + +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; + +macro_rules! tests { + ($range_ty:ty, $get_func_name:ident, $index_func_name:ident) => { + #[no_mangle] + pub fn $get_func_name(slice: &str, range: $range_ty) -> Option<&str> { + slice.get(range) + } + + #[no_mangle] + pub fn $index_func_name(slice: &str, range: $range_ty) -> &str { + &slice[range] + } + }; +} + +// 9 comparisons required: +// start <= end +// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) +// && (end == 0 || (end >= len && end == len) || bytes[end] >= -0x40) + +// CHECK-LABEL: @get_range +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(Range, get_range, index_range); + +// 9 comparisons required: +// end != usize::MAX && start <= end + 1 +// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) +// && ( (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) + +// CHECK-LABEL: @get_range_inclusive +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_inclusive +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); + +// 4 comparisons required: +// end == 0 || (end >= len && end == len) || bytes[end] >= -0x40 + +// CHECK-LABEL: @get_range_to +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeTo, get_range_to, index_range_to); + +// 4 comparisons required: +// end != usize::MAX && (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) + +// CHECK-LABEL: @get_range_to_inclusive +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to_inclusive +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeToInclusive, get_range_to_inclusive, index_range_to_inclusive); + +// 4 comparisons required: +// start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) + +// CHECK-LABEL: @get_range_from +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_from +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeFrom, get_range_from, index_range_from); From 625b18027d4d8d9b2092cf3706b29a5812f76357 Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Fri, 25 Jul 2025 19:51:21 +0100 Subject: [PATCH 104/182] Optimize `SliceIndex::get` impl for `RangeInclusive` The checks for `self.end() == usize::MAX` and `self.end() + 1 > slice.len()` can be replaced with `self.end() >= slice.len()`, since `self.end() < slice.len()` implies both `self.end() <= slice.len()` and `self.end() < usize::MAX`. --- library/core/src/slice/index.rs | 38 ++++++++++++---------- tests/codegen-llvm/slice-range-indexing.rs | 26 ++++++--------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 31d9931e474a..3d769010ea1c 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -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] @@ -950,8 +949,7 @@ where R: ops::RangeBounds, { let len = bounds.end; - let r = into_range(len, (range.start_bound().copied(), range.end_bound().copied()))?; - if r.start > r.end || r.end > len { None } else { Some(r) } + into_range(len, (range.start_bound().copied(), range.end_bound().copied())) } /// Converts a pair of `ops::Bound`s into `ops::Range` without performing any @@ -982,21 +980,27 @@ pub(crate) const fn into_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) } diff --git a/tests/codegen-llvm/slice-range-indexing.rs b/tests/codegen-llvm/slice-range-indexing.rs index 5c47cab6234e..c4b3492dc4dc 100644 --- a/tests/codegen-llvm/slice-range-indexing.rs +++ b/tests/codegen-llvm/slice-range-indexing.rs @@ -33,17 +33,14 @@ macro_rules! tests { // CHECK: ret tests!(Range, get_range, index_range); -// 3 comparisons required: -// end != usize::MAX && end + 1 <= len && start <= end + 1 - -// CHECK-LABEL: @get_range_inclusive -// CHECK-COUNT-3: %{{.+}} = icmp -// CHECK-NOT: %{{.+}} = icmp -// CHECK: ret - // 2 comparisons required: // end < len && start <= end + 1 +// CHECK-LABEL: @get_range_inclusive +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + // CHECK-LABEL: @index_range_inclusive // CHECK-COUNT-2: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp @@ -64,17 +61,14 @@ tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); // CHECK: ret tests!(RangeTo, get_range_to, index_range_to); -// 2 comparisons required: -// end != usize::MAX && end + 1 <= len - -// CHECK-LABEL: @get_range_to_inclusive -// CHECK-COUNT-2: %{{.+}} = icmp -// CHECK-NOT: %{{.+}} = icmp -// CHECK: ret - // 1 comparison required: // end < len +// CHECK-LABEL: @get_range_to_inclusive +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + // CHECK-LABEL: @index_range_to_inclusive // CHECK-COUNT-1: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp From 262cd76333b79fb85bb87f2846b3db79c82d2402 Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Fri, 25 Jul 2025 21:57:44 +0100 Subject: [PATCH 105/182] Optimize `SliceIndex` for `RangeInclusive` Replace `self.end() == usize::MAX` and `self.end() + 1 > slice.len()` with `self.end() >= slice.len()`. Same reasoning as previous commit. Also consolidate the str panicking functions into function. --- library/alloctests/tests/str.rs | 22 ++++--- library/core/src/range.rs | 9 --- library/core/src/str/mod.rs | 64 ++++++++++++------- library/core/src/str/traits.rs | 61 ++++++++++-------- tests/codegen-llvm/str-range-indexing.rs | 20 +++--- ...const-eval-select-backtrace-std.run.stderr | 2 +- 6 files changed, 97 insertions(+), 81 deletions(-) diff --git a/library/alloctests/tests/str.rs b/library/alloctests/tests/str.rs index fcc4aaaa1dcd..096df0007b65 100644 --- a/library/alloctests/tests/str.rs +++ b/library/alloctests/tests/str.rs @@ -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/core/src/range.rs b/library/core/src/range.rs index fe488355ad15..0ef0d192a868 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -352,15 +352,6 @@ impl RangeInclusive { } } -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 } - } -} - #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for RangeInclusive { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index ab7389a1300c..5483b8e17bc3 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 b63fe96ea99d..6cac9418f9d7 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 @@ -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,17 +651,37 @@ 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) } } @@ -678,35 +691,29 @@ 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/tests/codegen-llvm/str-range-indexing.rs b/tests/codegen-llvm/str-range-indexing.rs index 3c35b26773cb..dee1a3a41c46 100644 --- a/tests/codegen-llvm/str-range-indexing.rs +++ b/tests/codegen-llvm/str-range-indexing.rs @@ -35,18 +35,18 @@ macro_rules! tests { // CHECK: ret tests!(Range, get_range, index_range); -// 9 comparisons required: -// end != usize::MAX && start <= end + 1 -// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) -// && ( (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) +// 7 comparisons required: +// end < len && start <= end + 1 +// && (start == 0 || start >= len || bytes[start] >= -0x40) +// && ( end + 1 >= len || bytes[end + 1] >= -0x40) // CHECK-LABEL: @get_range_inclusive -// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-COUNT-7: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret // CHECK-LABEL: @index_range_inclusive -// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-COUNT-7: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); @@ -65,16 +65,16 @@ tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); // CHECK: ret tests!(RangeTo, get_range_to, index_range_to); -// 4 comparisons required: -// end != usize::MAX && (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) +// 3 comparisons required: +// end < len && (end + 1 >= len || bytes[end + 1] >= -0x40) // CHECK-LABEL: @get_range_to_inclusive -// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-COUNT-3: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret // CHECK-LABEL: @index_range_to_inclusive -// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-COUNT-3: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret tests!(RangeToInclusive, get_range_to_inclusive, index_range_to_inclusive); diff --git a/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr index 397eeaf600ad..aee60c94f106 100644 --- a/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr +++ b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr @@ -1,4 +1,4 @@ thread 'main' ($TID) panicked at $DIR/const-eval-select-backtrace-std.rs:6:8: -byte index 1 is out of bounds of `` +start byte index 1 is out of bounds of `` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From 94ff542ff5c89e33d91a6a2f5e8bf17250c8d08c Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Mon, 2 Feb 2026 20:56:46 +0000 Subject: [PATCH 106/182] Make panic message less confusing The panic message when slicing a string with a negative length range (eg `"abcdef"[4..3]`) is confusing: it gives the condition that failed to hold, whilst all the other panic messages give the condition that did hold. Before: begin <= end (4 <= 3) when slicing `abcdef` After: begin > end (4 > 3) when slicing `abcdef` --- library/alloctests/tests/str.rs | 4 ++-- library/core/src/str/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloctests/tests/str.rs b/library/alloctests/tests/str.rs index 096df0007b65..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)"; } } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 5483b8e17bc3..98354643aa40 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -99,7 +99,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { // 3. range is backwards. if begin > end { - panic!("begin <= end ({begin} <= {end}) when slicing `{s_trunc}`{ellipsis}") + panic!("begin > end ({begin} > {end}) when slicing `{s_trunc}`{ellipsis}") } // 4. begin is inside a character. From f8cf68f35ab8a37df77f658b8b575a4902bd813b Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Mon, 2 Feb 2026 21:12:49 +0000 Subject: [PATCH 107/182] Give `into_range` more consistent name Rename `into_range` to `try_into_slice_range`: - Prepend `try_` to show that it returns `None` on error, like `try_range` - add `_slice` to make it consistent with `into_slice_range` --- library/core/src/slice/index.rs | 8 ++++---- library/core/src/str/traits.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 3d769010ea1c..3a76c098bb53 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -949,7 +949,7 @@ where R: ops::RangeBounds, { let len = bounds.end; - into_range(len, (range.start_bound().copied(), range.end_bound().copied())) + 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 @@ -976,7 +976,7 @@ pub(crate) const fn into_range_unchecked( /// Returns `None` on overflowing indices. #[rustc_const_unstable(feature = "const_range", issue = "none")] #[inline] -pub(crate) const fn into_range( +pub(crate) const fn try_into_slice_range( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> Option> { @@ -1043,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/str/traits.rs b/library/core/src/str/traits.rs index 6cac9418f9d7..edf07c0c16f4 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -382,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] From 14527b257fdee2b86569b6014754d3452c85b3c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 11 Feb 2026 10:53:38 +0000 Subject: [PATCH 108/182] Move target machine factory error reporting into codegen backend --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cc88fd02435e..a6501354c23e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -374,7 +374,7 @@ impl ExtraBackendMethods for GccCodegenBackend { _features: &[String], ) -> TargetMachineFactoryFn { // TODO(antoyo): set opt level. - Arc::new(|_| Ok(())) + Arc::new(|_, _| ()) } } @@ -421,7 +421,6 @@ unsafe impl Sync for SyncContext {} impl WriteBackendMethods for GccCodegenBackend { type Module = GccContext; type TargetMachine = (); - type TargetMachineError = (); type ModuleBuffer = ModuleBuffer; type ThinData = ThinData; type ThinBuffer = ThinBuffer; From a75ff82177dce22326d3ce335c29e0a9d338f943 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:31:51 +0000 Subject: [PATCH 109/182] Remove tm_factory field from CodegenContext This is necessary to support serializing the CodegenContext to a .rlink file in the future for moving LTO to the -Zlink-only step. --- src/back/lto.rs | 14 ++++++-------- src/back/write.rs | 6 +++--- src/lib.rs | 12 +++++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index c93a2e8f8da5..dda777a54002 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -50,7 +50,7 @@ struct LtoData { } fn prepare_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, each_linked_rlib_for_lto: &[PathBuf], dcx: DiagCtxtHandle<'_>, ) -> LtoData { @@ -111,7 +111,7 @@ 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, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -132,7 +132,7 @@ pub(crate) fn run_fat( } fn fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, _dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, @@ -283,7 +283,7 @@ impl ModuleBufferMethods for ModuleBuffer { /// 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, dcx: DiagCtxtHandle<'_>, each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, ThinBuffer)>, @@ -345,7 +345,7 @@ pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBu /// all of the `LtoModuleCodegen` units returned below and destroyed once /// they all go out of scope. fn thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, _dcx: DiagCtxtHandle<'_>, modules: Vec<(String, ThinBuffer)>, serialized_modules: Vec<(SerializedModule, CString)>, @@ -520,11 +520,9 @@ fn thin_lto( pub fn optimize_thin_module( thin_module: ThinModule, - _cgcx: &CodegenContext, + _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 diff --git a/src/back/write.rs b/src/back/write.rs index b6223c5be370..5e9644723475 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -14,10 +14,10 @@ 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, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, @@ -227,7 +227,7 @@ pub(crate) fn codegen( } pub(crate) fn save_temp_bitcode( - cgcx: &CodegenContext, + cgcx: &CodegenContext, _module: &ModuleCodegen, _name: &str, ) { diff --git a/src/lib.rs b/src/lib.rs index a6501354c23e..d490650c37f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -426,8 +426,9 @@ impl WriteBackendMethods for GccCodegenBackend { type ThinBuffer = ThinBuffer; fn run_and_optimize_fat_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, 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], @@ -437,7 +438,7 @@ impl WriteBackendMethods for GccCodegenBackend { } fn run_thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], @@ -457,7 +458,7 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize( - _cgcx: &CodegenContext, + _cgcx: &CodegenContext, _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, @@ -466,15 +467,16 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, _shared_emitter: &SharedEmitter, + _tm_factory: TargetMachineFactoryFn, thin: ThinModule, ) -> ModuleCodegen { back::lto::optimize_thin_module(thin, cgcx) } fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, From 5dac025910f389c900b43e14c8e3732dbcd16a51 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 10 Feb 2026 17:08:32 +0100 Subject: [PATCH 110/182] Do not lint main function in `must_use_candidates` Marking the `main` function as `#[must_use]` is nonsensical, as it is not really supposed to be called anyway. --- clippy_lints/src/functions/must_use.rs | 3 ++- tests/ui/must_use_candidates.fixed | 3 ++- tests/ui/must_use_candidates.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 68532de0368f..9ad36f778904 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -13,7 +13,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::source::snippet_indent; use clippy_utils::ty::is_must_use_ty; use clippy_utils::visitors::for_each_expr_without_closures; -use clippy_utils::{return_ty, trait_ref_of_method}; +use clippy_utils::{is_entrypoint_fn, return_ty, trait_ref_of_method}; use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; use rustc_span::Symbol; @@ -211,6 +211,7 @@ fn check_must_use_candidate<'tcx>( || !cx.effective_visibilities.is_exported(item_id.def_id) || is_must_use_ty(cx, return_ty(cx, item_id)) || item_span.from_expansion() + || is_entrypoint_fn(cx, item_id.def_id.to_def_id()) { return; } diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 1e8589cf39d6..a53e6e9b85be 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -104,6 +104,7 @@ pub extern "C" fn unmangled(i: bool) -> bool { !i } -fn main() { +pub fn main() -> std::process::ExitCode { assert_eq!(1, pure(1)); + std::process::ExitCode::SUCCESS } diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 71d546718ae7..6593d6c68a13 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -99,6 +99,7 @@ pub extern "C" fn unmangled(i: bool) -> bool { !i } -fn main() { +pub fn main() -> std::process::ExitCode { assert_eq!(1, pure(1)); + std::process::ExitCode::SUCCESS } From b20572ec56f361d636e2da1d49dde311187bed8f Mon Sep 17 00:00:00 2001 From: mikhailofff Date: Wed, 11 Feb 2026 18:24:05 +0400 Subject: [PATCH 111/182] change to github permalinks --- book/src/development/type_checking.md | 2 +- tests/ui/unconditional_recursion.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index d1c88619d598..342f8a026ae4 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -154,7 +154,7 @@ in this chapter: [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type [is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char -[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1429-1432 +[is_char_source]: https://github.com/rust-lang/rust/blob/d34f1f931489618efffc4007e6b6bdb9e10f6467/compiler/rustc_middle/src/ty/sty.rs#L1429-L1432 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index 09a0de21ccd0..e4dd33a8eeea 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -334,7 +334,7 @@ mod issue12154 { } // Not necessarily related to the issue but another FP from the http crate that was fixed with it: - // https://docs.rs/http/latest/src/http/header/name.rs.html#1408 + // https://github.com/hyperium/http/blob/5f0c86642f1dc86f156da82b62aceb2f4fab20e1/src/header/name.rs#L1408-L1420 // We used to simply peel refs from the LHS and RHS, so we couldn't differentiate // between `PartialEq for &T` and `PartialEq<&T> for T` impls. #[derive(PartialEq)] From e1ade997ab280b8bd7802b4667f5795d1dc982e4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 11 Feb 2026 19:03:00 +0100 Subject: [PATCH 112/182] Enable triagebot new `[view-all-comments-link]` feature --- triagebot.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 09dec7675e7e..eb8442ab21e2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -55,6 +55,11 @@ labels = ["S-waiting-on-concerns"] # Amend a review to include a link to what was changed since the review [review-changes-since] +# Adds a "View all comments" link on the issue/PR body that shows all the comments of it +# Documentation at: https://forge.rust-lang.org/triagebot/view-all-comments-link.html +[view-all-comments-link] +threshold = 20 + [assign] contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md" users_on_vacation = [ From 24b1392c874c5cb3cccabb668d1f569a8bab5057 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Wed, 11 Feb 2026 20:02:32 +0100 Subject: [PATCH 113/182] Bump nightly version -> 2026-02-11 --- clippy_utils/README.md | 2 +- rust-toolchain.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/README.md b/clippy_utils/README.md index 204a66a435ee..1b85dcfd848d 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-01-22 +nightly-2026-02-11 ``` diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c26289c23725..558f808a7a3e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-01-22" +channel = "nightly-2026-02-11" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 809af1f6353ceb0fef375c2ea89623deef07e8c4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 11:37:19 -0500 Subject: [PATCH 114/182] Fix clippy warnings --- src/builder.rs | 4 +++- src/common.rs | 8 ++++---- src/context.rs | 18 ++++++++++++++++-- src/intrinsic/llvm.rs | 14 +++++++------- src/type_.rs | 4 ++-- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index ea75b4294e04..6347a3fb19b4 100644 --- a/src/builder.rs +++ b/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_u64(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() } diff --git a/src/common.rs b/src/common.rs index e71e1216dbd9..1f133fa0c1b7 100644 --- a/src/common.rs +++ b/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> { @@ -55,7 +55,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_u64(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 +76,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_u64(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 +95,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_u64(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/src/context.rs b/src/context.rs index d4d4c490e75e..03f207f45724 100644 --- a/src/context.rs +++ b/src/context.rs @@ -201,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_u64(None, i64_type, 2)/*.get_aligned(i128_align)*/; - let u128_type = context.new_array_type_u64(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) }; @@ -608,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/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 5c8bc5a4791c..11a69acdde42 100644 --- a/src/intrinsic/llvm.rs +++ b/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_u64(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_u64(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_u64(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_u64(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_u64(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_u64(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()); diff --git a/src/type_.rs b/src/type_.rs index 7a6a5d3a10ea..3b1ee53f8336 100644 --- a/src/type_.rs +++ b/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_u64(None, ty, len) + new_array_type(self.context, None, ty, len) } } From dd1b72a0d8eacf5f774b0fcb34d86d772892a748 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 10 Feb 2026 10:50:57 -0500 Subject: [PATCH 115/182] Fix typos and grammar in documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Readme.md: add missing "you" ("If don't" → "If you don't") - Readme.md: fix wrong preposition ("without this backend" → "with this backend") - Readme.md: fix double space - doc/errors.md: fix transposed letters ("libgccijt" → "libgccjit") - doc/debugging.md: remove extra word ("Run do the command" → "Run the command") - doc/debugging.md: fix past participle ("cannot be ran" → "cannot be run") - doc/tips.md: add missing verb ("won't a chance" → "won't have a chance") - doc/gimple.md: fix preposition ("interested into" → "interested in") --- Readme.md | 6 +++--- doc/debugging.md | 4 ++-- doc/errors.md | 2 +- doc/gimple.md | 2 +- doc/tips.md | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Readme.md b/Readme.md index cd6aeae4b42e..ce5ee1e4adee 100644 --- a/Readme.md +++ b/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/doc/debugging.md b/doc/debugging.md index 6ff4edf8877c..853852271708 100644 --- a/doc/debugging.md +++ b/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/doc/errors.md b/doc/errors.md index 5727b0ff7c86..81621d49b4f1 100644 --- a/doc/errors.md +++ b/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/doc/gimple.md b/doc/gimple.md index 145c4eda3c1c..bd298d65ed26 100644 --- a/doc/gimple.md +++ b/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/doc/tips.md b/doc/tips.md index 38bc98c02d92..ff92566d4a1a 100644 --- a/doc/tips.md +++ b/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 From 590c1c9966caea982b0e6d946dd7637b8c08f0a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 19 Jan 2026 13:53:08 +0100 Subject: [PATCH 116/182] UnsafePinned: implement opsem effects of UnsafeUnpin --- compiler/rustc_middle/src/queries.rs | 4 +++ compiler/rustc_middle/src/ty/layout.rs | 12 ++++--- compiler/rustc_middle/src/ty/util.rs | 13 +++++-- compiler/rustc_ty_utils/src/abi.rs | 6 +++- compiler/rustc_ty_utils/src/common_traits.rs | 22 ++++++++---- library/core/src/marker.rs | 19 ++++++---- .../src/borrow_tracker/stacked_borrows/mod.rs | 8 +++-- .../src/borrow_tracker/tree_borrows/mod.rs | 3 +- .../tests/pass/both_borrows/unsafe_pinned.rs | 36 ++++++++++++++++--- tests/auxiliary/minicore.rs | 3 ++ tests/codegen-llvm/function-arguments.rs | 18 +++++++--- 11 files changed, 113 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index de2298914438..4d2ed8d57f4a 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1694,6 +1694,10 @@ rustc_queries! { 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 } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d3b4654a8d79..a9b54092c887 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1049,9 +1049,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 { @@ -1146,7 +1148,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/util.rs b/compiler/rustc_middle/src/ty/util.rs index e01a5721a5e0..d534c273ff65 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1189,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() { 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/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/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index a21898c506ab..2d054557da7e 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -71,7 +71,9 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) + && pointee.is_unsafe_unpin(*cx.tcx, cx.typing_env()) + { // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, @@ -129,7 +131,9 @@ impl NewPermission { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); - if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + if pointee.is_unpin(*cx.tcx, cx.typing_env()) + && pointee.is_unsafe_unpin(*cx.tcx, cx.typing_env()) + { // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // a weak protector). NewPermission::Uniform { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 173145788ee3..4f170f48aed8 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -133,7 +133,8 @@ impl<'tcx> NewPermission { retag_kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()); + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()) + && pointee.is_unsafe_unpin(*cx.tcx, cx.typing_env()); let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); let is_protected = retag_kind == RetagKind::FnEntry; diff --git a/src/tools/miri/tests/pass/both_borrows/unsafe_pinned.rs b/src/tools/miri/tests/pass/both_borrows/unsafe_pinned.rs index 0c75a07bfa2a..8e222e627956 100644 --- a/src/tools/miri/tests/pass/both_borrows/unsafe_pinned.rs +++ b/src/tools/miri/tests/pass/both_borrows/unsafe_pinned.rs @@ -9,8 +9,36 @@ fn mutate(x: &UnsafePinned) { unsafe { ptr.write(42) }; } -fn main() { - let x = UnsafePinned::new(0); - mutate(&x); - assert_eq!(x.into_inner(), 42); +fn mut_alias(x: &mut UnsafePinned, y: &mut UnsafePinned) { + unsafe { + x.get().write(0); + y.get().write(0); + x.get().write(0); + y.get().write(0); + } +} + +// Also try this with a type for which we implement `Unpin`, just to be extra mean. +struct MyUnsafePinned(UnsafePinned); +impl Unpin for MyUnsafePinned {} + +fn my_mut_alias(x: &mut MyUnsafePinned, y: &mut MyUnsafePinned) { + unsafe { + x.0.get().write(0); + y.0.get().write(0); + x.0.get().write(0); + y.0.get().write(0); + } +} + +fn main() { + let mut x = UnsafePinned::new(0i32); + mutate(&x); + assert_eq!(unsafe { x.get().read() }, 42); + + let ptr = &raw mut x; + unsafe { mut_alias(&mut *ptr, &mut *ptr) }; + + let ptr = ptr.cast::>(); + unsafe { my_mut_alias(&mut *ptr, &mut *ptr) }; } diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 95b217c13031..c4546f4dea93 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -76,6 +76,9 @@ pub trait BikeshedGuaranteedNoDrop {} #[lang = "freeze"] pub unsafe auto trait Freeze {} +#[lang = "unsafe_unpin"] +pub unsafe auto trait UnsafeUnpin {} + #[lang = "unpin"] #[diagnostic::on_unimplemented( note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index b5febca3b87b..46e153a0cfc6 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -1,9 +1,9 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes #![crate_type = "lib"] #![feature(rustc_attrs)] -#![feature(allocator_api)] +#![feature(allocator_api, unsafe_unpin)] -use std::marker::PhantomPinned; +use std::marker::{PhantomPinned, UnsafeUnpin}; use std::mem::MaybeUninit; use std::num::NonZero; use std::ptr::NonNull; @@ -259,11 +259,21 @@ pub fn trait_raw(_: *const dyn Drop) {} // CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) #[no_mangle] -pub fn trait_box(_: Box) {} +pub fn trait_box(_: Box) {} + +// Ensure that removing *either* `Unpin` or `UnsafeUnpin` is enough to lose the attribute. +// CHECK: @trait_box_pin1(ptr noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) +#[no_mangle] +pub fn trait_box_pin1(_: Box) {} +// CHECK: @trait_box_pin2(ptr noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) +#[no_mangle] +pub fn trait_box_pin2(_: Box) {} // CHECK: { ptr, ptr } @trait_option(ptr noalias noundef align 1 %x.0, ptr %x.1) #[no_mangle] -pub fn trait_option(x: Option>) -> Option> { +pub fn trait_option( + x: Option>, +) -> Option> { x } From 0cbe1cc992f712704abdcbbcb35db431ab181bbc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 21 Jan 2026 08:49:25 +0100 Subject: [PATCH 117/182] try to work around rustdoc bug, and other rustdoc adjustments --- library/core/src/num/nonzero.rs | 2 +- .../auto/auto-trait-bounds-by-associated-type-50159.rs | 3 ++- tests/rustdoc-html/empty-section.rs | 4 +++- tests/rustdoc-html/synthetic_auto/basic.rs | 3 ++- tests/rustdoc-html/synthetic_auto/manual.rs | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7876fced1c98..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; } diff --git a/tests/rustdoc-html/auto/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc-html/auto/auto-trait-bounds-by-associated-type-50159.rs index 2803c4da437f..14981783e5f3 100644 --- a/tests/rustdoc-html/auto/auto-trait-bounds-by-associated-type-50159.rs +++ b/tests/rustdoc-html/auto/auto-trait-bounds-by-associated-type-50159.rs @@ -20,7 +20,8 @@ where //@ has - '//h3[@class="code-header"]' 'impl Send for Switchwhere ::Item: Send' //@ has - '//h3[@class="code-header"]' 'impl Sync for Switchwhere ::Item: Sync' //@ count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6 +//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 7 +// The number here will need updating when new auto traits are added: ^ pub struct Switch { pub inner: ::Item2, } diff --git a/tests/rustdoc-html/empty-section.rs b/tests/rustdoc-html/empty-section.rs index 71ebc66d6953..1e6e725a5a7b 100644 --- a/tests/rustdoc-html/empty-section.rs +++ b/tests/rustdoc-html/empty-section.rs @@ -1,13 +1,15 @@ #![crate_name = "foo"] -#![feature(negative_impls, freeze_impls, freeze)] +#![feature(negative_impls, freeze_impls, freeze, unsafe_unpin)] pub struct Foo; //@ has foo/struct.Foo.html //@ !hasraw - 'Auto Trait Implementations' +// Manually un-implement all auto traits for Foo: impl !Send for Foo {} impl !Sync for Foo {} impl !std::marker::Freeze for Foo {} +impl !std::marker::UnsafeUnpin for Foo {} impl !std::marker::Unpin for Foo {} impl !std::panic::RefUnwindSafe for Foo {} impl !std::panic::UnwindSafe for Foo {} diff --git a/tests/rustdoc-html/synthetic_auto/basic.rs b/tests/rustdoc-html/synthetic_auto/basic.rs index 9daf8963997a..e8c2f5da9fe6 100644 --- a/tests/rustdoc-html/synthetic_auto/basic.rs +++ b/tests/rustdoc-html/synthetic_auto/basic.rs @@ -2,7 +2,8 @@ //@ has - '//h3[@class="code-header"]' 'impl Send for Foowhere T: Send' //@ has - '//h3[@class="code-header"]' 'impl Sync for Foowhere T: Sync' //@ count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 -//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6 +//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 7 +// The number here will need updating when new auto traits are added: ^ pub struct Foo { field: T, } diff --git a/tests/rustdoc-html/synthetic_auto/manual.rs b/tests/rustdoc-html/synthetic_auto/manual.rs index bbf361a6e596..830bfccca09e 100644 --- a/tests/rustdoc-html/synthetic_auto/manual.rs +++ b/tests/rustdoc-html/synthetic_auto/manual.rs @@ -6,7 +6,8 @@ // 'impl Send for Foo' // //@ count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1 -//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5 +//@ count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6 +// The number here will need updating when new auto traits are added: ^ pub struct Foo { field: T, } From 13189f48cfd5f481110135a23e63d438e26c76d0 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 12 Feb 2026 11:38:22 +0000 Subject: [PATCH 118/182] use `?` instead of `*` for return types --- library/proc_macro/src/bridge/client.rs | 2 +- library/proc_macro/src/bridge/mod.rs | 2 +- library/proc_macro/src/bridge/server.rs | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 02a408802b6f..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)? { diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 6a9027046af0..603adf720789 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -133,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 { diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index a3c6a232264e..dc9aa5a72870 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -60,7 +60,7 @@ struct Dispatcher { 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 + Default; @@ -83,7 +83,7 @@ with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol); macro_rules! define_dispatcher { ( - $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* ) => { // FIXME(eddyb) `pub` only for `ExecutionStrategy` below. pub trait DispatcherTrait { @@ -100,9 +100,7 @@ macro_rules! define_dispatcher { 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. From 2f24a5e491adcbe681df4db7874fa0e4c45d8c76 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 12 Feb 2026 11:38:33 +0000 Subject: [PATCH 119/182] remove `DispatcherTrait` --- library/proc_macro/src/bridge/server.rs | 34 +++++++++++-------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index dc9aa5a72870..3ab9f40de750 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -53,11 +53,6 @@ impl Decode<'_, '_, HandleStore> for MarkedSpan { } } -struct Dispatcher { - handle_store: HandleStore, - server: S, -} - macro_rules! define_server { ( $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* @@ -81,16 +76,17 @@ macro_rules! define_server { } with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol); +// 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)?;)* ) => { - // FIXME(eddyb) `pub` only for `ExecutionStrategy` below. - pub trait DispatcherTrait { - fn dispatch(&mut self, buf: Buffer) -> Buffer; - } - - impl DispatcherTrait for Dispatcher { + impl Dispatcher { fn dispatch(&mut self, mut buf: Buffer) -> Buffer { let Dispatcher { handle_store, server } = self; @@ -126,9 +122,9 @@ macro_rules! define_dispatcher { with_api!(define_dispatcher, MarkedTokenStream, MarkedSpan, MarkedSymbol); pub trait ExecutionStrategy { - fn run_bridge_and_client( + 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, @@ -182,9 +178,9 @@ impl

ExecutionStrategy for MaybeCrossThread

where P: MessagePipe + Send + 'static, { - fn run_bridge_and_client( + 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, @@ -205,9 +201,9 @@ where pub struct SameThread; impl ExecutionStrategy for SameThread { - fn run_bridge_and_client( + 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, @@ -232,9 +228,9 @@ impl

ExecutionStrategy for CrossThread

where P: MessagePipe + Send + 'static, { - fn run_bridge_and_client( + 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, From 293e9506204aa8c33a23887f4a74163f6a63c0b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:16:18 +0000 Subject: [PATCH 120/182] Remove SelfProfilerRef from CodegenContext It can't be serialized to a file. --- src/back/lto.rs | 16 +++++++++++----- src/back/write.rs | 22 ++++++++++------------ src/lib.rs | 12 +++++++++--- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index dda777a54002..9a9040708ef8 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -30,6 +30,7 @@ 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; @@ -112,6 +113,7 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// for further optimization. pub(crate) fn run_fat( cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -123,6 +125,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, @@ -133,13 +136,14 @@ pub(crate) fn run_fat( fn fat_lto( 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 +227,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)) }); @@ -284,6 +287,7 @@ impl ModuleBufferMethods for ModuleBuffer { /// can simply be copied over from the incr. comp. cache. pub(crate) fn run_thin( cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, ThinBuffer)>, @@ -298,6 +302,7 @@ pub(crate) fn run_thin( } thin_lto( cgcx, + prof, dcx, modules, lto_data.upstream_modules, @@ -345,7 +350,8 @@ pub(crate) fn prepare_thin(module: ModuleCodegen) -> (String, ThinBu /// 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)>, @@ -353,7 +359,7 @@ fn thin_lto( cached_modules: Vec<(SerializedModule, WorkProduct)>, //_symbols_below_threshold: &[String], ) -> (Vec>, Vec) { - let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis"); + let _timer = prof.generic_activity("LLVM_thin_lto_global_analysis"); info!("going for that thin, thin LTO"); /*let green_modules: FxHashMap<_, _> = diff --git a/src/back/write.rs b/src/back/write.rs index 5e9644723475..ddf13558027b 100644 --- a/src/back/write.rs +++ b/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; @@ -18,6 +19,7 @@ use crate::{GccContext, LtoMode}; pub(crate) fn codegen( 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); } diff --git a/src/lib.rs b/src/lib.rs index d490650c37f7..24a065d69eca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,7 @@ use rustc_codegen_ssa::target_features::cfg_target_feature; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, 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}; @@ -427,6 +428,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, _tm_factory: TargetMachineFactoryFn, // FIXME(bjorn3): Limit LTO exports to these symbols @@ -434,11 +436,12 @@ impl WriteBackendMethods for GccCodegenBackend { 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, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], @@ -446,7 +449,7 @@ impl WriteBackendMethods for GccCodegenBackend { 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) + back::lto::run_thin(cgcx, prof, dcx, each_linked_rlib_for_lto, modules, cached_modules) } fn print_pass_timings(&self) { @@ -459,6 +462,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize( _cgcx: &CodegenContext, + _prof: &SelfProfilerRef, _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, @@ -468,6 +472,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize_thin( cgcx: &CodegenContext, + _prof: &SelfProfilerRef, _shared_emitter: &SharedEmitter, _tm_factory: TargetMachineFactoryFn, thin: ThinModule, @@ -477,11 +482,12 @@ impl WriteBackendMethods for GccCodegenBackend { fn codegen( 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) { From 9448bdf798aae371e3e00e7a2aa4de7994580e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20Kenan=20G=C3=BCng=C3=B6r?= Date: Thu, 12 Feb 2026 16:59:44 +0300 Subject: [PATCH 121/182] bootstrap: add explicit UTF-8 encoding to text-mode open() calls --- src/bootstrap/bootstrap.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 366fa8e150f8..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("#"): @@ -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="") From f5a8b86695fb7109d494f8aed595318e76957d36 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 27 Nov 2025 22:57:19 +0900 Subject: [PATCH 122/182] WF check lifetime bounds for locals with type params --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 2 +- ....run2-{closure#0}.Inline.panic-unwind.diff | 2 +- ...undant.InstSimplify-after-simplifycfg.diff | 10 ++-- ...mut_range.PreCodegen.after.panic-abort.mir | 2 +- ...ut_range.PreCodegen.after.panic-unwind.mir | 2 +- ...dex_range.PreCodegen.after.panic-abort.mir | 2 +- ...ex_range.PreCodegen.after.panic-unwind.mir | 2 +- ...ked_range.PreCodegen.after.panic-abort.mir | 2 +- ...ed_range.PreCodegen.after.panic-unwind.mir | 2 +- tests/ui/consts/issue-102117.stderr | 4 +- ...om-env-universe-err-project.current.stderr | 7 +-- tests/ui/nll/issue-98693.stderr | 2 +- tests/ui/nll/type-test-universe.stderr | 2 +- .../ui/regions/forall-wf-ref-reflexive.stderr | 2 +- .../wf-bound-region-in-local-issue-115175.rs | 11 ++++ ...-bound-region-in-local-issue-115175.stderr | 17 +++++++ ...-region-in-local-soundness-issue-148854.rs | 51 +++++++++++++++++++ ...ion-in-local-soundness-issue-148854.stderr | 17 +++++++ .../implied_lifetime_wf_check3.stderr | 2 +- .../implied_lifetime_wf_check4_static.stderr | 2 +- 21 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 tests/ui/regions/wf-bound-region-in-local-issue-115175.rs create mode 100644 tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr create mode 100644 tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs create mode 100644 tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cfb798b31ea0..e8d5ff017cf8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -581,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> { diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 4c1b25c786ef..9f4d085e19d1 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -197,8 +197,8 @@ + StorageLive(_40); + _40 = &raw mut _19; + _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_40); + _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageDead(_40); + StorageLive(_42); + _42 = Option::<()>::None; + _35 = copy ((*_37).0: std::option::Option<()>); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 59417ce64651..50cf7164028a 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -208,8 +208,8 @@ + StorageLive(_40); + _40 = &raw mut _19; + _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_40); + _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageDead(_40); + StorageLive(_42); + _42 = Option::<()>::None; + _35 = copy ((*_37).0: std::option::Option<()>); diff --git a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff index afa25ecdbfba..75038e899b3e 100644 --- a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff +++ b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff @@ -9,6 +9,7 @@ let mut _4: *const &u8; scope 1 (inlined generic_cast::<&u8, &u8>) { let mut _5: *const &u8; + let mut _6: *const &u8; } bb0: { @@ -17,9 +18,12 @@ StorageLive(_4); _4 = copy _1; StorageLive(_5); - _5 = copy _4; -- _3 = move _5 as *const &u8 (PtrToPtr); -+ _3 = move _5; + StorageLive(_6); + _6 = copy _4; +- _5 = move _6 as *const &u8 (PtrToPtr); ++ _5 = move _6; + _3 = copy _5; + StorageDead(_6); StorageDead(_5); StorageDead(_4); - _2 = move _3 as *const &u8 (PtrToPtr); diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index 6fb1637a6e02..8444157a1550 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> let _8: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::) { - let _9: *mut u32; + let mut _9: *mut u32; scope 7 { let _10: *mut u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index 6fb1637a6e02..8444157a1550 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -15,7 +15,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> let _8: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::) { - let _9: *mut u32; + let mut _9: *mut u32; scope 7 { let _10: *mut u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir index 2df2c4b85b8f..54be39b4293f 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir @@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range) -> &[u32] { let mut _6: usize; } scope 4 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _10: *const u32; + let mut _10: *const u32; scope 5 { let _11: *const u32; scope 6 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir index d4b86b9633ac..b258603a3d0d 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir @@ -19,7 +19,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range) -> &[u32] { let mut _6: usize; } scope 4 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _10: *const u32; + let mut _10: *const u32; scope 5 { let _11: *const u32; scope 6 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir index ad1ca5dff43a..7e9d9d24d619 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir @@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - let _7: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _8: *const u32; + let mut _8: *const u32; scope 7 { let _9: *const u32; scope 8 { diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir index ad1ca5dff43a..7e9d9d24d619 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir @@ -13,7 +13,7 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range) - let _7: usize; scope 3 { scope 6 (inlined core::slice::index::get_offset_len_noubcheck::) { - let _8: *const u32; + let mut _8: *const u32; scope 7 { let _9: *const u32; scope 8 { diff --git a/tests/ui/consts/issue-102117.stderr b/tests/ui/consts/issue-102117.stderr index cea355d01d7b..4440680bd7f1 100644 --- a/tests/ui/consts/issue-102117.stderr +++ b/tests/ui/consts/issue-102117.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:17:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds @@ -16,7 +16,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-102117.rs:17:26 | LL | type_id: TypeId::of::(), - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr index 395dd068e237..90d9eb3922e0 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr @@ -2,15 +2,10 @@ error[E0308]: mismatched types --> $DIR/candidate-from-env-universe-err-project.rs:38:5 | LL | projection_bound::(); - | ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | = note: expected associated type `>::Assoc` found associated type `>::Assoc` -note: the lifetime requirement is introduced here - --> $DIR/candidate-from-env-universe-err-project.rs:19:42 - | -LL | fn projection_bound Trait<'a, Assoc = usize>>() {} - | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/candidate-from-env-universe-err-project.rs:52:30 diff --git a/tests/ui/nll/issue-98693.stderr b/tests/ui/nll/issue-98693.stderr index b5e281538f9c..cf69fbd5aeed 100644 --- a/tests/ui/nll/issue-98693.stderr +++ b/tests/ui/nll/issue-98693.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/issue-98693.rs:16:9 | LL | assert_static::(); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | | | the parameter type `T` must be valid for the static lifetime... | ...so that the type `T` will meet its required lifetime bounds diff --git a/tests/ui/nll/type-test-universe.stderr b/tests/ui/nll/type-test-universe.stderr index 54b48c1597bd..c9dcb69f08f5 100644 --- a/tests/ui/nll/type-test-universe.stderr +++ b/tests/ui/nll/type-test-universe.stderr @@ -2,7 +2,7 @@ error: `S` does not live long enough --> $DIR/type-test-universe.rs:11:5 | LL | outlives_forall::(); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/type-test-universe.rs:17:5 diff --git a/tests/ui/regions/forall-wf-ref-reflexive.stderr b/tests/ui/regions/forall-wf-ref-reflexive.stderr index 5ee7cc7866c9..71debe7c297b 100644 --- a/tests/ui/regions/forall-wf-ref-reflexive.stderr +++ b/tests/ui/regions/forall-wf-ref-reflexive.stderr @@ -2,7 +2,7 @@ error: `T` does not live long enough --> $DIR/forall-wf-ref-reflexive.rs:12:5 | LL | self_wf2::(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs b/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs new file mode 100644 index 000000000000..b19f96357ad6 --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-issue-115175.rs @@ -0,0 +1,11 @@ +// A regression test for https://github.com/rust-lang/rust/issues/115175. +// This used to compile without error despite of unsatisfied outlives bound `T: 'static` on local. + +struct Static(T); + +fn test() { + let _ = None::>; + //~^ ERROR the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr b/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr new file mode 100644 index 000000000000..1a1b142b9d1d --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-issue-115175.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-bound-region-in-local-issue-115175.rs:7:13 + | +LL | let _ = None::>; + | ^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test() { + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs new file mode 100644 index 000000000000..b21669cf7842 --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.rs @@ -0,0 +1,51 @@ +// A regression test for https://github.com/rust-lang/rust/issues/148854. + +use std::cell::OnceCell; +use std::fmt::Display; +use std::marker::PhantomData; +use std::rc::Rc; + +type Storage = Rc>>; + +trait IntoDyn { + fn into_dyn(input: T, output: Storage); +} + +struct Inner(PhantomData); +impl IntoDyn for Inner { + fn into_dyn(input: T, output: Storage) { + output.set(Box::new(input)).ok().unwrap(); + } +} + +struct Outer> { + input: Option, + output: Storage, + _phantom: PhantomData, +} +impl> Drop for Outer { + fn drop(&mut self) { + U::into_dyn(self.input.take().unwrap(), self.output.clone()); + } +} + +fn extend(x: T) -> Box { + let storage = Rc::new(OnceCell::new()); + { + // This has to error due to an unsatisfied outlives bound on + // `Inner` as its implicit drop relies on that + // bound. + let _ = + Outer::> { input: Some(x), output: storage.clone(), _phantom: PhantomData }; + //~^ ERROR: the parameter type `T` may not live long enough + } + Rc::into_inner(storage).unwrap().into_inner().unwrap() +} + +fn main() { + let wrong = { + let data = String::from("abc"); + extend::<&String>(&data) + }; + println!("{wrong}"); +} diff --git a/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr new file mode 100644 index 000000000000..d79daaf2a6ad --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-local-soundness-issue-148854.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-bound-region-in-local-soundness-issue-148854.rs:39:13 + | +LL | Outer::> { input: Some(x), output: storage.clone(), _phantom: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn extend(x: T) -> Box { + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr index 7311f5882f75..bbc0b91cd503 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -28,7 +28,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check3.rs:55:5 | LL | test_type_param::assert_static::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | the parameter type `A` must be valid for the static lifetime... | ...so that the type `A` will meet its required lifetime bounds diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index 3cec4bbb0993..710e4a5ce9e8 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -21,7 +21,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/implied_lifetime_wf_check4_static.rs:15:5 | LL | assert_static::() - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | | | the parameter type `A` must be valid for the static lifetime... | ...so that the type `A` will meet its required lifetime bounds From 6a3baf6f2764e404f282119165b78ef68436edcc Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 12 Feb 2026 13:48:12 +0100 Subject: [PATCH 123/182] CI: rfl: add temporary commit for compiler bug The compiler is fixing a bug [1] that Rust for Linux happened to trigger, thus temporarily add Benno's patch to the CI job. As usual, the patch will eventually make it to the Linux kernel so that both sides are good. Cc: Benno Lossin Link: https://github.com/rust-lang/rust/pull/149389 [1] Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 535250557740..0af0328c5f2f 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -3,7 +3,8 @@ set -euo pipefail # https://github.com/rust-lang/rust/pull/151534 -LINUX_VERSION=eb268c7972f65fa0b11b051c5ef2b92747bb2b62 +# 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 From eaad11cc2c83692b47d624587717242fdb19a75e Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 12 Feb 2026 16:55:36 +0100 Subject: [PATCH 124/182] cg_gcc: remove Clippy expect attribute --- compiler/rustc_codegen_gcc/src/declare.rs | 1 - 1 file changed, 1 deletion(-) 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, From e098327271327f86fb6aac22e64136f4a3268d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 10 Feb 2026 15:10:04 +0100 Subject: [PATCH 125/182] Don't ICE on layout error in vtable computation --- compiler/rustc_middle/src/ty/vtable.rs | 7 ++++--- .../vtable-try-as-dyn.full-debuginfo.stderr | 4 ++++ .../limits/vtable-try-as-dyn.no-debuginfo.stderr | 4 ++++ tests/ui/limits/vtable-try-as-dyn.rs | 15 +++++++++++++++ tests/ui/limits/vtable.rs | 8 ++++++++ tests/ui/limits/vtable.stderr | 4 ++++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr create mode 100644 tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr create mode 100644 tests/ui/limits/vtable-try-as-dyn.rs create mode 100644 tests/ui/limits/vtable.rs create mode 100644 tests/ui/limits/vtable.stderr 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/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr b/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr new file mode 100644 index 000000000000..a3772e509ed6 --- /dev/null +++ b/tests/ui/limits/vtable-try-as-dyn.full-debuginfo.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the target architecture + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr b/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr new file mode 100644 index 000000000000..a3772e509ed6 --- /dev/null +++ b/tests/ui/limits/vtable-try-as-dyn.no-debuginfo.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the target architecture + +error: aborting due to 1 previous error + diff --git a/tests/ui/limits/vtable-try-as-dyn.rs b/tests/ui/limits/vtable-try-as-dyn.rs new file mode 100644 index 000000000000..4df4f92717f9 --- /dev/null +++ b/tests/ui/limits/vtable-try-as-dyn.rs @@ -0,0 +1,15 @@ +// At the time of writing, vtable.rs would ICE only with debuginfo disabled, while this testcase, +// originally reported as #152030, would ICE even with debuginfo enabled. +//@ revisions: no-debuginfo full-debuginfo +//@ compile-flags: --crate-type=lib --emit=mir +//@[no-debuginfo] compile-flags: -C debuginfo=0 +//@[full-debuginfo] compile-flags: -C debuginfo=2 +#![feature(try_as_dyn)] + +trait Trait {} +impl Trait for T {} + +//~? ERROR: values of the type `[u8; usize::MAX]` are too big for the target architecture +pub fn foo(x: &[u8; usize::MAX]) { + let _ = std::any::try_as_dyn::<[u8; usize::MAX], dyn Trait>(x); +} diff --git a/tests/ui/limits/vtable.rs b/tests/ui/limits/vtable.rs new file mode 100644 index 000000000000..570eaaec491c --- /dev/null +++ b/tests/ui/limits/vtable.rs @@ -0,0 +1,8 @@ +//@ compile-flags: --crate-type=lib --emit=mir -C debuginfo=0 +pub trait Trait {} +impl Trait for T {} + +//~? ERROR: values of the type `[u8; usize::MAX]` are too big for the target architecture +pub fn foo(x: &[u8; usize::MAX]) -> &dyn Trait { + x as &dyn Trait +} diff --git a/tests/ui/limits/vtable.stderr b/tests/ui/limits/vtable.stderr new file mode 100644 index 000000000000..a3772e509ed6 --- /dev/null +++ b/tests/ui/limits/vtable.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the target architecture + +error: aborting due to 1 previous error + From 42a3c864d2fd42903419d2e927b173f3d6da425b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 12 Feb 2026 21:40:10 +0100 Subject: [PATCH 126/182] Remove `deprecated_safe` and its corresponding feature gate --- compiler/rustc_feature/src/builtin_attrs.rs | 7 ------ compiler/rustc_feature/src/removed.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_passes/src/check_attr.rs | 2 -- .../feature-gate-deprecated_safe.rs | 7 ------ .../feature-gate-deprecated_safe.stderr | 23 ------------------- 6 files changed, 2 insertions(+), 41 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-deprecated_safe.rs delete mode 100644 tests/ui/feature-gates/feature-gate-deprecated_safe.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d74e8442545b..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, 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 add09c3ea58b..082558cf9a93 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -454,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. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b6f0e9fedd6d..c559e799f1c5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -391,8 +391,6 @@ 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 diff --git a/tests/ui/feature-gates/feature-gate-deprecated_safe.rs b/tests/ui/feature-gates/feature-gate-deprecated_safe.rs deleted file mode 100644 index d5f4a4705b97..000000000000 --- a/tests/ui/feature-gates/feature-gate-deprecated_safe.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature -unsafe fn deprecated_safe_fn() {} - -#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature -unsafe trait DeprecatedSafeTrait {} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr b/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr deleted file mode 100644 index 415d54463d1a..000000000000 --- a/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature - --> $DIR/feature-gate-deprecated_safe.rs:1:1 - | -LL | #[deprecated_safe(since = "TBD", note = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #94978 for more information - = help: add `#![feature(deprecated_safe)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature - --> $DIR/feature-gate-deprecated_safe.rs:4:1 - | -LL | #[deprecated_safe(since = "TBD", note = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #94978 for more information - = help: add `#![feature(deprecated_safe)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. From be8287730e44993b5f9880b5735f6a34f57ad5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20Kenan=20G=C3=BCng=C3=B6r?= Date: Fri, 13 Feb 2026 00:34:43 +0300 Subject: [PATCH 127/182] doc: move riscv64a23-unknown-linux-gnu to tier 2 --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 158539b47f30..a8b2111a901e 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -189,6 +189,7 @@ target | std | notes [`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA) [`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA) [`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) +[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39) [`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | ✓ |RISC-V Linux (kernel 4.20+, musl 1.2.5) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) [`riscv64im-unknown-none-elf`](platform-support/riscv64im-unknown-none-elf.md) | * | Bare RISC-V (RV64IM ISA) @@ -406,7 +407,6 @@ target | std | host | notes [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 [`riscv64gc-unknown-redox`](platform-support/redox.md) | ✓ | | RISC-V 64bit Redox OS [`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX -[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39) [`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.5) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ From a07f837491a3bca6218620f527b0a9f0c5e07291 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sat, 7 Feb 2026 17:49:08 +0800 Subject: [PATCH 128/182] Remove unused features in compiler --- compiler/rustc_abi/src/lib.rs | 2 +- compiler/rustc_codegen_cranelift/src/lib.rs | 4 ++-- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 -- compiler/rustc_index/src/lib.rs | 3 ++- compiler/rustc_macros/src/lib.rs | 1 - compiler/rustc_metadata/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 3 +-- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_passes/src/lib.rs | 5 ----- compiler/rustc_pattern_analysis/src/lib.rs | 1 - compiler/rustc_public_bridge/src/lib.rs | 1 - compiler/rustc_resolve/src/lib.rs | 1 - compiler/rustc_serialize/src/lib.rs | 1 - compiler/rustc_type_ir/src/lib.rs | 5 +---- 15 files changed, 9 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 85f31b75e240..88f8b7cc5170 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,5 +1,5 @@ // tidy-alphabetical-start -#![cfg_attr(all(feature = "nightly", bootstrap), feature(assert_matches))] +#![cfg_attr(all(feature = "nightly", bootstrap, test), feature(assert_matches))] #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", feature(step_trait))] diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index a49dc9be3458..bbf7d1b6998e 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)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index a56b5f5fdc7d..594d6d294d75 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -12,6 +12,7 @@ #![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)] @@ -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)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index cfd4ae3795e1..a17e08e9b031 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -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; 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_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 8cd6c0264448..88c622dd2aec 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)] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 22c8a0c4cd7e..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)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 2095327ea1b5..f0c85fec4ea6 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,6 +28,7 @@ #![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(associated_type_defaults)] #![feature(box_as_ptr)] @@ -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)] @@ -56,7 +56,6 @@ #![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 diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 014ccdc45ef8..31506ae38fa0 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -2,12 +2,12 @@ // tidy-alphabetical-start #![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 diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index ef6a8e80c72f..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; diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 9ffc237c6329..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; 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_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1399f9933ad4..fc863c84f099 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -15,7 +15,6 @@ #![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)] 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_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; From 0dc1556968da4d3db7e1196e77669a8c52c84609 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Thu, 12 Feb 2026 10:35:12 +0800 Subject: [PATCH 129/182] Remove unused features in library --- library/alloc/src/boxed.rs | 8 ++++---- library/alloc/src/lib.rs | 7 +------ library/alloc/src/vec/mod.rs | 6 +++--- library/core/src/lib.rs | 20 +------------------- library/panic_unwind/src/lib.rs | 2 +- library/test/src/lib.rs | 2 +- library/unwind/src/lib.rs | 2 +- 7 files changed, 12 insertions(+), 35 deletions(-) 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/lib.rs b/library/alloc/src/lib.rs index 0e0c2fcd8b99..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,13 +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(async_fn_traits)] #![feature(async_iterator)] -#![feature(box_vec_non_null)] #![feature(bstr)] #![feature(bstr_internals)] #![feature(cast_maybe_uninit)] @@ -148,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)] @@ -158,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)] @@ -176,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/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6cbe89d9da4f..11a498d09d3f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1238,7 +1238,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// @@ -1265,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}; /// @@ -1365,7 +1365,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(allocator_api, box_vec_non_null)] + /// #![feature(allocator_api)] /// /// use std::alloc::System; /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index aaa919ece6a5..dfa1236c2a2c 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,9 +96,7 @@ // // Library features: // tidy-alphabetical-start -#![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(bstr)] #![feature(bstr_internals)] #![feature(cfg_select)] #![feature(cfg_target_has_reliable_f16_f128)] @@ -106,31 +105,15 @@ #![feature(const_destruct)] #![feature(const_eval_select)] #![feature(const_select_unpredictable)] -#![feature(const_unsigned_bigint_helpers)] #![feature(core_intrinsics)] #![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(signed_bigint_helpers)] -#![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)] -#![feature(widening_mul)] // tidy-alphabetical-end // // Language features: @@ -175,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)] 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/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. From a318a207f0a744da50a1c52e50ae87c26dc19c40 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Thu, 12 Feb 2026 10:37:23 +0800 Subject: [PATCH 130/182] Remove unused features in librustdoc --- src/librustdoc/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7d878e7df529..4b03a5ea00ff 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -6,12 +6,10 @@ )] #![feature(ascii_char)] #![feature(ascii_char_variants)] -#![feature(box_into_inner)] #![feature(box_patterns)] #![feature(file_buffered)] #![feature(formatting_options)] #![feature(if_let_guard)] -#![feature(iter_advance_by)] #![feature(iter_intersperse)] #![feature(iter_order_by)] #![feature(rustc_private)] From 73c42c18005a2f788ae99a8d5d7dad900404e93b Mon Sep 17 00:00:00 2001 From: mu001999 Date: Thu, 12 Feb 2026 11:43:22 +0800 Subject: [PATCH 131/182] Remove or allow unused features in library doc and tests --- library/alloctests/lib.rs | 5 ----- library/alloctests/tests/lib.rs | 3 --- library/core/src/ascii/ascii_char.rs | 2 +- library/core/src/cell.rs | 1 - library/core/src/convert/num.rs | 2 ++ library/core/src/num/f128.rs | 11 +++++++++-- library/core/src/num/f16.rs | 5 ++++- library/core/src/num/f32.rs | 1 + library/core/src/num/f64.rs | 1 + library/core/src/num/uint_macros.rs | 3 ++- library/core/src/ptr/alignment.rs | 1 - library/core/src/ptr/mut_ptr.rs | 1 - library/core/src/time.rs | 2 -- library/coretests/tests/lib.rs | 6 ------ library/std/src/num/f128.rs | 1 + library/std/src/num/f16.rs | 4 ---- library/std/tests/floats/lib.rs | 2 +- library/std/tests/volatile-fat-ptr.rs | 1 - library/std_detect/tests/cpu-detection.rs | 2 +- library/std_detect/tests/macro_trailing_commas.rs | 2 +- 20 files changed, 24 insertions(+), 32 deletions(-) diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 296f76d7c073..e09d8495fdea 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -16,7 +16,6 @@ // tidy-alphabetical-start #![feature(allocator_api)] #![feature(array_into_iter_constructors)] -#![feature(box_vec_non_null)] #![feature(char_internals)] #![feature(const_alloc_error)] #![feature(const_cmp)] @@ -55,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/lib.rs b/library/alloctests/tests/lib.rs index b7b8336ee429..699a5010282b 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -3,7 +3,6 @@ #![feature(const_heap)] #![feature(deque_extend_front)] #![feature(iter_array_chunks)] -#![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/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/cell.rs b/library/core/src/cell.rs index a9e7c49515c7..28c3db698536 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -774,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 6e82e3356410..03650615e25a 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -219,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"))] { /// @@ -230,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"))] { /// diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 140b955259ab..d114b821655b 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -148,7 +148,10 @@ 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")] @@ -1470,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 463f07da91b2..373225c5806c 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -142,7 +142,10 @@ 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")] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index be908cb3894b..f3c7961931a1 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1821,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 73b20a50ff8e..a6fd3b1cb5d0 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1819,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/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5c263ea845cc..8475cc71a7e0 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3072,7 +3072,6 @@ macro_rules! uint_impl { /// implementing it for wider-than-native types. /// /// ``` - /// #![feature(const_unsigned_bigint_helpers)] /// fn scalar_mul_eq(little_endian_digits: &mut Vec, multiplicand: u16) { /// let mut carry = 0; /// for d in little_endian_digits.iter_mut() { @@ -3097,6 +3096,7 @@ macro_rules! uint_impl { /// except that it gives the value of the overflow instead of just whether one happened: /// /// ``` + /// # #![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)); @@ -3109,6 +3109,7 @@ macro_rules! uint_impl { /// [`wrapping_add`](Self::wrapping_add) methods: /// /// ``` + /// # #![allow(unused_features)] /// #![feature(const_unsigned_bigint_helpers)] /// assert_eq!( /// 789_u16.carrying_mul(456, 123).0, diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index b27930de4e66..b106314f14d1 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -112,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); diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 02e12d56fa65..f19a5d02b98d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1800,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/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/lib.rs b/library/coretests/tests/lib.rs index 592332865552..3a30b6b7edcc 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -13,7 +13,6 @@ #![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)] @@ -35,7 +34,6 @@ #![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)] @@ -47,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)] @@ -55,7 +52,6 @@ #![feature(f16)] #![feature(f128)] #![feature(float_algebraic)] -#![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(flt2dec)] #![feature(fmt_internals)] @@ -94,7 +90,6 @@ #![feature(nonzero_from_str_radix)] #![feature(numfmt)] #![feature(one_sided_range)] -#![feature(option_reduce)] #![feature(pattern)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] @@ -114,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)] 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/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/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_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", From 7d7b3816607c3f0c5afd4562bb3efca8b6eea777 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 8 Feb 2026 16:42:28 +0900 Subject: [PATCH 132/182] Fix ICE in borrowck when recovering `fn_sig` for `-> _` --- compiler/rustc_hir_analysis/src/collect.rs | 56 ++++++++++++++++++- tests/crashes/135845.rs | 6 -- .../recover-infer-ret-ty-issue-135845.rs | 11 ++++ .../recover-infer-ret-ty-issue-135845.stderr | 15 +++++ 4 files changed, 80 insertions(+), 8 deletions(-) delete mode 100644 tests/crashes/135845.rs create mode 100644 tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs create mode 100644 tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 03bbc9c0a7c9..29a2e7e36220 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1138,13 +1138,65 @@ 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, - )) + ); + + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() { + ty::ReLateParam(lp) if lp.scope == scope => { + let br = match lp.kind { + ty::LateParamRegionKind::Anon(idx) | ty::LateParamRegionKind::NamedAnon(idx, _) => { + let idx = idx as usize; + match bound_vars.get(idx).copied() { + Some(ty::BoundVariableKind::Region(br_kind)) => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + } + } + ty::LateParamRegionKind::Named(def_id) => { + bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region( + br_kind @ ty::BoundRegionKind::Named(did), + ) if did == def_id => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + }) + } + ty::LateParamRegionKind::ClosureEnv => { + bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { + ty::BoundVariableKind::Region( + br_kind @ ty::BoundRegionKind::ClosureEnv, + ) => Some(ty::BoundRegion { + var: ty::BoundVar::from_usize(idx), + kind: br_kind, + }), + _ => None, + }) + } + }; + + br.map(|br| ty::Region::new_bound(tcx, ty::INNERMOST, br)) + .unwrap_or_else(|| ty::Region::new_error(tcx, guar)) + } + _ => r, + }); + + ty::Binder::bind_with_vars(fn_sig, bound_vars) } pub fn suggest_impl_trait<'tcx>( diff --git a/tests/crashes/135845.rs b/tests/crashes/135845.rs deleted file mode 100644 index ed038d8a1f18..000000000000 --- a/tests/crashes/135845.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #135845 -struct S<'a, T: ?Sized>(&'a T); - -fn b<'a>() -> S<'static, _> { - S::<'a>(&0) -} diff --git a/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs new file mode 100644 index 000000000000..acce49b1af72 --- /dev/null +++ b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.rs @@ -0,0 +1,11 @@ +// Regression test for #135845. + +use std::marker::PhantomData; + +fn b<'a>() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + let _: PhantomData<&'a ()> = PhantomData; + 0 +} + +fn main() {} diff --git a/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr new file mode 100644 index 000000000000..9f3695e88f82 --- /dev/null +++ b/tests/ui/lifetimes/recover-infer-ret-ty-issue-135845.stderr @@ -0,0 +1,15 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/recover-infer-ret-ty-issue-135845.rs:5:15 + | +LL | fn b<'a>() -> _ { + | ^ not allowed in type signatures + | +help: replace with the correct return type + | +LL - fn b<'a>() -> _ { +LL + fn b<'a>() -> i32 { + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0121`. From 45bc47e4e26f29450dd679c3adac249eae28d220 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 12 Feb 2026 20:16:33 +0900 Subject: [PATCH 133/182] Apply review suggestions --- compiler/rustc_hir_analysis/src/collect.rs | 106 +++++++++++++-------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 29a2e7e36220..1cd96cf6a54d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1063,6 +1063,69 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( ) } +/// Convert `ReLateParam`s in `value` back into `ReBound`s so the returned +/// `PolyFnSig` properly binds all late-bound vars. +fn late_param_regions_to_bound<'tcx, T>( + tcx: TyCtxt<'tcx>, + scope: DefId, + bound_vars: &'tcx ty::List>, + value: T, +) -> T +where + T: ty::TypeFoldable>, +{ + 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, + }) +} + fn recover_infer_ret_ty<'tcx>( icx: &ItemCtxt<'tcx>, infer_ret_ty: &'tcx hir::Ty<'tcx>, @@ -1153,48 +1216,7 @@ fn recover_infer_ret_ty<'tcx>( fn_sig.abi, ); - let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() { - ty::ReLateParam(lp) if lp.scope == scope => { - let br = match lp.kind { - ty::LateParamRegionKind::Anon(idx) | ty::LateParamRegionKind::NamedAnon(idx, _) => { - let idx = idx as usize; - match bound_vars.get(idx).copied() { - Some(ty::BoundVariableKind::Region(br_kind)) => Some(ty::BoundRegion { - var: ty::BoundVar::from_usize(idx), - kind: br_kind, - }), - _ => None, - } - } - ty::LateParamRegionKind::Named(def_id) => { - bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { - ty::BoundVariableKind::Region( - br_kind @ ty::BoundRegionKind::Named(did), - ) if did == def_id => Some(ty::BoundRegion { - var: ty::BoundVar::from_usize(idx), - kind: br_kind, - }), - _ => None, - }) - } - ty::LateParamRegionKind::ClosureEnv => { - bound_vars.iter().enumerate().find_map(|(idx, bv)| match bv { - ty::BoundVariableKind::Region( - br_kind @ ty::BoundRegionKind::ClosureEnv, - ) => Some(ty::BoundRegion { - var: ty::BoundVar::from_usize(idx), - kind: br_kind, - }), - _ => None, - }) - } - }; - - br.map(|br| ty::Region::new_bound(tcx, ty::INNERMOST, br)) - .unwrap_or_else(|| ty::Region::new_error(tcx, guar)) - } - _ => r, - }); + let fn_sig = late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig); ty::Binder::bind_with_vars(fn_sig, bound_vars) } From 20c46d647f1bc60592fa008cc2b18f26f567f0ae Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sat, 31 Jan 2026 16:20:09 +0800 Subject: [PATCH 134/182] report unconstrained region in hidden types lazily --- .../src/region_infer/opaque_types/mod.rs | 100 ++++++++++++++++-- compiler/rustc_borrowck/src/root_cx.rs | 20 +++- .../opaques/eventually-constrained-region.rs | 21 ++++ .../report-all-unexpected-hidden-errors.rs | 34 ++++++ ...report-all-unexpected-hidden-errors.stderr | 36 +++++++ 5 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 tests/ui/traits/next-solver/opaques/eventually-constrained-region.rs create mode 100644 tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.rs create mode 100644 tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.stderr 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/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/tests/ui/traits/next-solver/opaques/eventually-constrained-region.rs b/tests/ui/traits/next-solver/opaques/eventually-constrained-region.rs new file mode 100644 index 000000000000..997bcd6ed9b4 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/eventually-constrained-region.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for trait-system-refactor-initiative#264. +// +// Some defining uses of opaque types can't constrain captured regions to universals. +// Previouly, we eagerly report error in this case. +// Now we report error only if there's no fully defining use from all bodies of the typeck root. + +struct Inv<'a>(*mut &'a ()); + +fn mk_static() -> Inv<'static> { todo!() } + +fn guide_closure_sig<'a>(f: impl FnOnce() -> Inv<'a>) {} + +fn unconstrained_in_closure() -> impl Sized { + guide_closure_sig(|| unconstrained_in_closure()); + mk_static() +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.rs b/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.rs new file mode 100644 index 000000000000..61823c1e300d --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.rs @@ -0,0 +1,34 @@ +//@ compile-flags: -Znext-solver + +// Just for diagnostics completeness. +// This is probably unimportant as we only report one error for such case in HIR typeck. + +#![feature(type_alias_impl_trait)] + +struct Invar<'a>(*mut &'a ()); + +fn mk_invar<'a>(a: &'a i32) -> Invar<'a> { + todo!() +} + +type MultiUse = impl Sized; + +#[define_opaque(MultiUse)] +fn capture_different_universals_not_on_bounds<'a, 'b, 'c>(a: &'a i32, b: &'b i32, c: &'c i32) { + let _ = || -> MultiUse { + //~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700] + mk_invar(a) + }; + let _ = || -> MultiUse { + //~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700] + mk_invar(b) + }; + let _ = || { + let _ = || -> MultiUse { + //~^ ERROR: hidden type for `MultiUse` captures lifetime that does not appear in bounds [E0700] + mk_invar(c) + }; + }; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.stderr b/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.stderr new file mode 100644 index 000000000000..28d9da3d4666 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/report-all-unexpected-hidden-errors.stderr @@ -0,0 +1,36 @@ +error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds + --> $DIR/report-all-unexpected-hidden-errors.rs:18:19 + | +LL | type MultiUse = impl Sized; + | ---------- opaque type defined here +... +LL | let _ = || -> MultiUse { + | ^^^^^^^^ + | + = note: hidden type `Invar<'_>` captures lifetime `'_` + +error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds + --> $DIR/report-all-unexpected-hidden-errors.rs:22:19 + | +LL | type MultiUse = impl Sized; + | ---------- opaque type defined here +... +LL | let _ = || -> MultiUse { + | ^^^^^^^^ + | + = note: hidden type `Invar<'_>` captures lifetime `'_` + +error[E0700]: hidden type for `MultiUse` captures lifetime that does not appear in bounds + --> $DIR/report-all-unexpected-hidden-errors.rs:27:23 + | +LL | type MultiUse = impl Sized; + | ---------- opaque type defined here +... +LL | let _ = || -> MultiUse { + | ^^^^^^^^ + | + = note: hidden type `Invar<'_>` captures lifetime `'_` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0700`. From b0f2ac8797078dd7a2da924969b57ada41794f7e Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 13 Feb 2026 14:06:30 +0900 Subject: [PATCH 135/182] Return Binder --- compiler/rustc_hir_analysis/src/collect.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1cd96cf6a54d..2fc1f1ab01d2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1063,18 +1063,17 @@ fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( ) } -/// Convert `ReLateParam`s in `value` back into `ReBound`s so the returned -/// `PolyFnSig` properly binds all late-bound vars. +/// 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, -) -> T +) -> ty::Binder<'tcx, T> where T: ty::TypeFoldable>, { - fold_regions(tcx, value, |r, debruijn| match r.kind() { + 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); @@ -1123,7 +1122,9 @@ where ty::Region::new_bound(tcx, debruijn, br) } _ => r, - }) + }); + + ty::Binder::bind_with_vars(value, bound_vars) } fn recover_infer_ret_ty<'tcx>( @@ -1216,9 +1217,7 @@ fn recover_infer_ret_ty<'tcx>( fn_sig.abi, ); - let fn_sig = late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig); - - ty::Binder::bind_with_vars(fn_sig, bound_vars) + late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig) } pub fn suggest_impl_trait<'tcx>( From 4c10efb939ee78bb10a2b8833746c554478d64f9 Mon Sep 17 00:00:00 2001 From: Asuna Date: Fri, 13 Feb 2026 07:55:58 +0100 Subject: [PATCH 136/182] Replace "bug" with "issue" in triagebot ping messages --- triagebot.toml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 2a98b1d43b99..bc90371393b6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -76,9 +76,9 @@ add-labels = ["beta-nominated"] [ping.windows] message = """\ -Hey Windows Group! This bug has been identified as a good "Windows candidate". +Hey Windows Group! This issue has been identified as a good "Windows candidate". In case it's useful, here are some [instructions] for tackling these sorts of -bugs. Maybe take a look? +issues. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/windows.html @@ -87,9 +87,9 @@ label = "O-windows" [ping.arm] message = """\ -Hey ARM Group! This bug has been identified as a good "ARM candidate". +Hey ARM Group! This issue has been identified as a good "ARM candidate". In case it's useful, here are some [instructions] for tackling these sorts of -bugs. Maybe take a look? +issues. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/arm.html @@ -98,9 +98,9 @@ label = "O-ARM" [ping.loongarch] message = """\ -Hey LoongArch Group! This bug has been identified as a good "LoongArch candidate". +Hey LoongArch Group! This issue has been identified as a good "LoongArch candidate". In case it's useful, here are some [instructions] for tackling these sorts of -bugs. Maybe take a look? +issues. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/loongarch.html @@ -109,9 +109,9 @@ label = "O-loongarch" [ping.risc-v] message = """\ -Hey RISC-V Group! This bug has been identified as a good "RISC-V candidate". +Hey RISC-V Group! This issue has been identified as a good "RISC-V candidate". In case it's useful, here are some [instructions] for tackling these sorts of -bugs. Maybe take a look? +issues. Maybe take a look? Thanks! <3 [instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/risc-v.html From a8d7a47927077001e8cdab0e4974d582b68b176e Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Feb 2026 17:04:59 +0900 Subject: [PATCH 137/182] improve associated-type suggestions from bounds --- compiler/rustc_resolve/src/late.rs | 33 +++ .../rustc_resolve/src/late/diagnostics.rs | 236 +++++++++++++++++- compiler/rustc_resolve/src/lib.rs | 28 +++ .../associated-types-eq-1.stderr | 9 +- .../suggest-assoc-type-from-bounds.rs | 43 ++++ .../suggest-assoc-type-from-bounds.stderr | 58 +++++ ...swap-equality-in-macro-issue-139050.stderr | 7 +- 7 files changed, 405 insertions(+), 9 deletions(-) create mode 100644 tests/ui/associated-types/suggest-assoc-type-from-bounds.rs create mode 100644 tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fe6346f6c6e9..504dacd958ec 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5442,6 +5442,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 { @@ -5500,6 +5526,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 95f0d3e67ef2..06acba4749dd 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, @@ -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; @@ -169,6 +186,213 @@ 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, + } + }) + } + + fn assoc_type_required_generic_args_suggestion(&self, assoc_type_def_id: DefId) -> String { + self.r.item_required_generic_args_suggestion(assoc_type_def_id) + } + + /// 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(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.assoc_type_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.assoc_type_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(); + + match suggestions.as_slice() { + [one] => { + err.span_suggestion_verbose( + ident_span, + "use the associated type", + one, + Applicability::MaybeIncorrect, + ); + } + _ => { + err.span_suggestions( + ident_span, + "use an associated type", + suggestions, + Applicability::MaybeIncorrect, + ); + } + }; + + true + } + fn make_base_error( &mut self, path: &[Segment], @@ -1038,6 +1262,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; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1399f9933ad4..3a3ce879234a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1338,6 +1338,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(), @@ -1556,6 +1558,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 } diff --git a/tests/ui/associated-types/associated-types-eq-1.stderr b/tests/ui/associated-types/associated-types-eq-1.stderr index 869583df644f..53ad1aefe5d3 100644 --- a/tests/ui/associated-types/associated-types-eq-1.stderr +++ b/tests/ui/associated-types/associated-types-eq-1.stderr @@ -1,16 +1,13 @@ error[E0425]: cannot find type `A` in this scope --> $DIR/associated-types-eq-1.rs:10:12 | -LL | fn foo2(x: I) { - | - similarly named type parameter `I` defined here LL | let _: A = x.boo(); | ^ | -help: a type parameter with a similar name exists - | -LL - let _: A = x.boo(); -LL + let _: I = x.boo(); +help: use the associated type | +LL | let _: I::A = x.boo(); + | +++ help: you might be missing a type parameter | LL | fn foo2(x: I) { diff --git a/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs b/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs new file mode 100644 index 000000000000..0eb56ad96e36 --- /dev/null +++ b/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs @@ -0,0 +1,43 @@ +pub trait Trait { + type Assoc; +} + +fn f + Trait>() { + let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope +} + +pub trait Foo<'a> { + type A; +} + +pub mod inner { + pub trait Foo<'a> { + type A; + } +} + +fn g<'a, T: ::Foo<'a> + inner::Foo<'a>>() { + let _: A = todo!(); //~ ERROR cannot find type `A` in this scope +} + +pub trait First { + type Assoc; +} + +pub trait Second { + type Assoc; +} + +fn h + Second>() { + let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope +} + +pub trait Gat { + type Assoc<'a>; +} + +fn i() { + let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope +} + +fn main() {} diff --git a/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr b/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr new file mode 100644 index 000000000000..c46c89c119e1 --- /dev/null +++ b/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr @@ -0,0 +1,58 @@ +error[E0425]: cannot find type `Assoc` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:6:12 + | +LL | let _: Assoc = todo!(); + | ^^^^^ + | +help: use an associated type + | +LL | let _: >::Assoc = todo!(); + | +++++++++++++++++++ +LL | let _: >::Assoc = todo!(); + | +++++++++++++++++++ + +error[E0425]: cannot find type `A` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:20:12 + | +LL | let _: A = todo!(); + | ^ + | +help: use an associated type + | +LL | let _: >::A = todo!(); + | ++++++++++++++++++ +LL | let _: >::A = todo!(); + | +++++++++++++++++++++++ +help: you might be missing a type parameter + | +LL | fn g<'a, T: ::Foo<'a> + inner::Foo<'a>, A>() { + | +++ + +error[E0425]: cannot find type `Assoc` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:32:12 + | +LL | let _: Assoc = todo!(); + | ^^^^^ + | +help: use an associated type + | +LL | let _: ::Assoc = todo!(); + | ++++++++++++++ +LL | let _: ::Assoc = todo!(); + | +++++++++++++++ + +error[E0425]: cannot find type `Assoc` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:40:12 + | +LL | let _: Assoc = todo!(); + | ^^^^^ + | +help: use the associated type + | +LL - let _: Assoc = todo!(); +LL + let _: T::Assoc<'_> = todo!(); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr index d74372c665a4..184a5aaf0488 100644 --- a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr +++ b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr @@ -2,7 +2,12 @@ error[E0425]: cannot find type `Item` in this scope --> $DIR/sugg-swap-equality-in-macro-issue-139050.rs:29:5 | LL | Item: Eq + Debug, - | ^^^^ not found in this scope + | ^^^^ + | +help: use the associated type + | +LL | I::Item: Eq + Debug, + | +++ error[E0308]: mismatched types --> $DIR/sugg-swap-equality-in-macro-issue-139050.rs:31:5 From 391a3951580c222ba6b7a1aca0531e3d81fd9f5d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 13 Feb 2026 16:41:14 +0900 Subject: [PATCH 138/182] Improve diagnostics following reviews --- .../rustc_resolve/src/late/diagnostics.rs | 38 +++++++------------ .../associated-types-eq-1.stderr | 2 +- .../suggest-assoc-type-from-bounds.rs | 21 ++++++++++ .../suggest-assoc-type-from-bounds.stderr | 27 ++++++++++--- ...swap-equality-in-macro-issue-139050.stderr | 2 +- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 06acba4749dd..7bc8d280824f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -205,10 +205,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }) } - fn assoc_type_required_generic_args_suggestion(&self, assoc_type_def_id: DefId) -> String { - self.r.item_required_generic_args_suggestion(assoc_type_def_id) - } - /// This does best-effort work to generate suggestions for associated types. fn suggest_assoc_type_from_bounds( &mut self, @@ -323,7 +319,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { record_from_generics(self, generics); } - if let Some(assoc) = self.diag_metadata.current_impl_item { + 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, .. }) @@ -346,7 +345,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let assoc_segment = format!( "{}{}", assoc_name, - self.assoc_type_required_generic_args_suggestion(assoc_type_def_id) + self.r.item_required_generic_args_suggestion(assoc_type_def_id) ); suggestions.insert(format!("{ty_param}::{assoc_segment}")); } else { @@ -354,7 +353,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let assoc_segment = format!( "{}{}", assoc_name, - self.assoc_type_required_generic_args_suggestion(assoc_type_def_id) + self.r.item_required_generic_args_suggestion(assoc_type_def_id) ); for trait_path in trait_paths { suggestions @@ -371,24 +370,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut suggestions: Vec = suggestions.into_iter().collect(); suggestions.sort(); - match suggestions.as_slice() { - [one] => { - err.span_suggestion_verbose( - ident_span, - "use the associated type", - one, - Applicability::MaybeIncorrect, - ); - } - _ => { - err.span_suggestions( - ident_span, - "use an associated type", - suggestions, - Applicability::MaybeIncorrect, - ); - } - }; + 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 } diff --git a/tests/ui/associated-types/associated-types-eq-1.stderr b/tests/ui/associated-types/associated-types-eq-1.stderr index 53ad1aefe5d3..54e50f36fb6a 100644 --- a/tests/ui/associated-types/associated-types-eq-1.stderr +++ b/tests/ui/associated-types/associated-types-eq-1.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find type `A` in this scope LL | let _: A = x.boo(); | ^ | -help: use the associated type +help: you might have meant to use an associated type of the same name | LL | let _: I::A = x.boo(); | +++ diff --git a/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs b/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs index 0eb56ad96e36..8b349f325cd7 100644 --- a/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs +++ b/tests/ui/associated-types/suggest-assoc-type-from-bounds.rs @@ -40,4 +40,25 @@ fn i() { let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope } +fn j() { + struct Local; + impl Local { + fn method() { + let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope + } + } + + let _ = std::marker::PhantomData::; +} + +pub struct S; +impl S { + fn method() { + fn inner() { + let _: Assoc = todo!(); //~ ERROR cannot find type `Assoc` in this scope + } + inner(); + } +} + fn main() {} diff --git a/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr b/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr index c46c89c119e1..b5ce2d91ca4d 100644 --- a/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr +++ b/tests/ui/associated-types/suggest-assoc-type-from-bounds.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find type `Assoc` in this scope LL | let _: Assoc = todo!(); | ^^^^^ | -help: use an associated type +help: you might have meant to use an associated type of the same name | LL | let _: >::Assoc = todo!(); | +++++++++++++++++++ @@ -17,7 +17,7 @@ error[E0425]: cannot find type `A` in this scope LL | let _: A = todo!(); | ^ | -help: use an associated type +help: you might have meant to use an associated type of the same name | LL | let _: >::A = todo!(); | ++++++++++++++++++ @@ -34,7 +34,7 @@ error[E0425]: cannot find type `Assoc` in this scope LL | let _: Assoc = todo!(); | ^^^^^ | -help: use an associated type +help: you might have meant to use an associated type of the same name | LL | let _: ::Assoc = todo!(); | ++++++++++++++ @@ -47,12 +47,29 @@ error[E0425]: cannot find type `Assoc` in this scope LL | let _: Assoc = todo!(); | ^^^^^ | -help: use the associated type +help: you might have meant to use an associated type of the same name | LL - let _: Assoc = todo!(); LL + let _: T::Assoc<'_> = todo!(); | -error: aborting due to 4 previous errors +error[E0425]: cannot find type `Assoc` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:47:20 + | +LL | let _: Assoc = todo!(); + | ^^^^^ + | +help: you might have meant to use an associated type of the same name + | +LL | let _: U::Assoc = todo!(); + | +++ + +error[E0425]: cannot find type `Assoc` in this scope + --> $DIR/suggest-assoc-type-from-bounds.rs:58:20 + | +LL | let _: Assoc = todo!(); + | ^^^^^ not found in this scope + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr index 184a5aaf0488..c217672b0050 100644 --- a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr +++ b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find type `Item` in this scope LL | Item: Eq + Debug, | ^^^^ | -help: use the associated type +help: you might have meant to use an associated type of the same name | LL | I::Item: Eq + Debug, | +++ From cbc661022e4954731209d63d47e22762c7e73bc0 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 12 Feb 2026 22:14:49 +0100 Subject: [PATCH 139/182] Port `#[rustc_diagnostic_item]` to the new attribute parsers --- .../src/attributes/rustc_internal.rs | 39 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_expand/src/base.rs | 2 +- .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/diagnostic_items.rs | 16 +++----- compiler/rustc_resolve/src/diagnostics.rs | 12 +++--- .../rustc_resolve/src/late/diagnostics.rs | 10 ++--- 9 files changed, 61 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 0d19dc25d402..ea5501af9666 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1103,6 +1103,45 @@ impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { 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 { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 87aa4150becd..546654d0ce79 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -203,6 +203,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 91f98d475f00..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 diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 8e68a3d00233..f69ee128fce8 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1153,6 +1153,9 @@ pub enum AttributeKind { /// Represents `#[rustc_deprecated_safe_2024]` RustcDeprecatedSafe2024 { suggestion: Symbol }, + /// Represents `#[rustc_diagnostic_item]` + RustcDiagnosticItem(Symbol), + /// Represents `#[rustc_dummy]`. RustcDummy, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index e68ab1c42baf..553c29953f9b 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -112,6 +112,7 @@ impl AttributeKind { RustcDelayedBugFromInsideQuery => No, RustcDenyExplicitImpl(..) => No, RustcDeprecatedSafe2024 { .. } => Yes, + RustcDiagnosticItem(..) => Yes, RustcDummy => No, RustcDumpDefParents => No, RustcDumpItemBounds => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b6f0e9fedd6d..e7ea27a28007 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -307,6 +307,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDelayedBugFromInsideQuery | AttributeKind::RustcDenyExplicitImpl(..) | AttributeKind::RustcDeprecatedSafe2024 {..} + | AttributeKind::RustcDiagnosticItem(..) | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents | AttributeKind::RustcDumpItemBounds @@ -398,7 +399,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::panic_handler | sym::lang | sym::default_lib_allocator - | sym::rustc_diagnostic_item | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks | sym::rustc_on_unimplemented 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_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9a88f74b5b17..ac6188c2c152 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1425,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", diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 95f0d3e67ef2..ec577a1aea83 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -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}; @@ -2446,10 +2446,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; From f63007cd3b264c231c929d70175b7a7ea5ea6c5d Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Fri, 13 Feb 2026 09:54:04 +0000 Subject: [PATCH 140/182] fix missleading error for tuple ctor --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 8 +++++++- .../mgca/size-of-generic-ptr-in-array-len.rs | 3 ++- .../mgca/size-of-generic-ptr-in-array-len.stderr | 2 +- tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs | 2 +- tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) 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 1578f098dd95..cc5248718927 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2465,7 +2465,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); diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs index 22963b6438c0..d06ea7a10c74 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs @@ -4,9 +4,10 @@ fn foo() { [0; size_of::<*mut T>()]; - //~^ ERROR: tuple constructor with invalid base path + //~^ ERROR: complex const arguments must be placed inside of a `const` block [0; const { size_of::<*mut T>() }]; //~^ ERROR: generic parameters may not be used in const operations + [0; const { size_of::<*mut i32>() }]; } fn main() {} diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 6d8d3b4054d3..61e934380c36 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -1,4 +1,4 @@ -error: tuple constructor with invalid base path +error: complex const arguments must be placed inside of a `const` block --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 | LL | [0; size_of::<*mut T>()]; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index 95ee42d93d73..43d0d21fb736 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -32,7 +32,7 @@ fn test_errors() { //~| ERROR tuple constructor with invalid base path accepts_point::<{ non_ctor(N, N) }>(); - //~^ ERROR tuple constructor with invalid base path + //~^ ERROR complex const arguments must be placed inside of a `const` block accepts_point::<{ CONST_ITEM(N, N) }>(); //~^ ERROR tuple constructor with invalid base path diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index dc6a700a8e12..ce210b2b3e39 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -27,7 +27,7 @@ error: tuple constructor with invalid base path LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ -error: tuple constructor with invalid base path +error: complex const arguments must be placed inside of a `const` block --> $DIR/tuple_ctor_erroneous.rs:34:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); From a18724523c95dd00b078a9e0224ead248b29d74e Mon Sep 17 00:00:00 2001 From: Makai Date: Fri, 13 Feb 2026 17:54:34 +0800 Subject: [PATCH 141/182] nix-dev-shell: fix a typo --- src/tools/nix-dev-shell/envrc-flake | 2 +- src/tools/nix-dev-shell/envrc-shell | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake index f3e5442b86b2..2feac5ac5699 100644 --- a/src/tools/nix-dev-shell/envrc-flake +++ b/src/tools/nix-dev-shell/envrc-flake @@ -1,5 +1,5 @@ # If you want to use this as an .envrc file to create a shell with necessary components -# to develop rustc, use the following command in the root of the rusr checkout: +# to develop rustc, use the following command in the root of the rust checkout: # # ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell diff --git a/src/tools/nix-dev-shell/envrc-shell b/src/tools/nix-dev-shell/envrc-shell index 4080d7d53840..047da54c1f14 100644 --- a/src/tools/nix-dev-shell/envrc-shell +++ b/src/tools/nix-dev-shell/envrc-shell @@ -1,5 +1,5 @@ # If you want to use this as an .envrc file to create a shell with necessary components -# to develop rustc, use the following command in the root of the rusr checkout: +# to develop rustc, use the following command in the root of the rust checkout: # # ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc From 31053484a791cef24e04e8b9bb9e28366dd63e91 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 12 Feb 2026 12:14:14 +0000 Subject: [PATCH 142/182] replace `MessagePipe` trait with its impl --- compiler/rustc_expand/src/proc_macro.rs | 23 +--------- library/proc_macro/src/bridge/server.rs | 57 +++++++++++-------------- 2 files changed, 27 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index ea63ff7bfc46..530e7b998d41 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -11,29 +11,8 @@ 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( + pm::bridge::server::MaybeCrossThread::new( sess.opts.unstable_opts.proc_macro_execution_strategy == ProcMacroExecutionStrategy::CrossThread, ) diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 3ab9f40de750..b5b63ead4464 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::*; @@ -163,21 +163,17 @@ impl Drop for RunningSameThreadGuard { } } -pub struct MaybeCrossThread

{ +pub struct MaybeCrossThread { cross_thread: bool, - marker: PhantomData

, } -impl

MaybeCrossThread

{ +impl MaybeCrossThread { pub const fn new(cross_thread: bool) -> Self { - MaybeCrossThread { cross_thread, marker: PhantomData } + MaybeCrossThread { cross_thread } } } -impl

ExecutionStrategy for MaybeCrossThread

-where - P: MessagePipe + Send + 'static, -{ +impl ExecutionStrategy for MaybeCrossThread { fn run_bridge_and_client( &self, dispatcher: &mut Dispatcher, @@ -186,12 +182,7 @@ where 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, - ) + CrossThread.run_bridge_and_client(dispatcher, input, run_client, force_show_panics) } else { SameThread.run_bridge_and_client(dispatcher, input, run_client, force_show_panics) } @@ -216,18 +207,9 @@ impl ExecutionStrategy for SameThread { } } -pub struct CrossThread

(PhantomData

); +pub struct CrossThread; -impl

CrossThread

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

ExecutionStrategy for CrossThread

-where - P: MessagePipe + Send + 'static, -{ +impl ExecutionStrategy for CrossThread { fn run_bridge_and_client( &self, dispatcher: &mut Dispatcher, @@ -235,7 +217,7 @@ where run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, force_show_panics: bool, ) -> Buffer { - let (mut server, mut client) = P::new(); + let (mut server, mut client) = MessagePipe::new(); let join_handle = thread::spawn(move || { let mut dispatch = |b: Buffer| -> Buffer { @@ -255,18 +237,31 @@ where } /// A message pipe used for communicating between server and client threads. -pub trait MessagePipe: Sized { +struct MessagePipe { + tx: std::sync::mpsc::SyncSender, + rx: std::sync::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< From f601b29825f874ba05e67631ddb80a2b830cc03c Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 13 Feb 2026 11:24:50 +0000 Subject: [PATCH 143/182] inline `SameThread` and `CrossThread` --- compiler/rustc_expand/src/proc_macro.rs | 6 +- library/proc_macro/src/bridge/server.rs | 92 +++++++------------ .../proc-macro-srv/src/dylib/proc_macros.rs | 6 +- 3 files changed, 40 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 530e7b998d41..e67855700813 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -12,10 +12,10 @@ use crate::base::{self, *}; use crate::{errors, proc_macro_server}; 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/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index b5b63ead4464..1151798fccf4 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -121,10 +121,13 @@ macro_rules! define_dispatcher { } 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( + fn run_bridge_and_client( &self, - dispatcher: &mut Dispatcher, + dispatcher: &mut Dispatcher, input: Buffer, run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, force_show_panics: bool, @@ -164,82 +167,55 @@ impl Drop for RunningSameThreadGuard { } pub struct MaybeCrossThread { - cross_thread: bool, + pub cross_thread: bool, } -impl MaybeCrossThread { - pub const fn new(cross_thread: bool) -> Self { - MaybeCrossThread { cross_thread } - } -} +pub const SAME_THREAD: MaybeCrossThread = MaybeCrossThread { cross_thread: false }; +pub const CROSS_THREAD: MaybeCrossThread = MaybeCrossThread { cross_thread: true }; impl ExecutionStrategy for MaybeCrossThread { - fn run_bridge_and_client( + fn run_bridge_and_client( &self, - dispatcher: &mut Dispatcher, + 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() { - CrossThread.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 Dispatcher, - 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; - -impl ExecutionStrategy for CrossThread { - fn run_bridge_and_client( - &self, - dispatcher: &mut Dispatcher, - input: Buffer, - run_client: extern "C" fn(BridgeConfig<'_>) -> Buffer, - force_show_panics: bool, - ) -> Buffer { - 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") - }; + 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. struct MessagePipe { - tx: std::sync::mpsc::SyncSender, - rx: std::sync::mpsc::Receiver, + tx: mpsc::SyncSender, + rx: mpsc::Receiver, } impl MessagePipe { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs index 76c5097101c7..4065dbd0b49b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/proc_macros.rs @@ -30,7 +30,7 @@ impl ProcMacros { if *trait_name == macro_name => { let res = client.run( - &bridge::server::SameThread, + &bridge::server::SAME_THREAD, S::make_server(call_site, def_site, mixed_site, callback), macro_body, cfg!(debug_assertions), @@ -39,7 +39,7 @@ impl ProcMacros { } bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { let res = client.run( - &bridge::server::SameThread, + &bridge::server::SAME_THREAD, S::make_server(call_site, def_site, mixed_site, callback), macro_body, cfg!(debug_assertions), @@ -48,7 +48,7 @@ impl ProcMacros { } bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { let res = client.run( - &bridge::server::SameThread, + &bridge::server::SAME_THREAD, S::make_server(call_site, def_site, mixed_site, callback), parsed_attributes, macro_body, From 1d6ef95075a0268e70e1868a7db03192040685d3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Feb 2026 22:06:57 +1100 Subject: [PATCH 144/182] Extract `DepKindVTable` constructors to their own module --- .../rustc_query_impl/src/dep_kind_vtables.rs | 174 +++++++++++++++++ compiler/rustc_query_impl/src/lib.rs | 10 +- compiler/rustc_query_impl/src/plumbing.rs | 179 ++---------------- 3 files changed, 200 insertions(+), 163 deletions(-) create mode 100644 compiler/rustc_query_impl/src/dep_kind_vtables.rs 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..92fd9c6734d0 --- /dev/null +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -0,0 +1,174 @@ +use rustc_middle::bug; +use rustc_middle::dep_graph::DepKindVTable; +use rustc_middle::ty::TyCtxt; +use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle}; +use rustc_query_system::query::QueryCache; + +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_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 9b2078275aae..feeb072f027a 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -12,8 +12,7 @@ use std::marker::ConstParamTy; use rustc_data_structures::sync::AtomicU64; -use rustc_middle::arena::Arena; -use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNode, DepNodeIndex}; +use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex}; use rustc_middle::queries::{ self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, }; @@ -27,6 +26,7 @@ use rustc_query_system::query::{ }; use rustc_span::{ErrorGuaranteed, Span}; +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}; @@ -34,11 +34,13 @@ use crate::profiling_support::QueryKeyStringCache; pub use crate::profiling_support::alloc_self_profile_query_strings; use crate::values::Value; +#[macro_use] +mod plumbing; + +mod dep_kind_vtables; mod error; mod execution; mod job; -#[macro_use] -mod plumbing; mod profiling_support; mod values; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 9804e6b21756..12cef31f58bb 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -13,9 +13,10 @@ 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, DepKindVTable, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex, - dep_kinds, + self, DepContext, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex, dep_kinds, }; use rustc_middle::query::Key; use rustc_middle::query::on_disk_cache::{ @@ -26,7 +27,7 @@ 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::{DepNodeKey, FingerprintStyle, HasDepContext}; +use rustc_query_system::dep_graph::{DepNodeKey, HasDepContext}; use rustc_query_system::query::{ QueryCache, QueryContext, QueryJobId, QuerySideEffect, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, @@ -447,7 +448,8 @@ pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache, const FLAGS: QueryFlags }); } -fn try_load_from_on_disk_cache<'tcx, C: QueryCache, const FLAGS: QueryFlags>( +/// 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, @@ -496,7 +498,8 @@ where value } -fn force_from_dep_node<'tcx, C: QueryCache, const FLAGS: QueryFlags>( +/// 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, @@ -527,49 +530,6 @@ fn force_from_dep_node<'tcx, C: QueryCache, const FLAGS: QueryFlags>( } } -pub(crate) fn make_dep_kind_vtable_for_query< - 'tcx, - Q, - C: QueryCache + 'tcx, - const FLAGS: QueryFlags, ->( - is_eval_always: bool, -) -> DepKindVTable<'tcx> -where - Q: QueryDispatcherUnerased<'tcx, C, FLAGS>, -{ - 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(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, - } -} - // 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 { @@ -882,119 +842,20 @@ macro_rules! define_queries { 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_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)) + )* } } } From 4796ff1bf53be2e639928603f37268c13302bb46 Mon Sep 17 00:00:00 2001 From: usamoi Date: Fri, 13 Feb 2026 20:30:23 +0800 Subject: [PATCH 145/182] move `escape_symbol_name` to `cg_ssa` --- .../rustc_codegen_cranelift/src/global_asm.rs | 5 ++- compiler/rustc_codegen_llvm/src/asm.rs | 44 ++----------------- .../src/back/symbol_export.rs | 41 +++++++++++++++++ 3 files changed, 47 insertions(+), 43 deletions(-) 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_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index fd25fba2daac..80d77be1cc38 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -400,6 +400,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.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 } => { // 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(&escape_symbol_name(self, symbol, span)); + 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(&escape_symbol_name(self, symbol, span)); + template_str.push_str(&escape_symbol_name(self.tcx, &symbol, span)); } } } @@ -1390,42 +1391,3 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } - -fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String { - use rustc_target::spec::{Arch, BinaryFormat}; - if !symbol.is_empty() - && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) - { - return symbol; - } - if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff { - cx.tcx.sess.dcx().span_fatal( - span, - format!( - "symbol escaping is not supported for the binary format {}", - cx.tcx.sess.target.binary_format - ), - ); - } - if cx.tcx.sess.target.arch == Arch::Nvptx64 { - cx.tcx.sess.dcx().span_fatal( - span, - format!( - "symbol escaping is not supported for the architecture {}", - cx.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/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 +} From c2b8abd8105349dea576917903408266a9212a84 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 07:49:27 -0500 Subject: [PATCH 146/182] Update to nightly-2026-02-13 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index c2179bc3ff98..ce97f300fa40 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-01-30" +channel = "nightly-2026-02-13" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 458adbd66a7bf85a058fd4e4d4b88ef86e604ee2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 08:12:59 -0500 Subject: [PATCH 147/182] Implement fptoint_sat for f16 and f128 --- src/builder.rs | 33 +++++++++++++++++++-------------- src/common.rs | 4 ++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 6347a3fb19b4..8dac76f01d10 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1873,32 +1873,33 @@ 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) { + fn compute_clamp_bounds(signed: bool, int_width: u64) -> (u128, u128) { let rounded_min = - ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero); + 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); + 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. @@ -1928,15 +1929,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/src/common.rs b/src/common.rs index 1f133fa0c1b7..86a4eeac89d5 100644 --- a/src/common.rs +++ b/src/common.rs @@ -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); From 5577bd7ac4bafda4888205fa4a621ca0e89f7180 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 08:13:29 -0500 Subject: [PATCH 148/182] Add missing -Zjson-target-spec for m68k test --- .github/workflows/m68k.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index e49c62d6c931..11bc88e67d2d 100644 --- a/.github/workflows/m68k.yml +++ b/.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 From ab13120882d43a6e4bef72ec1cd6750e24482041 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Fri, 13 Feb 2026 13:16:21 +0000 Subject: [PATCH 149/182] Port #[rustc_proc_macro_decls] to the new attribute parser. --- .../rustc_attr_parsing/src/attributes/macro_attrs.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_interface/src/proc_macro_decls.rs | 7 +++---- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 18 insertions(+), 5 deletions(-) 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/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c6f0914bfbda..f68b27dd58a6 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -297,6 +297,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index e28ecd06b89b..877f2b0afe49 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1288,6 +1288,9 @@ pub enum AttributeKind { /// 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), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b4cf244bfb8a..0d8e70a9f39b 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -156,6 +156,7 @@ impl AttributeKind { RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, RustcPreserveUbChecks => No, + RustcProcMacroDecls => No, RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcRegions => No, 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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 08f2597e874d..9dcf1ae74d00 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -348,6 +348,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::RustcPreserveUbChecks + | AttributeKind::RustcProcMacroDecls | AttributeKind::RustcReallocator | AttributeKind::RustcRegions | AttributeKind::RustcReservationImpl(..) @@ -406,7 +407,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_doc_primitive | sym::rustc_test_marker | sym::rustc_layout - | sym::rustc_proc_macro_decls | sym::rustc_autodiff | sym::rustc_capture_analysis | sym::rustc_mir From 27e25ff6d8f9594b23ebb22e677481029fbbd8a7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 08:27:31 -0500 Subject: [PATCH 150/182] Add failing tests --- tests/failing-run-make-tests.txt | 2 +- tests/failing-ui-tests.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 822aaec0edeb..528ee1df9f58 100644 --- a/tests/failing-run-make-tests.txt +++ b/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/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 75ca1845f45e..8589929d2fbc 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -98,3 +98,4 @@ 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 From e373b93b0b953033f869e386d30d2446b920133b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 08:35:12 -0500 Subject: [PATCH 151/182] Fix formatting --- src/builder.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8dac76f01d10..e1937f5c11eb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1892,11 +1892,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { (rounded_min.value.to_bits(), rounded_max.value.to_bits()) }; 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); + let rounded_min = F::from_i128_r(int_min(signed, int_width), Round::TowardZero); assert_eq!(rounded_min.status, Status::OK); - let rounded_max = - F::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()) } From b4f38c1da4a7aa9d7065253f77a65a482a5a7993 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 13 Feb 2026 12:51:47 +0000 Subject: [PATCH 152/182] add regression test --- .../ui/layout/rigid-alias-due-to-broken-impl.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/ui/layout/rigid-alias-due-to-broken-impl.rs diff --git a/tests/ui/layout/rigid-alias-due-to-broken-impl.rs b/tests/ui/layout/rigid-alias-due-to-broken-impl.rs new file mode 100644 index 000000000000..912c660cb7ca --- /dev/null +++ b/tests/ui/layout/rigid-alias-due-to-broken-impl.rs @@ -0,0 +1,17 @@ +// Make sure we don't ICE if `layout_of` encounters an alias +// which is rigid due to a malformed program. A regression test +// for #152545. +// +// This specific ICE happens in the `KnownPanicsLint` visitor. + +//@ compile-flags: --crate-type=rlib +trait Foo { + type Assoc; +} + +// The trait solver only treats missng associated items +// as rigid if the self-type is known to be unsized. +impl Foo for str {} +//~^ ERROR not all trait items implemented + +fn foo(_: [u32; std::mem::size_of::<::Assoc>()]) {} From b3d9fbc17271a03bdd3ccbf95bb296b3505d4120 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 13 Feb 2026 12:52:05 +0000 Subject: [PATCH 153/182] ICE to delayed bug --- compiler/rustc_ty_utils/src/layout.rs | 4 +++- .../ui/layout/rigid-alias-due-to-broken-impl.stderr | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/ui/layout/rigid-alias-due-to-broken-impl.stderr diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index bebc0707e26d..5a41e46f3a6b 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -777,7 +777,9 @@ fn layout_of_uncached<'tcx>( let err = if ty.has_param() || !cx.typing_env.param_env.caller_bounds().is_empty() { LayoutError::TooGeneric(ty) } else { - unreachable!("invalid rigid alias in layout_of after normalization: {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/tests/ui/layout/rigid-alias-due-to-broken-impl.stderr b/tests/ui/layout/rigid-alias-due-to-broken-impl.stderr new file mode 100644 index 000000000000..e9ba6df2fdc7 --- /dev/null +++ b/tests/ui/layout/rigid-alias-due-to-broken-impl.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Assoc` + --> $DIR/rigid-alias-due-to-broken-impl.rs:14:1 + | +LL | type Assoc; + | ---------- `Assoc` from trait +... +LL | impl Foo for str {} + | ^^^^^^^^^^^^^^^^ missing `Assoc` in implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. From ec2996cfbad0c83c172486fd6213290f43cc9a90 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 10:39:02 -0500 Subject: [PATCH 154/182] Add cast from f128 to non-native integer --- src/int.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/int.rs b/src/int.rs index 49de0b490e88..442a54addf29 100644 --- a/src/int.rs +++ b/src/int.rs @@ -955,6 +955,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // cSpell:disable TypeKind::Float => "sfti", TypeKind::Double => "dfti", + TypeKind::FP128 => "tfti", // cSpell:enable kind => panic!("cannot cast a {:?} to non-native integer", kind), }; From 4a6f0bebfb8c14ea11cbdc443d9803f750dbd934 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 10:39:24 -0500 Subject: [PATCH 155/182] Add missing -Zjson-target-spec for m68k sysroot build --- build_system/src/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 9b7ee8380ca5..839c762fed74 100644 --- a/build_system/src/build.rs +++ b/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); From c61c2603cf153196aed4f741a9d86a753794839c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 13 Feb 2026 16:04:19 +0000 Subject: [PATCH 156/182] Port `#[lang]` to the new attribute parsers --- .../src/attributes/rustc_internal.rs | 29 ++++++++++++++++++- compiler/rustc_attr_parsing/src/context.rs | 1 + .../src/session_diagnostics.rs | 9 ++++++ .../rustc_codegen_ssa/src/codegen_attrs.rs | 4 +-- .../src/error_codes/E0264.md | 4 +-- .../rustc_hir/src/attrs/data_structures.rs | 4 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir/src/lang_items.rs | 20 +++---------- compiler/rustc_passes/src/check_attr.rs | 12 ++++---- compiler/rustc_passes/src/dead.rs | 12 +++----- compiler/rustc_passes/src/errors.rs | 9 ------ compiler/rustc_passes/src/lang_items.rs | 25 ++++++++++++---- compiler/rustc_passes/src/weak_lang_items.rs | 3 +- tests/ui/error-codes/E0264.rs | 4 +-- tests/ui/error-codes/E0264.stderr | 4 +-- tests/ui/lowering/issue-96847.rs | 3 +- tests/ui/lowering/issue-96847.stderr | 9 ++++++ 17 files changed, 96 insertions(+), 57 deletions(-) create mode 100644 tests/ui/lowering/issue-96847.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index f1b31365013e..7dbf38419a4b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,6 +1,7 @@ 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, @@ -12,7 +13,7 @@ use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; use crate::session_diagnostics::{ - AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, + AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem, }; pub(crate) struct RustcMainParser; @@ -626,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 { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c6f0914bfbda..b61da848967a 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -181,6 +181,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 2eb585671fff..e98969dda300 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1013,6 +1013,15 @@ pub(crate) struct DocAliasMalformed { pub span: Span, } +#[derive(Diagnostic)] +#[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> { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 9ecb7ab9fd45..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, }; @@ -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_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_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index e28ecd06b89b..9ed4856e3a2d 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -8,6 +8,7 @@ use rustc_ast::token::DocFragmentKind; 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; @@ -953,6 +954,9 @@ pub enum AttributeKind { /// Represents `#[instruction_set]` InstructionSet(InstructionSetAttr), + /// Represents `#[lang]` + Lang(LangItem, Span), + /// Represents `#[link]`. Link(ThinVec, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b4cf244bfb8a..b656cc26bd8e 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -50,6 +50,7 @@ impl AttributeKind { Ignore { .. } => No, Inline(..) => No, InstructionSet(..) => No, + Lang(..) => Yes, Link(..) => No, LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, 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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 08f2597e874d..e7d546874c83 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -256,6 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Fundamental | AttributeKind::Ignore { .. } | AttributeKind::InstructionSet(..) + | AttributeKind::Lang(..) | AttributeKind::LinkName { .. } | AttributeKind::LinkOrdinal { .. } | AttributeKind::LinkSection { .. } @@ -395,8 +396,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // need to be fixed | sym::deprecated_safe // FIXME(deprecated_safe) // internal - | sym::panic_handler - | sym::lang | sym::default_lib_allocator | sym::rustc_diagnostic_item | sym::rustc_nonnull_optimization_guaranteed @@ -786,15 +785,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, }); } @@ -858,7 +856,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 @@ -868,7 +866,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::LangItemWithTargetFeature { attr_span, - name: lang_item, + name: lang_item.name(), sig_span: sig.span, }); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 75bac9eff2c7..e56d27721bdd 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -22,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, @@ -706,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; @@ -732,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/errors.rs b/compiler/rustc_passes/src/errors.rs index f420bba9b4e9..630a39781309 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -465,15 +465,6 @@ pub(crate) struct LangItemOnIncorrectTarget { pub actual_target: Target, } -#[derive(Diagnostic)] -#[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, -} - pub(crate) struct InvalidAttrAtCrateLevel { pub span: Span, pub sugg_span: Option, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index b9417af13b11..ba71630d2681 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -8,19 +8,18 @@ //! * Functions called by the compiler itself. use rustc_ast as ast; -use rustc_ast::visit; +use rustc_ast::fmvisit; 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/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/tests/ui/error-codes/E0264.rs b/tests/ui/error-codes/E0264.rs index 6adaf01fb524..855644796ed4 100644 --- a/tests/ui/error-codes/E0264.rs +++ b/tests/ui/error-codes/E0264.rs @@ -1,8 +1,8 @@ #![feature(lang_items)] extern "C" { - #[lang = "cake"] - fn cake(); //~ ERROR E0264 + #[lang = "copy"] + fn copy(); //~ ERROR E0264 } fn main() {} diff --git a/tests/ui/error-codes/E0264.stderr b/tests/ui/error-codes/E0264.stderr index 3503fb229e4f..6442f42e689d 100644 --- a/tests/ui/error-codes/E0264.stderr +++ b/tests/ui/error-codes/E0264.stderr @@ -1,7 +1,7 @@ -error[E0264]: unknown external lang item: `cake` +error[E0264]: unknown external lang item: `copy` --> $DIR/E0264.rs:5:5 | -LL | fn cake(); +LL | fn copy(); | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/lowering/issue-96847.rs b/tests/ui/lowering/issue-96847.rs index 9408f6b9b4ab..a1fd105d9dd4 100644 --- a/tests/ui/lowering/issue-96847.rs +++ b/tests/ui/lowering/issue-96847.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-fail // Test that this doesn't abort during AST lowering. In #96847 it did abort // because the attribute was being lowered twice. @@ -9,6 +9,7 @@ fn main() { for _ in [1,2,3] { #![lang="foo"] + //~^ ERROR definition of an unknown lang item: `foo` [E0522] println!("foo"); } } diff --git a/tests/ui/lowering/issue-96847.stderr b/tests/ui/lowering/issue-96847.stderr new file mode 100644 index 000000000000..2cded32f9fb8 --- /dev/null +++ b/tests/ui/lowering/issue-96847.stderr @@ -0,0 +1,9 @@ +error[E0522]: definition of an unknown lang item: `foo` + --> $DIR/issue-96847.rs:11:9 + | +LL | #![lang="foo"] + | ^^^^^^^^^^^^^^ definition of unknown lang item `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0522`. From ee8ca0a89ff8bff74c98ac0920cbfcb366354286 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 13 Feb 2026 12:43:02 +0000 Subject: [PATCH 157/182] Port `#[panic_handler]` to the new attribute parsers --- .../rustc_attr_parsing/src/attributes/rustc_internal.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_passes/src/lang_items.rs | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 7dbf38419a4b..e7b639c9af18 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -668,6 +668,15 @@ 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 { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b61da848967a..93a2b819c51f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -254,6 +254,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index ba71630d2681..25aea8e9f82a 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -8,7 +8,7 @@ //! * Functions called by the compiler itself. use rustc_ast as ast; -use rustc_ast::fmvisit; +use rustc_ast::visit; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::GenericRequirement; From c43a33eec7b29a637ff8a41804d30e679092bad9 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 3 Feb 2026 23:34:42 +0000 Subject: [PATCH 158/182] Feed `ErrorGuaranteed` from late lifetime resolution to RBV If late lifetime resolution fails for whatever reason, forward to RBV the guarantee that an error was emitted - thereby eliminating the need for a "hack" to suppress subsequent/superfluous error diagnostics. --- compiler/rustc_ast_lowering/src/lib.rs | 56 +++++---- compiler/rustc_hir/src/def.rs | 2 +- compiler/rustc_hir/src/hir.rs | 4 +- .../src/collect/resolve_bound_vars.rs | 10 +- .../src/hir_ty_lowering/dyn_trait.rs | 12 +- compiler/rustc_resolve/src/late.rs | 119 +++++++++++------- .../rustc_resolve/src/late/diagnostics.rs | 68 +++++----- .../cast/ice-cast-type-with-error-124848.rs | 1 - .../ice-cast-type-with-error-124848.stderr | 10 +- tests/ui/closures/binder/implicit-stuff.rs | 1 - .../ui/closures/binder/implicit-stuff.stderr | 11 +- .../ice-line-bounds-issue-148732.rs | 1 - .../ice-line-bounds-issue-148732.stderr | 17 +-- .../undeclared-object-lifetime.rs | 7 ++ .../undeclared-object-lifetime.stderr | 14 +++ tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs | 1 - .../ui/rfcs/rfc-1623-static/rfc1623-3.stderr | 11 +- 17 files changed, 184 insertions(+), 161 deletions(-) create mode 100644 tests/ui/object-lifetime/undeclared-object-lifetime.rs create mode 100644 tests/ui/object-lifetime/undeclared-object-lifetime.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ff5edfc79943..6265a06410d5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -878,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 @@ -1931,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); @@ -2014,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 }; 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 68fc7653b636..f1f7350c1e79 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -238,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 @@ -258,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, } } } 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 3e687700f11c..ff919bd58ba1 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -663,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 => { @@ -804,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) => { @@ -891,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 => {} } 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 a0b9b60cde5c..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(span.shrink_to_hi()) - } + RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi()) } else { RegionInferReason::ExplicitObjectLifetime }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fe6346f6c6e9..dd85c3083d4c 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) + } + } + } + } } }); } @@ -3025,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; } @@ -3035,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, @@ -3068,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; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 95f0d3e67ef2..a55d098f7bf1 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -131,7 +131,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, @@ -3274,7 +3274,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 +3319,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } - err.emit(); + err.emit() } fn suggest_introducing_lifetime( @@ -3473,14 +3473,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 +3493,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 @@ -3512,18 +3514,18 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime, 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(), @@ -3540,13 +3542,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!( @@ -3675,7 +3677,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); @@ -3703,7 +3705,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" @@ -3728,7 +3732,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) { @@ -4024,7 +4030,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, @@ -4034,7 +4044,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/tests/ui/cast/ice-cast-type-with-error-124848.rs b/tests/ui/cast/ice-cast-type-with-error-124848.rs index 9b3732b02db4..0c623de8050b 100644 --- a/tests/ui/cast/ice-cast-type-with-error-124848.rs +++ b/tests/ui/cast/ice-cast-type-with-error-124848.rs @@ -14,5 +14,4 @@ fn main() { let bad_addr = &unpinned as *const Cell>> as usize; //~^ ERROR use of undeclared lifetime name `'a` //~| ERROR use of undeclared lifetime name `'a` - //~| ERROR casting `&MyType<'_>` as `*const Cell>>` is invalid } diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.stderr b/tests/ui/cast/ice-cast-type-with-error-124848.stderr index dff227727324..665b0e0a0dd4 100644 --- a/tests/ui/cast/ice-cast-type-with-error-124848.stderr +++ b/tests/ui/cast/ice-cast-type-with-error-124848.stderr @@ -58,13 +58,7 @@ help: provide the argument LL | let mut unpinned = MyType(Cell::new(None), /* value */); | +++++++++++++ -error[E0606]: casting `&MyType<'_>` as `*const Cell>>` is invalid - --> $DIR/ice-cast-type-with-error-124848.rs:14:20 - | -LL | let bad_addr = &unpinned as *const Cell>> as usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 5 previous errors -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0061, E0261, E0425, E0606. +Some errors have detailed explanations: E0061, E0261, E0425. For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs index c976c200b0c8..09e4c747afee 100644 --- a/tests/ui/closures/binder/implicit-stuff.rs +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -24,5 +24,4 @@ fn main() { //~| ERROR `'_` cannot be used here let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here - //~^ ERROR: lifetime may not live long enough } diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index 330a05a79bae..cec2a60ba28c 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -102,15 +102,6 @@ LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { | | | `for<...>` is here -error: lifetime may not live long enough - --> $DIR/implicit-stuff.rs:26:42 - | -LL | let _ = for<'a> |x: &'a ()| -> &() { x }; - | -- - ^ returning this value requires that `'a` must outlive `'1` - | | | - | | let's call the lifetime of this reference `'1` - | lifetime `'a` defined here - -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.rs b/tests/ui/delegation/ice-line-bounds-issue-148732.rs index e44c78476021..699e7d86f258 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.rs +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.rs @@ -3,7 +3,6 @@ reuse a as b { //~| ERROR functions delegation is not yet fully implemented dbg!(b); //~^ ERROR missing lifetime specifier - //~| ERROR `fn() {b}` doesn't implement `Debug` } fn main() {} diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr index 83cc238b5e0c..c4f261181b10 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr @@ -17,7 +17,7 @@ LL | / reuse a as b { LL | | LL | | LL | | dbg!(b); -... | +LL | | LL | | } | |_^ | @@ -25,18 +25,7 @@ LL | | } = help: add `#![feature(fn_delegation)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0277]: `fn() {b}` doesn't implement `Debug` - --> $DIR/ice-line-bounds-issue-148732.rs:4:5 - | -LL | reuse a as b { - | - consider calling this function -... -LL | dbg!(b); - | ^^^^^^^ the trait `Debug` is not implemented for fn item `fn() {b}` - | - = help: use parentheses to call this function: `b()` +error: aborting due to 3 previous errors -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0106, E0277, E0425, E0658. +Some errors have detailed explanations: E0106, E0425, E0658. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/object-lifetime/undeclared-object-lifetime.rs b/tests/ui/object-lifetime/undeclared-object-lifetime.rs new file mode 100644 index 000000000000..7c0e1100fe7b --- /dev/null +++ b/tests/ui/object-lifetime/undeclared-object-lifetime.rs @@ -0,0 +1,7 @@ +//! E0228 (lifetime bound for trait object cannot be deduced from context) should not be emitted +//! when an undeclared lifetime bound has been specified. +//! +//! Regression test for https://github.com/rust-lang/rust/issues/152014 + +fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} //~ ERROR use of undeclared lifetime name `'undefined` +fn main() {} diff --git a/tests/ui/object-lifetime/undeclared-object-lifetime.stderr b/tests/ui/object-lifetime/undeclared-object-lifetime.stderr new file mode 100644 index 000000000000..b6646a05420b --- /dev/null +++ b/tests/ui/object-lifetime/undeclared-object-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0261]: use of undeclared lifetime name `'undefined` + --> $DIR/undeclared-object-lifetime.rs:6:24 + | +LL | fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} + | ^^^^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'undefined` here + | +LL | fn f<'undefined>(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs index 26fa6fdb57f9..35a2ef10c2e3 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs @@ -9,6 +9,5 @@ static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = //~^ ERROR missing lifetime specifier [E0106] &(non_elidable as fn(&u8, &u8) -> &u8); //~^ ERROR missing lifetime specifier [E0106] - //~| ERROR non-primitive cast fn main() {} diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr index 77fc3f0412eb..05ea6e44486f 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr @@ -23,13 +23,6 @@ help: consider making the type lifetime-generic with a new `'a` lifetime LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); | +++++++ ++ ++ ++ -error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8` - --> $DIR/rfc1623-3.rs:10:6 - | -LL | &(non_elidable as fn(&u8, &u8) -> &u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0106, E0605. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`. From c5cb56957a1e245ac5bd195fbfc961f319dc9295 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 13 Feb 2026 10:56:10 -0500 Subject: [PATCH 159/182] Add cast from f16 to non-native integer --- src/int.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/int.rs b/src/int.rs index 442a54addf29..51612d604c8f 100644 --- a/src/int.rs +++ b/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,9 +951,14 @@ 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 @@ -961,7 +966,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { }; 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, @@ -970,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]) } From be204dd047e5fb65aac96cb8fb81734d2f22f895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 13 Feb 2026 17:10:29 +0000 Subject: [PATCH 160/182] make per-point liveness accessible It avoids round-tripping through `Location`s if you're working with `Point`s already. --- compiler/rustc_borrowck/src/polonius/mod.rs | 3 +-- compiler/rustc_borrowck/src/region_infer/values.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 0924ce25c52e..45108bfcb79b 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -182,8 +182,7 @@ impl LocalizedConstraintGraphVisitor for LoanLivenessVisitor<'_> { // // FIXME: analyze potential unsoundness, possibly in concert with a borrowck // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples. - let location = self.liveness.location_from_point(node.point); - if self.liveness.is_live_at(node.region, location) { + 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/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 1dd3bc831f45..c1fed1260340 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -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 { From 65eb2e709d1d1282b8e258281a5ee2a9edaf9a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 13 Feb 2026 17:29:49 +0000 Subject: [PATCH 161/182] add another NLL problem case 3 variant --- .../nll-problem-case-3-issue-21906.nll.stderr | 23 +++++++++++++++---- .../nll-problem-case-3-issue-21906.rs | 20 ++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr index e16300886b0b..0ab90faabcf0 100644 --- a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr +++ b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.nll.stderr @@ -35,8 +35,21 @@ LL | | } LL | | } | |_____- returning this value requires that `*map` is borrowed for `'r` +error[E0499]: cannot borrow `*map` as mutable more than once at a time + --> $DIR/nll-problem-case-3-issue-21906.rs:45:41 + | +LL | fn get_priority_mut_entry<'a, K, V>( + | -- lifetime `'a` defined here +... +LL | match map.entry(key1) { + | --- first mutable borrow occurs here +LL | Entry::Occupied(occupied) => Some(occupied.into_mut()), + | ------------------------- returning this value requires that `*map` is borrowed for `'a` +LL | Entry::Vacant(_vacant) => match map.entry(key2) { + | ^^^ second mutable borrow occurs here + error[E0499]: cannot borrow `*self` as mutable more than once at a time - --> $DIR/nll-problem-case-3-issue-21906.rs:44:21 + --> $DIR/nll-problem-case-3-issue-21906.rs:64:21 | LL | fn two(&mut self) -> &i32 { | - let's call the lifetime of this reference `'1` @@ -48,7 +61,7 @@ LL | return k; | - returning this value requires that `*self` is borrowed for `'1` error[E0502]: cannot borrow `x.data` as immutable because it is also borrowed as mutable - --> $DIR/nll-problem-case-3-issue-21906.rs:62:22 + --> $DIR/nll-problem-case-3-issue-21906.rs:82:22 | LL | fn foo(x: &mut Foo) -> Option<&mut i32> { | - let's call the lifetime of this reference `'1` @@ -61,7 +74,7 @@ LL | println!("{:?}", x.data); | ^^^^^^ immutable borrow occurs here error[E0499]: cannot borrow `*vec` as mutable more than once at a time - --> $DIR/nll-problem-case-3-issue-21906.rs:77:9 + --> $DIR/nll-problem-case-3-issue-21906.rs:97:9 | LL | fn f(vec: &mut Vec) -> &u8 { | - let's call the lifetime of this reference `'1` @@ -75,7 +88,7 @@ LL | vec.push(10); | ^^^ second mutable borrow occurs here error[E0502]: cannot borrow `*vec` as immutable because it is also borrowed as mutable - --> $DIR/nll-problem-case-3-issue-21906.rs:78:9 + --> $DIR/nll-problem-case-3-issue-21906.rs:98:9 | LL | fn f(vec: &mut Vec) -> &u8 { | - let's call the lifetime of this reference `'1` @@ -88,7 +101,7 @@ LL | n LL | vec.last().unwrap() | ^^^ immutable borrow occurs here -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0499, E0502. For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs index b025ea78f8b4..45b56e32522f 100644 --- a/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs +++ b/tests/ui/nll/polonius/nll-problem-case-3-issue-21906.rs @@ -29,6 +29,26 @@ fn from_the_rfc<'r, K: Hash + Eq + Copy, V: Default>( } } +// A variant that's similar to the RFC example above, but using the entry API, and requested in +// https://internals.rust-lang.org/t/get-mut-map-back-from-entry-api/24003 +fn get_priority_mut_entry<'a, K, V>( + map: &'a mut HashMap, + key1: K, + key2: K, +) -> Option<&'a mut V> +where + K: Eq + Hash, +{ + use std::collections::hash_map::Entry; + match map.entry(key1) { + Entry::Occupied(occupied) => Some(occupied.into_mut()), + Entry::Vacant(_vacant) => match map.entry(key2) { + Entry::Occupied(occupied2) => Some(occupied2.into_mut()), + Entry::Vacant(_) => None, + }, + } +} + // MCVE 1 from issue #21906 struct A { a: i32, From dca86a9521005874a3ad05e00c09b7f7004cbeee Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 29 Nov 2025 12:04:31 -0600 Subject: [PATCH 162/182] rustdoc: sort stable items first --- src/librustdoc/clean/types.rs | 4 ++++ src/librustdoc/formats/cache.rs | 2 ++ src/librustdoc/html/render/mod.rs | 1 + src/librustdoc/html/render/search_index.rs | 9 +++++++++ src/librustdoc/html/static/js/rustdoc.d.ts | 2 ++ src/librustdoc/html/static/js/search.js | 13 ++++++++++++- tests/rustdoc-js-std/core-transmute.js | 2 +- tests/rustdoc-js-std/transmute-fail.js | 2 +- tests/rustdoc-js-std/transmute.js | 2 +- tests/rustdoc-js/sort-stability.js | 9 +++++++++ tests/rustdoc-js/sort-stability.rs | 16 ++++++++++++++++ 11 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 tests/rustdoc-js/sort-stability.js create mode 100644 tests/rustdoc-js/sort-stability.rs diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c145929534d9..9687d014c872 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -431,6 +431,10 @@ impl Item { self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect()) } + pub(crate) fn is_unstable(&self) -> bool { + self.stability.is_some_and(|x| x.is_unstable()) + } + pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false) } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 64e361d566c3..5a97d8e5b5f4 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -594,6 +594,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It ); let aliases = item.attrs.get_doc_aliases(); let is_deprecated = item.is_deprecated(tcx); + let is_unstable = item.is_unstable(); let index_item = IndexItem { ty: item.type_(), defid: Some(defid), @@ -609,6 +610,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It search_type, aliases, is_deprecated, + is_unstable, }; cache.search_index.push(index_item); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 86e8167dc3cd..57428b6f481e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -142,6 +142,7 @@ pub(crate) struct IndexItem { pub(crate) search_type: Option, pub(crate) aliases: Box<[Symbol]>, pub(crate) is_deprecated: bool, + pub(crate) is_unstable: bool, } /// A type used for the search index. diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 30b534003da1..7c493653e77c 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -616,6 +616,7 @@ impl SerializedSearchIndex { parent, trait_parent, deprecated, + unstable, associated_item_disambiguator, }| EntryData { krate: *map.get(krate).unwrap(), @@ -626,6 +627,7 @@ impl SerializedSearchIndex { parent: parent.and_then(|path_id| map.get(&path_id).copied()), trait_parent: trait_parent.and_then(|path_id| map.get(&path_id).copied()), deprecated: *deprecated, + unstable: *unstable, associated_item_disambiguator: associated_item_disambiguator.clone(), }, ), @@ -896,6 +898,7 @@ struct EntryData { parent: Option, trait_parent: Option, deprecated: bool, + unstable: bool, associated_item_disambiguator: Option, } @@ -912,6 +915,7 @@ impl Serialize for EntryData { seq.serialize_element(&self.parent.map(|id| id + 1).unwrap_or(0))?; seq.serialize_element(&self.trait_parent.map(|id| id + 1).unwrap_or(0))?; seq.serialize_element(&if self.deprecated { 1 } else { 0 })?; + seq.serialize_element(&if self.unstable { 1 } else { 0 })?; if let Some(disambig) = &self.associated_item_disambiguator { seq.serialize_element(&disambig)?; } @@ -946,6 +950,7 @@ impl<'de> Deserialize<'de> for EntryData { v.next_element()?.ok_or_else(|| A::Error::missing_field("trait_parent"))?; let deprecated: u32 = v.next_element()?.unwrap_or(0); + let unstable: u32 = v.next_element()?.unwrap_or(0); let associated_item_disambiguator: Option = v.next_element()?; Ok(EntryData { krate, @@ -956,6 +961,7 @@ impl<'de> Deserialize<'de> for EntryData { parent: Option::::from(parent).map(|path| path as usize), trait_parent: Option::::from(trait_parent).map(|path| path as usize), deprecated: deprecated != 0, + unstable: unstable != 0, associated_item_disambiguator, }) } @@ -1283,6 +1289,7 @@ pub(crate) fn build_index( ), aliases: item.attrs.get_doc_aliases(), is_deprecated: item.is_deprecated(tcx), + is_unstable: item.is_unstable(), }); } } @@ -1382,6 +1389,7 @@ pub(crate) fn build_index( parent: None, trait_parent: None, deprecated: false, + unstable: false, associated_item_disambiguator: None, }), crate_doc, @@ -1520,6 +1528,7 @@ pub(crate) fn build_index( module_path, exact_module_path, deprecated: item.is_deprecated, + unstable: item.is_unstable, associated_item_disambiguator: if let Some(impl_id) = item.impl_id && let Some(parent_idx) = item.parent_idx && associated_item_duplicates diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 60df4fc10b8c..555324c16f71 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -243,6 +243,7 @@ declare namespace rustdoc { parent: number?, traitParent: number?, deprecated: boolean, + unstable: boolean, associatedItemDisambiguator: string?, } @@ -292,6 +293,7 @@ declare namespace rustdoc { path: PathData?, functionData: FunctionData?, deprecated: boolean, + unstable: boolean, parent: RowParent, traitParent: RowParent, } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 9961c1447ec2..ab7350c8c0e4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1633,6 +1633,7 @@ class DocSearch { * parent, * trait_parent, * deprecated, + * unstable, * associated_item_disambiguator * @type {rustdoc.ArrayWithOptionals<[ * number, @@ -1642,6 +1643,7 @@ class DocSearch { * number, * number, * number, + * number, * ], [string]>} */ const raw = JSON.parse(encoded); @@ -1653,7 +1655,8 @@ class DocSearch { parent: raw[4] === 0 ? null : raw[4] - 1, traitParent: raw[5] === 0 ? null : raw[5] - 1, deprecated: raw[6] === 1 ? true : false, - associatedItemDisambiguator: raw.length === 7 ? null : raw[7], + unstable: raw[7] === 1 ? true : false, + associatedItemDisambiguator: raw.length === 8 ? null : raw[8], }; } @@ -1946,6 +1949,7 @@ class DocSearch { path, functionData, deprecated: entry ? entry.deprecated : false, + unstable: entry ? entry.unstable : false, parent, traitParent, }; @@ -2858,6 +2862,13 @@ class DocSearch { return a - b; } + // sort unstable items later + a = Number(aai.unstable); + b = Number(bbi.unstable); + if (a !== b) { + return a - b; + } + // sort by crate (current crate comes first) a = Number(aai.crate !== preferredCrate); b = Number(bbi.crate !== preferredCrate); diff --git a/tests/rustdoc-js-std/core-transmute.js b/tests/rustdoc-js-std/core-transmute.js index 8c9910a32d7f..b15f398902c3 100644 --- a/tests/rustdoc-js-std/core-transmute.js +++ b/tests/rustdoc-js-std/core-transmute.js @@ -3,9 +3,9 @@ const EXPECTED = [ { 'query': 'generic:T -> generic:U', 'others': [ + { 'path': 'core::mem', 'name': 'transmute' }, { 'path': 'core::intrinsics::simd', 'name': 'simd_as' }, { 'path': 'core::intrinsics::simd', 'name': 'simd_cast' }, - { 'path': 'core::mem', 'name': 'transmute' }, ], }, ]; diff --git a/tests/rustdoc-js-std/transmute-fail.js b/tests/rustdoc-js-std/transmute-fail.js index ddfb27619481..459e8dc3f002 100644 --- a/tests/rustdoc-js-std/transmute-fail.js +++ b/tests/rustdoc-js-std/transmute-fail.js @@ -6,9 +6,9 @@ const EXPECTED = [ // should-fail tag and the search query below: 'query': 'generic:T -> generic:T', 'others': [ + { 'path': 'std::mem', 'name': 'transmute' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_as' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' }, - { 'path': 'std::mem', 'name': 'transmute' }, ], }, ]; diff --git a/tests/rustdoc-js-std/transmute.js b/tests/rustdoc-js-std/transmute.js index f52e0ab14362..a85b02e29947 100644 --- a/tests/rustdoc-js-std/transmute.js +++ b/tests/rustdoc-js-std/transmute.js @@ -5,9 +5,9 @@ const EXPECTED = [ // should-fail tag and the search query below: 'query': 'generic:T -> generic:U', 'others': [ + { 'path': 'std::mem', 'name': 'transmute' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_as' }, { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' }, - { 'path': 'std::mem', 'name': 'transmute' }, ], }, ]; diff --git a/tests/rustdoc-js/sort-stability.js b/tests/rustdoc-js/sort-stability.js new file mode 100644 index 000000000000..8c095619a086 --- /dev/null +++ b/tests/rustdoc-js/sort-stability.js @@ -0,0 +1,9 @@ +const EXPECTED = [ + { + 'query': 'foo', + 'others': [ + {"path": "sort_stability::old", "name": "foo"}, + {"path": "sort_stability::new", "name": "foo"}, + ], + }, +]; diff --git a/tests/rustdoc-js/sort-stability.rs b/tests/rustdoc-js/sort-stability.rs new file mode 100644 index 000000000000..68662bb3aab6 --- /dev/null +++ b/tests/rustdoc-js/sort-stability.rs @@ -0,0 +1,16 @@ +#![feature(staged_api)] +#![stable(feature = "foo_lib", since = "1.0.0")] + +#[stable(feature = "old_foo", since = "1.0.1")] +pub mod old { + /// Old, stable foo + #[stable(feature = "old_foo", since = "1.0.1")] + pub fn foo() {} +} + +#[unstable(feature = "new_foo", issue = "none")] +pub mod new { + /// New, unstable foo + #[unstable(feature = "new_foo", issue = "none")] + pub fn foo() {} +} From cd314dead15bfd58815b32a48fae68c3bb2a56a9 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 6 Jul 2025 21:41:48 +0300 Subject: [PATCH 163/182] Remove named lifetimes in some `PartialOrd` & `PartialEq` `impl`s --- library/alloc/src/bstr.rs | 18 ++++----- library/alloc/src/string.rs | 14 +++---- library/core/src/bstr/traits.rs | 14 ++----- library/std/src/ffi/os_str.rs | 16 ++++---- library/std/src/path.rs | 58 +++++++++++++-------------- tests/ui/inference/issue-72616.stderr | 3 ++ 6 files changed, 57 insertions(+), 66 deletions(-) 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/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/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/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/path.rs b/library/std/src/path.rs index 14b41a427f1e..bf27df7b0428 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3841,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) @@ -3851,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) @@ -3859,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) @@ -3867,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) @@ -3876,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()) @@ -3893,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) @@ -3901,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()) @@ -3909,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) @@ -3918,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/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr index 6b47d5688113..8eba3216a846 100644 --- a/tests/ui/inference/issue-72616.stderr +++ b/tests/ui/inference/issue-72616.stderr @@ -8,8 +8,11 @@ LL | if String::from("a") == "a".try_into().unwrap() {} | = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the following crates: `alloc`, `std`: - impl PartialEq for String; + - impl PartialEq for String; + - impl PartialEq for String; - impl PartialEq for String; - impl PartialEq for String; + - impl PartialEq for String; help: try using a fully qualified path to specify the expected types | LL - if String::from("a") == "a".try_into().unwrap() {} From cc9e8c97168cf7f4efebccc8fbac1aa0af3c1c62 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 14 Feb 2026 00:51:10 +0100 Subject: [PATCH 164/182] c-variadic: implement `va_arg` for `wasm64` --- compiler/rustc_codegen_llvm/src/va_arg.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index a491f30fd916..460f4afea963 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1122,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, @@ -1135,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, From 8af02e230aac276d7eaa538729abca8618f02225 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 3 Feb 2026 01:08:44 +0900 Subject: [PATCH 165/182] mGCA: Validate const literal against expected type Co-authored-by: Boxy --- .../src/hir_ty_lowering/mod.rs | 27 ++++-- .../rustc_middle/src/mir/interpret/mod.rs | 38 ++++++++ compiler/rustc_middle/src/queries.rs | 2 +- compiler/rustc_middle/src/query/erase.rs | 4 + compiler/rustc_mir_build/src/thir/constant.rs | 89 ++++++++++++------- .../rustc_mir_build/src/thir/pattern/mod.rs | 17 +++- compiler/rustc_ty_utils/src/consts.rs | 5 +- .../byte-string-u8-validation.rs | 2 +- .../byte-string-u8-validation.stderr | 18 ++-- .../mismatch-raw-ptr-in-adt.stderr | 18 ++-- .../mgca/generic_const_type_mismatch.rs | 20 +++++ .../mgca/generic_const_type_mismatch.stderr | 8 ++ .../mgca/nonsensical-negated-literal.rs | 26 ++++++ .../mgca/nonsensical-negated-literal.stderr | 38 ++++++++ .../mgca/tuple_expr_type_mismatch.rs | 22 +++++ .../mgca/tuple_expr_type_mismatch.stderr | 38 ++++++++ .../mgca/type_const-mismatched-types.rs | 1 - .../mgca/type_const-mismatched-types.stderr | 10 +-- .../invalid-patterns.32bit.stderr | 52 +++++------ .../invalid-patterns.64bit.stderr | 48 +++++----- tests/ui/issues/issue-34373.rs | 1 + tests/ui/issues/issue-34373.stderr | 23 ++++- tests/ui/repeat-expr/repeat_count.stderr | 12 +-- ...ce-hir-wf-check-anon-const-issue-122989.rs | 2 + ...ir-wf-check-anon-const-issue-122989.stderr | 22 ++++- 25 files changed, 407 insertions(+), 136 deletions(-) create mode 100644 tests/ui/const-generics/mgca/generic_const_type_mismatch.rs create mode 100644 tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr create mode 100644 tests/ui/const-generics/mgca/nonsensical-negated-literal.rs create mode 100644 tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr create mode 100644 tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs create mode 100644 tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr 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 f58461e5d0e1..e22aa990c3e7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -35,7 +35,7 @@ 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::mir::interpret::{LitToConstInput, const_lit_matches_ty}; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, @@ -2803,8 +2803,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, ) -> Const<'tcx> { let tcx = self.tcx(); + if let LitKind::Err(guar) = *kind { + return ty::Const::new_error(tcx, guar); + } let input = LitToConstInput { lit: *kind, ty, neg }; - tcx.at(span).lit_to_const(input) + 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")] @@ -2833,11 +2842,15 @@ 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( diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 9762e0f21da9..f31610cd5e14 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -84,6 +84,44 @@ pub struct LitToConstInput<'tcx> { pub neg: bool, } +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, + } +} + #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct AllocId(pub NonZero); diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 771c300989f2..60a03cc66d72 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1412,7 +1412,7 @@ rustc_queries! { // FIXME get rid of this with valtrees query lit_to_const( key: LitToConstInput<'tcx> - ) -> ty::Const<'tcx> { + ) -> Option> { desc { "converting literal to const" } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 99b1f6d8c251..fe0368525e27 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -256,6 +256,10 @@ impl Erasable for Option>> { type Storage = [u8; size_of::>>>()]; } +impl Erasable for Option> { + type Storage = [u8; size_of::>>()]; +} + impl Erasable for rustc_hir::MaybeOwner<'_> { type Storage = [u8; size_of::>()]; } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 96248499044a..6b93cf8ec8f4 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -3,7 +3,7 @@ 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, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _}; use tracing::trace; use crate::builder::parse_float_into_scalar; @@ -11,11 +11,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 +32,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 +50,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/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3641561567bc..a231f1fda4b4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -8,13 +8,14 @@ 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::mir::interpret::{LitToConstInput, const_lit_matches_ty}; use rustc_middle::thir::{ Ascription, DerefPatBorrowMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; @@ -197,8 +198,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 +695,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_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index f6d08bd458bd..5029b33e5b6c 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -59,7 +59,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/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs index 703e63ae047f..063a38c8aa01 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs @@ -8,7 +8,7 @@ struct ConstBytes //~^ ERROR rustc_dump_predicates //~| NOTE Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } -//~| NOTE Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } +//~| NOTE Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } where ConstBytes: Sized; //~^ ERROR mismatched types diff --git a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr index f5f8a420a703..d4b8ac7f021d 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr @@ -1,12 +1,3 @@ -error: rustc_dump_predicates - --> $DIR/byte-string-u8-validation.rs:8:1 - | -LL | struct ConstBytes - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } - = note: Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } - error[E0308]: mismatched types --> $DIR/byte-string-u8-validation.rs:13:16 | @@ -16,6 +7,15 @@ LL | ConstBytes: Sized; = note: expected reference `&'static [*mut u8; 3]` found reference `&'static [u8; 3]` +error: rustc_dump_predicates + --> $DIR/byte-string-u8-validation.rs:8:1 + | +LL | struct ConstBytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } + = note: Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/adt_const_params/mismatch-raw-ptr-in-adt.stderr b/tests/ui/const-generics/adt_const_params/mismatch-raw-ptr-in-adt.stderr index 717e680ee536..d7eec45bae0f 100644 --- a/tests/ui/const-generics/adt_const_params/mismatch-raw-ptr-in-adt.stderr +++ b/tests/ui/const-generics/adt_const_params/mismatch-raw-ptr-in-adt.stderr @@ -7,15 +7,6 @@ LL | struct ConstBytes; = note: `*mut u8` must implement `ConstParamTy_`, but it does not = note: `[*mut u8; 3]` must implement `ConstParamTy_`, but it does not -error[E0308]: mismatched types - --> $DIR/mismatch-raw-ptr-in-adt.rs:9:46 - | -LL | let _: ConstBytes = ConstBytes::; - | ^^^^^^ expected `&[*mut u8; 3]`, found `&[u8; 3]` - | - = note: expected reference `&'static [*mut u8; 3]` - found reference `&'static [u8; 3]` - error[E0308]: mismatched types --> $DIR/mismatch-raw-ptr-in-adt.rs:9:23 | @@ -25,6 +16,15 @@ LL | let _: ConstBytes = ConstBytes::; = note: expected reference `&'static [*mut u8; 3]` found reference `&'static [u8; 3]` +error[E0308]: mismatched types + --> $DIR/mismatch-raw-ptr-in-adt.rs:9:46 + | +LL | let _: ConstBytes = ConstBytes::; + | ^^^^^^ expected `&[*mut u8; 3]`, found `&[u8; 3]` + | + = note: expected reference `&'static [*mut u8; 3]` + found reference `&'static [u8; 3]` + error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0741. diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs new file mode 100644 index 000000000000..ffde84522a26 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -0,0 +1,20 @@ +//! Regression test for +#![expect(incomplete_features)] +#![feature( + generic_const_items, + generic_const_parameter_types, + min_generic_const_args, + unsized_const_params +)] +use std::marker::ConstParamTy_; + +struct Foo { + field: T, +} + +#[type_const] +const WRAP : T = { + Foo::{field : 1} //~ ERROR: type annotations needed for the literal +}; + +fn main() {} diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr new file mode 100644 index 000000000000..10e37b327eec --- /dev/null +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr @@ -0,0 +1,8 @@ +error: type annotations needed for the literal + --> $DIR/generic_const_type_mismatch.rs:17:22 + | +LL | Foo::{field : 1} + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs new file mode 100644 index 000000000000..cd68a2c0d430 --- /dev/null +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -0,0 +1,26 @@ +#![feature(adt_const_params, min_generic_const_args)] +#![expect(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(Eq, PartialEq, ConstParamTy)] +struct Foo { + field: isize +} + +fn foo() {} + +fn main() { + foo::<{ Foo { field: -1_usize } }>(); + //~^ ERROR: type annotations needed for the literal + foo::<{ Foo { field: { -1_usize } } }>(); + //~^ ERROR: complex const arguments must be placed inside of a `const` block + foo::<{ Foo { field: -true } }>(); + //~^ ERROR: the constant `true` is not of type `isize` + foo::<{ Foo { field: { -true } } }>(); + //~^ ERROR: complex const arguments must be placed inside of a `const` block + foo::<{ Foo { field: -"<3" } }>(); + //~^ ERROR: the constant `"<3"` is not of type `isize` + foo::<{ Foo { field: { -"<3" } } }>(); + //~^ ERROR: complex const arguments must be placed inside of a `const` block +} diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr new file mode 100644 index 000000000000..43ed4b71e33e --- /dev/null +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr @@ -0,0 +1,38 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/nonsensical-negated-literal.rs:16:26 + | +LL | foo::<{ Foo { field: { -1_usize } } }>(); + | ^^^^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/nonsensical-negated-literal.rs:20:26 + | +LL | foo::<{ Foo { field: { -true } } }>(); + | ^^^^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/nonsensical-negated-literal.rs:24:26 + | +LL | foo::<{ Foo { field: { -"<3" } } }>(); + | ^^^^^^^^^ + +error: type annotations needed for the literal + --> $DIR/nonsensical-negated-literal.rs:14:26 + | +LL | foo::<{ Foo { field: -1_usize } }>(); + | ^^^^^^^^ + +error: the constant `true` is not of type `isize` + --> $DIR/nonsensical-negated-literal.rs:18:13 + | +LL | foo::<{ Foo { field: -true } }>(); + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` + +error: the constant `"<3"` is not of type `isize` + --> $DIR/nonsensical-negated-literal.rs:22:13 + | +LL | foo::<{ Foo { field: -"<3" } }>(); + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&'static str` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs new file mode 100644 index 000000000000..373cce1d6220 --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -0,0 +1,22 @@ +//! Regression test for +#![expect(incomplete_features)] +#![feature( + adt_const_params, + min_generic_const_args, + unsized_const_params +)] +fn foo() {} +fn bar() {} +fn qux() {} + +fn main() { + foo::<{ (1, true) }>(); + //~^ ERROR: type annotations needed for the literal + //~| ERROR: mismatched types: expected `i32`, found `bool` + bar::<{ (1_u32, [1, 2]) }>(); + //~^ ERROR: expected `i32`, found const array + //~| ERROR: mismatched types: expected `[u8; 2]`, found `u32` + qux::<{ (1i32, 'a') }>(); + //~^ ERROR: mismatched types: expected `char`, found `i32` + //~| ERROR: mismatched types: expected `i32`, found `char` +} diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr new file mode 100644 index 000000000000..13e2789ccb67 --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr @@ -0,0 +1,38 @@ +error: type annotations needed for the literal + --> $DIR/tuple_expr_type_mismatch.rs:13:14 + | +LL | foo::<{ (1, true) }>(); + | ^ + +error: mismatched types: expected `i32`, found `bool` + --> $DIR/tuple_expr_type_mismatch.rs:13:17 + | +LL | foo::<{ (1, true) }>(); + | ^^^^ + +error: mismatched types: expected `[u8; 2]`, found `u32` + --> $DIR/tuple_expr_type_mismatch.rs:16:14 + | +LL | bar::<{ (1_u32, [1, 2]) }>(); + | ^^^^^ + +error: expected `i32`, found const array + --> $DIR/tuple_expr_type_mismatch.rs:16:21 + | +LL | bar::<{ (1_u32, [1, 2]) }>(); + | ^^^^^^ + +error: mismatched types: expected `char`, found `i32` + --> $DIR/tuple_expr_type_mismatch.rs:19:14 + | +LL | qux::<{ (1i32, 'a') }>(); + | ^^^^ + +error: mismatched types: expected `i32`, found `char` + --> $DIR/tuple_expr_type_mismatch.rs:19:20 + | +LL | qux::<{ (1i32, 'a') }>(); + | ^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index 460c5d7b2199..deac97383b04 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -5,7 +5,6 @@ type const FREE: u32 = 5_usize; //~^ ERROR mismatched types type const FREE2: isize = FREE; -//~^ ERROR the constant `5` is not of type `isize` trait Tr { type const N: usize; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index 152dd9ec0cca..1c04ac508569 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -1,9 +1,3 @@ -error: the constant `5` is not of type `isize` - --> $DIR/type_const-mismatched-types.rs:7:1 - | -LL | type const FREE2: isize = FREE; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` - error[E0308]: mismatched types --> $DIR/type_const-mismatched-types.rs:4:24 | @@ -17,11 +11,11 @@ LL + type const FREE: u32 = 5_u32; | error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:15:27 + --> $DIR/type_const-mismatched-types.rs:18:22 | LL | type const N: usize = false; | ^^^^^ expected `usize`, found `bool` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr index cc6a813b747d..b85856db9287 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -1,4 +1,28 @@ -error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:21 + | +LL | get_flag::(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:35:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:35:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: reading memory at ALLOC6[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:40:32 | LL | get_flag::(); @@ -30,7 +54,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character 42 │ B } -error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory +error[E0080]: reading memory at ALLOC12[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:44:58 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); @@ -40,30 +64,6 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character ff __ __ __ │ .░░░ } -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:31:21 - | -LL | get_flag::(); - | ^^^^ expected `char`, found `u8` - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:33:14 - | -LL | get_flag::<7, 'c'>(); - | ^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:35:14 - | -LL | get_flag::<42, 0x5ad>(); - | ^^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:35:18 - | -LL | get_flag::<42, 0x5ad>(); - | ^^^^^ expected `char`, found `u8` - error: aborting due to 8 previous errors Some errors have detailed explanations: E0080, E0308. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr index cc6a813b747d..df7c2a0a8629 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -1,3 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:21 + | +LL | get_flag::(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:35:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:35:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:40:32 | @@ -40,30 +64,6 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character ff __ __ __ │ .░░░ } -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:31:21 - | -LL | get_flag::(); - | ^^^^ expected `char`, found `u8` - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:33:14 - | -LL | get_flag::<7, 'c'>(); - | ^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:35:14 - | -LL | get_flag::<42, 0x5ad>(); - | ^^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/invalid-patterns.rs:35:18 - | -LL | get_flag::<42, 0x5ad>(); - | ^^^^^ expected `char`, found `u8` - error: aborting due to 8 previous errors Some errors have detailed explanations: E0080, E0308. diff --git a/tests/ui/issues/issue-34373.rs b/tests/ui/issues/issue-34373.rs index 5b05811a4eb3..019cab42c643 100644 --- a/tests/ui/issues/issue-34373.rs +++ b/tests/ui/issues/issue-34373.rs @@ -6,6 +6,7 @@ trait Trait { pub struct Foo>>; //~ ERROR cycle detected //~^ ERROR `T` is never used +//~| ERROR cycle detected type DefaultFoo = Foo; fn main() { diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 03d771931341..49365a701cee 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -5,7 +5,26 @@ LL | pub struct Foo>>; | ^^^^^^^^^^ | note: ...which requires expanding type alias `DefaultFoo`... - --> $DIR/issue-34373.rs:9:19 + --> $DIR/issue-34373.rs:10:1 + | +LL | type DefaultFoo = Foo; + | ^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `Foo::T`, completing the cycle +note: cycle used when checking that `Foo` is well-formed + --> $DIR/issue-34373.rs:7:1 + | +LL | pub struct Foo>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `Foo::T` + --> $DIR/issue-34373.rs:7:34 + | +LL | pub struct Foo>>; + | ^^^^^^^^^^ + | +note: ...which requires expanding type alias `DefaultFoo`... + --> $DIR/issue-34373.rs:10:19 | LL | type DefaultFoo = Foo; | ^^^ @@ -26,7 +45,7 @@ LL | pub struct Foo>>; = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0391, E0392. For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr index cf94ad41ee36..8d8702e981e6 100644 --- a/tests/ui/repeat-expr/repeat_count.stderr +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -16,12 +16,6 @@ error[E0308]: mismatched types LL | let b = [0; ()]; | ^^ expected `usize`, found `()` -error[E0308]: mismatched types - --> $DIR/repeat_count.rs:33:17 - | -LL | let g = [0; G { g: () }]; - | ^^^^^^^^^^^ expected `usize`, found `G` - error[E0308]: mismatched types --> $DIR/repeat_count.rs:12:17 | @@ -68,6 +62,12 @@ LL - let f = [0; 4u8]; LL + let f = [0; 4usize]; | +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:33:17 + | +LL | let g = [0; G { g: () }]; + | ^^^^^^^^^^^ expected `usize`, found `G` + error: aborting due to 9 previous errors Some errors have detailed explanations: E0308, E0435. diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index f2b9f037ea5f..13d7a800c51f 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -4,11 +4,13 @@ trait Foo> { //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| ERROR cycle detected when computing type of `Foo::N` + //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter fn func() {} } trait Bar> {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index 4024f57af4ff..f9a855d3b93b 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -13,7 +13,7 @@ LL | trait Foo> { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 | LL | trait Bar> {} | ^^^^^^ @@ -32,7 +32,7 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^ | note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:10:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 | LL | trait Bar> {} | ^^^^^^^^^^^^^^^ @@ -44,6 +44,22 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 1 previous error; 2 warnings emitted +error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:3:20 + | +LL | trait Foo> { + | ^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 + | +LL | trait Bar> {} + | ^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: aborting due to 3 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0391`. From b4ee9953d8dd037fcfce60a0d10c0da90ec81650 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 10 Feb 2026 16:01:13 +0000 Subject: [PATCH 166/182] modify error comment and bless test, delete tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs --- tests/crashes/133966.rs | 3 -- .../byte-string-u8-validation.rs | 2 + .../byte-string-u8-validation.stderr | 2 +- .../generic_const_exprs/issue-105257.rs | 6 +-- .../generic_const_exprs/lit_type_mismatch.rs | 22 ----------- .../lit_type_mismatch.stderr | 21 ---------- .../mgca/generic_const_type_mismatch.rs | 7 ++-- .../mgca/generic_const_type_mismatch.stderr | 6 +-- .../mgca/tuple_expr_type_mismatch.rs | 6 +-- .../mgca/tuple_expr_type_mismatch.stderr | 28 ++++--------- .../mgca/type_const-mismatched-types.rs | 4 +- .../mgca/type_const-mismatched-types.stderr | 26 +++++++++---- .../invalid-patterns.32bit.stderr | 4 +- .../type-dependent/type-mismatch.full.stderr | 14 ++++++- .../type-dependent/type-mismatch.min.stderr | 14 ++++++- .../type-dependent/type-mismatch.rs | 3 +- .../const-eval/array-len-mismatch-type.rs | 8 ++++ .../const-eval/array-len-mismatch-type.stderr | 39 +++++++++++++++++++ tests/ui/issues/issue-34373.rs | 6 +-- tests/ui/issues/issue-34373.stderr | 21 +--------- tests/ui/repeat-expr/repeat_count.rs | 19 +++++---- tests/ui/repeat-expr/repeat_count.stderr | 36 ++++++++++------- 22 files changed, 159 insertions(+), 138 deletions(-) delete mode 100644 tests/crashes/133966.rs delete mode 100644 tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs delete mode 100644 tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.stderr create mode 100644 tests/ui/consts/const-eval/array-len-mismatch-type.rs create mode 100644 tests/ui/consts/const-eval/array-len-mismatch-type.stderr diff --git a/tests/crashes/133966.rs b/tests/crashes/133966.rs deleted file mode 100644 index 25a881ae99b4..000000000000 --- a/tests/crashes/133966.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ known-bug: #133966 -pub struct Data([[&'static str]; 5_i32]); -const _: &'static Data = unsafe { &*(&[] as *const Data) }; diff --git a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs index 063a38c8aa01..d49fb49d253c 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs @@ -9,10 +9,12 @@ struct ConstBytes //~^ ERROR rustc_dump_predicates //~| NOTE Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } //~| NOTE Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } + where ConstBytes: Sized; //~^ ERROR mismatched types //~| NOTE expected `&[*mut u8; 3]`, found `&[u8; 3]` //~| NOTE expected reference `&'static [*mut u8; 3]` +//~| NOTE found reference `&'static [u8; 3]` fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr index d4b8ac7f021d..1273a74102a2 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/byte-string-u8-validation.rs:13:16 + --> $DIR/byte-string-u8-validation.rs:14:16 | LL | ConstBytes: Sized; | ^^^^^^ expected `&[*mut u8; 3]`, found `&[u8; 3]` diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.rs b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs index 85a28f2b3303..947410cbe0dc 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-105257.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs @@ -2,9 +2,9 @@ #![expect(incomplete_features)] trait Trait { - fn fnc(&self) {} //~ERROR defaults for generic parameters are not allowed here - //~^ ERROR: mismatched types - fn foo() }>(&self) {} //~ERROR defaults for generic parameters are not allowed here + fn fnc(&self) {} //~ ERROR defaults for generic parameters are not allowed here + //~^ ERROR mismatched types + fn foo() }>(&self) {} //~ ERROR defaults for generic parameters are not allowed here } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs deleted file mode 100644 index 1ed0965e1bde..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! ICE regression test for #114317 and #126182 -//! Type mismatches of literals cause errors int typeck, -//! but those errors cannot be propagated to the various -//! `lit_to_const` call sites. Now `lit_to_const` just delays -//! a bug and produces an error constant on its own. - -#![feature(adt_const_params)] -#![feature(generic_const_exprs)] -#![allow(incomplete_features)] - -struct A(C); -//~^ ERROR: generic parameters with a default must be trailing -//~| ERROR: mismatched types - -struct Cond; - -struct Thing>(T); -//~^ ERROR: mismatched types - -impl Thing {} - -fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.stderr deleted file mode 100644 index e4613e498b27..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/lit_type_mismatch.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: generic parameters with a default must be trailing - --> $DIR/lit_type_mismatch.rs:11:16 - | -LL | struct A(C); - | ^ - -error[E0308]: mismatched types - --> $DIR/lit_type_mismatch.rs:11:24 - | -LL | struct A(C); - | ^ expected `()`, found integer - -error[E0308]: mismatched types - --> $DIR/lit_type_mismatch.rs:17:23 - | -LL | struct Thing>(T); - | ^ expected `bool`, found integer - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index ffde84522a26..948b8ce72148 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -1,6 +1,7 @@ //! Regression test for #![expect(incomplete_features)] #![feature( + adt_const_params, generic_const_items, generic_const_parameter_types, min_generic_const_args, @@ -12,9 +13,7 @@ struct Foo { field: T, } -#[type_const] -const WRAP : T = { - Foo::{field : 1} //~ ERROR: type annotations needed for the literal -}; +type const WRAP : T = Foo::{field : 1}; +//~^ ERROR: type annotations needed for the literal fn main() {} diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr index 10e37b327eec..fdb0995bff5d 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr @@ -1,8 +1,8 @@ error: type annotations needed for the literal - --> $DIR/generic_const_type_mismatch.rs:17:22 + --> $DIR/generic_const_type_mismatch.rs:16:59 | -LL | Foo::{field : 1} - | ^ +LL | type const WRAP : T = Foo::{field : 1}; + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs index 373cce1d6220..4bf62b3a3070 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -12,11 +12,9 @@ fn qux() {} fn main() { foo::<{ (1, true) }>(); //~^ ERROR: type annotations needed for the literal - //~| ERROR: mismatched types: expected `i32`, found `bool` bar::<{ (1_u32, [1, 2]) }>(); //~^ ERROR: expected `i32`, found const array - //~| ERROR: mismatched types: expected `[u8; 2]`, found `u32` qux::<{ (1i32, 'a') }>(); - //~^ ERROR: mismatched types: expected `char`, found `i32` - //~| ERROR: mismatched types: expected `i32`, found `char` + //~^ ERROR: the constant `1` is not of type `char` + //~| ERROR: the constant `'a'` is not of type `i32 } diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr index 13e2789ccb67..4136c7337cd4 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.stderr @@ -4,35 +4,23 @@ error: type annotations needed for the literal LL | foo::<{ (1, true) }>(); | ^ -error: mismatched types: expected `i32`, found `bool` - --> $DIR/tuple_expr_type_mismatch.rs:13:17 - | -LL | foo::<{ (1, true) }>(); - | ^^^^ - -error: mismatched types: expected `[u8; 2]`, found `u32` - --> $DIR/tuple_expr_type_mismatch.rs:16:14 - | -LL | bar::<{ (1_u32, [1, 2]) }>(); - | ^^^^^ - error: expected `i32`, found const array - --> $DIR/tuple_expr_type_mismatch.rs:16:21 + --> $DIR/tuple_expr_type_mismatch.rs:15:21 | LL | bar::<{ (1_u32, [1, 2]) }>(); | ^^^^^^ -error: mismatched types: expected `char`, found `i32` - --> $DIR/tuple_expr_type_mismatch.rs:19:14 +error: the constant `1` is not of type `char` + --> $DIR/tuple_expr_type_mismatch.rs:17:13 | LL | qux::<{ (1i32, 'a') }>(); - | ^^^^ + | ^^^^^^^^^^^ expected `char`, found `i32` -error: mismatched types: expected `i32`, found `char` - --> $DIR/tuple_expr_type_mismatch.rs:19:20 +error: the constant `'a'` is not of type `i32` + --> $DIR/tuple_expr_type_mismatch.rs:17:13 | LL | qux::<{ (1i32, 'a') }>(); - | ^^^ + | ^^^^^^^^^^^ expected `i32`, found `char` -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index deac97383b04..c73785f9a3e3 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -2,9 +2,11 @@ #![feature(min_generic_const_args)] type const FREE: u32 = 5_usize; -//~^ ERROR mismatched types +//~^ ERROR the constant `5` is not of type `u32` +//~| ERROR mismatched types type const FREE2: isize = FREE; +//~^ ERROR the constant `5` is not of type `isize` trait Tr { type const N: usize; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index 1c04ac508569..f7f64c535f60 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -1,3 +1,21 @@ +error: the constant `5` is not of type `u32` + --> $DIR/type_const-mismatched-types.rs:4:1 + | +LL | type const FREE: u32 = 5_usize; + | ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` + +error: the constant `5` is not of type `isize` + --> $DIR/type_const-mismatched-types.rs:8:1 + | +LL | type const FREE2: isize = FREE; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_const-mismatched-types.rs:16:27 + | +LL | type const N: usize = false; + | ^^^^^ expected `usize`, found `bool` + error[E0308]: mismatched types --> $DIR/type_const-mismatched-types.rs:4:24 | @@ -10,12 +28,6 @@ LL - type const FREE: u32 = 5_usize; LL + type const FREE: u32 = 5_u32; | -error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:18:22 - | -LL | type const N: usize = false; - | ^^^^^ expected `usize`, found `bool` - -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr index b85856db9287..df7c2a0a8629 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -22,7 +22,7 @@ error[E0308]: mismatched types LL | get_flag::<42, 0x5ad>(); | ^^^^^ expected `char`, found `u8` -error[E0080]: reading memory at ALLOC6[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:40:32 | LL | get_flag::(); @@ -54,7 +54,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character 42 │ B } -error[E0080]: reading memory at ALLOC12[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:44:58 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr index 95d20de1b432..9de140dab9eb 100644 --- a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr +++ b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -1,3 +1,15 @@ +error: the constant `1` is not of type `u8` + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +note: required by a const generic parameter in `R::method` + --> $DIR/type-mismatch.rs:5:15 + | +LL | fn method(&self) -> u8 { N } + | ^^^^^^^^^^^ required by this const generic parameter in `R::method` + error[E0308]: mismatched types --> $DIR/type-mismatch.rs:8:27 | @@ -10,6 +22,6 @@ LL - assert_eq!(R.method::<1u16>(), 1); LL + assert_eq!(R.method::<1u8>(), 1); | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr index 95d20de1b432..9de140dab9eb 100644 --- a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr +++ b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -1,3 +1,15 @@ +error: the constant `1` is not of type `u8` + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +note: required by a const generic parameter in `R::method` + --> $DIR/type-mismatch.rs:5:15 + | +LL | fn method(&self) -> u8 { N } + | ^^^^^^^^^^^ required by this const generic parameter in `R::method` + error[E0308]: mismatched types --> $DIR/type-mismatch.rs:8:27 | @@ -10,6 +22,6 @@ LL - assert_eq!(R.method::<1u16>(), 1); LL + assert_eq!(R.method::<1u8>(), 1); | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.rs b/tests/ui/const-generics/type-dependent/type-mismatch.rs index 6ed5fdca30ae..fc7ae994184b 100644 --- a/tests/ui/const-generics/type-dependent/type-mismatch.rs +++ b/tests/ui/const-generics/type-dependent/type-mismatch.rs @@ -6,5 +6,6 @@ impl R { } fn main() { assert_eq!(R.method::<1u16>(), 1); - //~^ ERROR mismatched types + //~^ ERROR the constant `1` is not of type `u8` + //~| ERROR mismatched types } diff --git a/tests/ui/consts/const-eval/array-len-mismatch-type.rs b/tests/ui/consts/const-eval/array-len-mismatch-type.rs new file mode 100644 index 000000000000..463572c13e10 --- /dev/null +++ b/tests/ui/consts/const-eval/array-len-mismatch-type.rs @@ -0,0 +1,8 @@ +//! Regression test for +pub struct Data([[&'static str]; 5_i32]); +//~^ ERROR the constant `5` is not of type `usize` +//~| ERROR the size for values of type `[&'static str]` cannot be known at compilation time +//~| ERROR mismatched types +const _: &'static Data = unsafe { &*(&[] as *const Data) }; +//~^ ERROR the type `[[&str]; 5]` has an unknown layout +fn main() {} diff --git a/tests/ui/consts/const-eval/array-len-mismatch-type.stderr b/tests/ui/consts/const-eval/array-len-mismatch-type.stderr new file mode 100644 index 000000000000..0f03006f0032 --- /dev/null +++ b/tests/ui/consts/const-eval/array-len-mismatch-type.stderr @@ -0,0 +1,39 @@ +error: the constant `5` is not of type `usize` + --> $DIR/array-len-mismatch-type.rs:2:17 + | +LL | pub struct Data([[&'static str]; 5_i32]); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i32` + | + = note: the length of array `[[&'static str]; 5]` must be type `usize` + +error[E0277]: the size for values of type `[&'static str]` cannot be known at compilation time + --> $DIR/array-len-mismatch-type.rs:2:17 + | +LL | pub struct Data([[&'static str]; 5_i32]); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[&'static str]` + = note: slice and array elements must have `Sized` type + +error[E0080]: the type `[[&str]; 5]` has an unknown layout + --> $DIR/array-len-mismatch-type.rs:6:39 + | +LL | const _: &'static Data = unsafe { &*(&[] as *const Data) }; + | ^^ evaluation of `_` failed here + +error[E0308]: mismatched types + --> $DIR/array-len-mismatch-type.rs:2:34 + | +LL | pub struct Data([[&'static str]; 5_i32]); + | ^^^^^ expected `usize`, found `i32` + | +help: change the type of the numeric literal from `i32` to `usize` + | +LL - pub struct Data([[&'static str]; 5_i32]); +LL + pub struct Data([[&'static str]; 5_usize]); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/issues/issue-34373.rs b/tests/ui/issues/issue-34373.rs index 019cab42c643..765bfc20a451 100644 --- a/tests/ui/issues/issue-34373.rs +++ b/tests/ui/issues/issue-34373.rs @@ -4,9 +4,9 @@ trait Trait { fn foo(_: T) {} } -pub struct Foo>>; //~ ERROR cycle detected -//~^ ERROR `T` is never used -//~| ERROR cycle detected +pub struct Foo>>; +//~^ ERROR cycle detected when computing type of `Foo::T` +//~| ERROR type parameter `T` is never used type DefaultFoo = Foo; fn main() { diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 49365a701cee..6d68de8fb3b8 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -1,22 +1,3 @@ -error[E0391]: cycle detected when computing type of `Foo::T` - --> $DIR/issue-34373.rs:7:34 - | -LL | pub struct Foo>>; - | ^^^^^^^^^^ - | -note: ...which requires expanding type alias `DefaultFoo`... - --> $DIR/issue-34373.rs:10:1 - | -LL | type DefaultFoo = Foo; - | ^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::T`, completing the cycle -note: cycle used when checking that `Foo` is well-formed - --> $DIR/issue-34373.rs:7:1 - | -LL | pub struct Foo>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - error[E0391]: cycle detected when computing type of `Foo::T` --> $DIR/issue-34373.rs:7:34 | @@ -45,7 +26,7 @@ LL | pub struct Foo>>; = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0391, E0392. For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/repeat-expr/repeat_count.rs b/tests/ui/repeat-expr/repeat_count.rs index 2febcdc07c2a..b1e3a9d8cb3b 100644 --- a/tests/ui/repeat-expr/repeat_count.rs +++ b/tests/ui/repeat-expr/repeat_count.rs @@ -21,16 +21,21 @@ fn main() { let f = [0; -4_isize]; //~^ ERROR mismatched types //~| NOTE expected `usize`, found `isize` - let f = [0_usize; -1_isize]; + //~| NOTE `-4_isize` cannot fit into type `usize` + let g = [0_usize; -1_isize]; //~^ ERROR mismatched types //~| NOTE expected `usize`, found `isize` - let f = [0; 4u8]; - //~^ ERROR mismatched types + //~| NOTE `-1_isize` cannot fit into type `usize` + let h = [0; 4u8]; + //~^ ERROR the constant `4` is not of type `usize` //~| NOTE expected `usize`, found `u8` - struct G { - g: (), + //~| NOTE the length of array `[{integer}; 4]` must be type `usize` + //~| ERROR mismatched types + //~| NOTE expected `usize`, found `u8` + struct I { + i: (), } - let g = [0; G { g: () }]; + let i = [0; I { i: () }]; //~^ ERROR mismatched types - //~| NOTE expected `usize`, found `G` + //~| NOTE expected `usize`, found `I` } diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr index 8d8702e981e6..5da9dbe03209 100644 --- a/tests/ui/repeat-expr/repeat_count.stderr +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -43,32 +43,40 @@ LL | let f = [0; -4_isize]; = note: `-4_isize` cannot fit into type `usize` error[E0308]: mismatched types - --> $DIR/repeat_count.rs:24:23 + --> $DIR/repeat_count.rs:25:23 | -LL | let f = [0_usize; -1_isize]; +LL | let g = [0_usize; -1_isize]; | ^^^^^^^^ expected `usize`, found `isize` | = note: `-1_isize` cannot fit into type `usize` -error[E0308]: mismatched types - --> $DIR/repeat_count.rs:27:17 +error: the constant `4` is not of type `usize` + --> $DIR/repeat_count.rs:29:13 | -LL | let f = [0; 4u8]; +LL | let h = [0; 4u8]; + | ^^^^^^^^ expected `usize`, found `u8` + | + = note: the length of array `[{integer}; 4]` must be type `usize` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:38:17 + | +LL | let i = [0; I { i: () }]; + | ^^^^^^^^^^^ expected `usize`, found `I` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:29:17 + | +LL | let h = [0; 4u8]; | ^^^ expected `usize`, found `u8` | help: change the type of the numeric literal from `u8` to `usize` | -LL - let f = [0; 4u8]; -LL + let f = [0; 4usize]; +LL - let h = [0; 4u8]; +LL + let h = [0; 4usize]; | -error[E0308]: mismatched types - --> $DIR/repeat_count.rs:33:17 - | -LL | let g = [0; G { g: () }]; - | ^^^^^^^^^^^ expected `usize`, found `G` - -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0308, E0435. For more information about an error, try `rustc --explain E0308`. From 01d48c62a5e6219f2893ac8eed40cf8ae38a7282 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Thu, 12 Feb 2026 01:50:19 +0000 Subject: [PATCH 167/182] Move LitToConstInput into ty::consts Relocate LitToConstInput and const_lit_matches_ty from mir::interpret to ty::consts::lit --- .../src/hir_ty_lowering/mod.rs | 5 +- .../rustc_middle/src/mir/interpret/mod.rs | 51 +---------------- compiler/rustc_middle/src/queries.rs | 6 +- compiler/rustc_middle/src/query/erase.rs | 2 +- compiler/rustc_middle/src/query/keys.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 2 + compiler/rustc_middle/src/ty/consts/lit.rs | 55 +++++++++++++++++++ compiler/rustc_middle/src/ty/mod.rs | 5 +- .../src/builder/expr/as_constant.rs | 8 +-- compiler/rustc_mir_build/src/thir/constant.rs | 3 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 5 +- compiler/rustc_ty_utils/src/consts.rs | 3 +- 12 files changed, 77 insertions(+), 70 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/consts/lit.rs 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 e22aa990c3e7..a897fa8a0dd5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -35,11 +35,10 @@ 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, const_lit_matches_ty}; 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; diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index f31610cd5e14..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,55 +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, -} - -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, - } -} - #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct AllocId(pub NonZero); diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 60a03cc66d72..68971df9eb8e 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -112,7 +112,7 @@ use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, use crate::middle::stability::DeprecationEntry; use crate::mir::interpret::{ EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, - EvalToValTreeResult, GlobalId, LitToConstInput, + EvalToValTreeResult, GlobalId, }; use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, @@ -135,8 +135,8 @@ 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, + self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput, + SizedTraitKind, Ty, TyCtxt, TyCtxtFeed, }; use crate::{dep_graph, mir, thir}; diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index fe0368525e27..4d4833b4943e 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -445,7 +445,6 @@ impl_erasable_for_single_lifetime_types! { 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, @@ -470,6 +469,7 @@ impl_erasable_for_single_lifetime_types! { 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/keys.rs b/compiler/rustc_middle/src/query/keys.rs index cccb7d51bd3e..2a1fe739134b 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -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/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 3e17943a8857..aade274bfc98 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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::*; 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/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 37871aad4a77..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::{ - 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, 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/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 6b93cf8ec8f4..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, Ty, TyCtxt, TypeVisitableExt as _}; +use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _}; use tracing::trace; use crate::builder::parse_float_into_scalar; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index a231f1fda4b4..acf20cb092e2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -15,13 +15,14 @@ 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, const_lit_matches_ty}; 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}; diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 5029b33e5b6c..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; From 1ac199af0a923580b97db6fdf6e798b37f97d43f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 13:09:27 +1100 Subject: [PATCH 168/182] Move `QueryState`/`ActiveKeyStatus`. From `rustc_query_state` to `rustc_middle`. --- compiler/rustc_middle/src/query/mod.rs | 6 ++-- compiler/rustc_middle/src/query/plumbing.rs | 35 ++++++++++++++++++- compiler/rustc_query_impl/src/execution.rs | 5 +-- compiler/rustc_query_impl/src/lib.rs | 8 ++--- .../rustc_query_system/src/query/plumbing.rs | 35 +------------------ 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 62d5c1f9dd20..eea809db1230 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,8 +1,10 @@ use rustc_hir::def_id::LocalDefId; -pub use rustc_query_system::query::{QueryMode, QueryState}; +pub use rustc_query_system::query::QueryMode; pub use self::keys::{AsLocalKey, Key, LocalCrate}; -pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; +pub use self::plumbing::{ + ActiveKeyStatus, IntoQueryParam, QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, +}; pub use crate::queries::Providers; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 9a709d2c43c8..2b093b4be033 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -1,6 +1,8 @@ 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; @@ -8,7 +10,7 @@ use rustc_macros::HashStable; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_query_system::ich::StableHashingContext; pub(crate) use rustc_query_system::query::QueryJobId; -use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache}; +use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache, QueryJob}; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -20,6 +22,37 @@ use crate::queries::{ use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; 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, +} + pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 50fb4f29ed71..7e1c2faa18df 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -6,11 +6,12 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_middle::dep_graph::DepsType; +use rustc_middle::query::{ActiveKeyStatus, QueryState}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, - QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, incremental_verify_ich, + CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryMode, + QueryStackDeferred, QueryStackFrame, incremental_verify_ich, }; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index feeb072f027a..0ec4d94bcf72 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -18,12 +18,12 @@ use rustc_middle::queries::{ }; use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use rustc_middle::query::plumbing::{HashResult, QuerySystem, QuerySystemFns, QueryVTable}; +use rustc_middle::query::plumbing::{ + HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, +}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::query::{ - CycleError, CycleErrorHandling, QueryCache, QueryMode, QueryState, -}; +use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache, QueryMode}; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index d7a24d613583..0cdc94cf4d88 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,48 +2,15 @@ use std::cell::Cell; use std::fmt::Debug; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::hash_table::HashTable; -use rustc_data_structures::sharded::Sharded; use rustc_span::Span; use tracing::instrument; use super::{QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::{DepContext, DepGraphData}; use crate::ich::StableHashingContext; -use crate::query::job::{QueryInfo, QueryJob}; +use crate::query::job::QueryInfo; use crate::query::{QueryStackFrame, SerializedDepNodeIndex}; -/// 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)>>, -} - -/// 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, -} - -impl<'tcx, K> Default for QueryState<'tcx, K> { - fn default() -> QueryState<'tcx, K> { - QueryState { active: Default::default() } - } -} - #[derive(Clone, Debug)] pub struct CycleError { /// The query and related span that uses the cycle. From 8b0dc1ece0a6fd515b7bdb5c3d28f2fdd54bef61 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 13:16:31 +1100 Subject: [PATCH 169/182] Move `rustc_query_system::query::job` to `rustc_middle`. This includes the types `QueryInfo`, `QueryJob`, `QueryJobId`, `QueryWaiter`, `QueryLatch`, and `QueryLatchInfo`. `CycleError` and `QueryStack*` had to come along too, due to type interdependencies. The `QueryStack*` types are put into a new submodule `rustc_middle::query::stack`. --- Cargo.lock | 4 +- compiler/rustc_middle/Cargo.toml | 1 + .../src/query/job.rs | 15 ++- compiler/rustc_middle/src/query/mod.rs | 7 +- compiler/rustc_middle/src/query/plumbing.rs | 21 +++- compiler/rustc_middle/src/query/stack.rs | 112 ++++++++++++++++++ compiler/rustc_middle/src/ty/context/tls.rs | 2 +- compiler/rustc_query_impl/src/execution.rs | 10 +- compiler/rustc_query_impl/src/job.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 4 +- compiler/rustc_query_impl/src/plumbing.rs | 9 +- compiler/rustc_query_impl/src/values.rs | 2 +- compiler/rustc_query_system/Cargo.toml | 3 - compiler/rustc_query_system/src/query/mod.rs | 112 +----------------- .../rustc_query_system/src/query/plumbing.rs | 21 +--- 15 files changed, 163 insertions(+), 162 deletions(-) rename compiler/{rustc_query_system => rustc_middle}/src/query/job.rs (92%) create mode 100644 compiler/rustc_middle/src/query/stack.rs diff --git a/Cargo.lock b/Cargo.lock index 4f98a3facf9b..9b8506c25473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4226,6 +4226,7 @@ dependencies = [ "bitflags", "either", "gsgdt", + "parking_lot", "polonius-engine", "rustc_abi", "rustc_apfloat", @@ -4512,20 +4513,17 @@ dependencies = [ name = "rustc_query_system" version = "0.0.0" dependencies = [ - "parking_lot", "rustc_abi", "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_hashes", "rustc_hir", "rustc_index", "rustc_macros", "rustc_serialize", "rustc_session", "rustc_span", - "rustc_thread_pool", "smallvec", "tracing", ] diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index f9d5e7c02789..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" diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_middle/src/query/job.rs similarity index 92% rename from compiler/rustc_query_system/src/query/job.rs rename to compiler/rustc_middle/src/query/job.rs index 7349fe223ef9..f1a2b3a34d0e 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_middle/src/query/job.rs @@ -6,9 +6,9 @@ use std::sync::Arc; use parking_lot::{Condvar, Mutex}; use rustc_span::Span; -use super::{QueryStackDeferred, QueryStackFrameExtra}; use crate::query::plumbing::CycleError; -use crate::query::{QueryContext, QueryStackFrame}; +use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; +use crate::ty::TyCtxt; /// Represents a span and a query key. #[derive(Clone, Debug)] @@ -98,13 +98,13 @@ impl<'tcx> QueryLatch<'tcx> { /// Awaits for the query job to complete. pub fn wait_on( &self, - qcx: impl QueryContext<'tcx>, + 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(qcx, &waiter); + 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 @@ -116,7 +116,7 @@ impl<'tcx> QueryLatch<'tcx> { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, qcx: impl QueryContext<'tcx>, waiter: &Arc>) { + 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 @@ -129,12 +129,11 @@ impl<'tcx> QueryLatch<'tcx> { // 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(); + tcx.jobserver_proxy.release_thread(); waiter.condvar.wait(&mut info); // Release the lock before we potentially block in `acquire_thread` drop(info); - proxy.acquire_thread(); + tcx.jobserver_proxy.acquire_thread(); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index eea809db1230..7083f160bd77 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,21 +1,26 @@ use rustc_hir::def_id::LocalDefId; pub use rustc_query_system::query::QueryMode; +pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{ - ActiveKeyStatus, IntoQueryParam, QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, + ActiveKeyStatus, CycleError, IntoQueryParam, QueryState, TyCtxtAt, TyCtxtEnsureDone, + TyCtxtEnsureOk, }; +pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; pub use crate::queries::Providers; use crate::ty::TyCtxt; pub(crate) mod arena_cached; 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; pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { let def_id = def_id.into(); diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 2b093b4be033..f2021978aad7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -9,8 +9,7 @@ use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_query_system::ich::StableHashingContext; -pub(crate) use rustc_query_system::query::QueryJobId; -use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache, QueryJob}; +use rustc_query_system::query::{CycleErrorHandling, QueryCache}; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -20,6 +19,8 @@ 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::{QueryInfo, QueryJob}; use crate::ty::TyCtxt; /// For a particular query, keeps track of "active" keys, i.e. keys whose @@ -67,6 +68,22 @@ pub type IsLoadableFromDiskFn<'tcx, Key> = 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(), + } + } +} + /// Stores function pointers and other metadata for a particular query. /// /// Used indirectly by query plumbing in `rustc_query_system` via a trait, 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_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index a06f92792820..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 diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 7e1c2faa18df..38150c154e08 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -6,12 +6,14 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_middle::dep_graph::DepsType; -use rustc_middle::query::{ActiveKeyStatus, QueryState}; +use rustc_middle::query::{ + ActiveKeyStatus, CycleError, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, + QueryStackFrame, QueryState, +}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ - CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryMode, - QueryStackDeferred, QueryStackFrame, incremental_verify_ich, + CycleErrorHandling, QueryCache, QueryMode, incremental_verify_ich, }; use rustc_span::{DUMMY_SP, Span}; @@ -239,7 +241,7 @@ fn wait_for_query<'tcx, C: QueryCache, const FLAGS: QueryFlags>( // 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(()) => { diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index 19b8245b97e7..8e554d4ed4e6 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Diag, DiagCtxtHandle}; use rustc_hir::def::DefKind; -use rustc_query_system::query::{ +use rustc_middle::query::{ CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, QueryWaiter, }; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 0ec4d94bcf72..02a86b5a4c65 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -16,14 +16,14 @@ use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex}; use rustc_middle::queries::{ self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, }; -use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{ HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, }; +use rustc_middle::query::{AsLocalKey, CycleError}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache, QueryMode}; +use rustc_query_system::query::{CycleErrorHandling, QueryCache, QueryMode}; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 12cef31f58bb..1d549c6ecc69 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -18,20 +18,19 @@ use rustc_middle::dep_graph::DepKindVTable; use rustc_middle::dep_graph::{ self, DepContext, DepNode, DepNodeIndex, DepsType, 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, 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::{DepNodeKey, HasDepContext}; -use rustc_query_system::query::{ - QueryCache, QueryContext, QueryJobId, QuerySideEffect, QueryStackDeferred, QueryStackFrame, - QueryStackFrameExtra, -}; +use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffect}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; diff --git a/compiler/rustc_query_impl/src/values.rs b/compiler/rustc_query_impl/src/values.rs index 783e7a10d12a..67bc6893a320 100644 --- a/compiler/rustc_query_impl/src/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -8,10 +8,10 @@ use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; 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_query_system::query::CycleError; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 761a299eab77..d2a58b341048 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -5,20 +5,17 @@ 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_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 diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index c33af941f802..8b84c1023b01 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -1,26 +1,16 @@ 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, QueryCacheKey, SingleCache, VecCache, }; -pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::plumbing::*; -use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; +use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; mod caches; -mod job; mod plumbing; /// How a particular query deals with query cycle errors. @@ -35,106 +25,6 @@ pub enum CycleErrorHandling { 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. - 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 } - } - - 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") - } -} - /// Tracks 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 0cdc94cf4d88..d53b4a430b79 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,30 +2,11 @@ use std::cell::Cell; use std::fmt::Debug; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_span::Span; use tracing::instrument; -use super::{QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::{DepContext, DepGraphData}; use crate::ich::StableHashingContext; -use crate::query::job::QueryInfo; -use crate::query::{QueryStackFrame, SerializedDepNodeIndex}; - -#[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(), - } - } -} +use crate::query::SerializedDepNodeIndex; #[inline] #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] From 940f30792c614ee18c551c7321470c8f60ae6422 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 14:25:35 +1100 Subject: [PATCH 170/182] Move `rustc_query_system::query::caches` to `rustc_middle::query`. This one is straightforward. --- compiler/rustc_middle/src/lib.rs | 1 + .../src/query/caches.rs | 2 +- compiler/rustc_middle/src/query/inner.rs | 3 ++- compiler/rustc_middle/src/query/keys.rs | 4 ++-- compiler/rustc_middle/src/query/mod.rs | 4 ++++ compiler/rustc_middle/src/query/plumbing.rs | 4 ++-- compiler/rustc_query_impl/src/dep_kind_vtables.rs | 2 +- compiler/rustc_query_impl/src/execution.rs | 6 ++---- compiler/rustc_query_impl/src/lib.rs | 4 ++-- compiler/rustc_query_impl/src/plumbing.rs | 4 ++-- compiler/rustc_query_impl/src/profiling_support.rs | 2 +- compiler/rustc_query_system/src/lib.rs | 1 - compiler/rustc_query_system/src/query/mod.rs | 4 ---- 13 files changed, 20 insertions(+), 21 deletions(-) rename compiler/{rustc_query_system => rustc_middle}/src/query/caches.rs (99%) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index f0c85fec4ea6..9ed92a77431b 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -51,6 +51,7 @@ #![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)] diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_middle/src/query/caches.rs similarity index 99% rename from compiler/rustc_query_system/src/query/caches.rs rename to compiler/rustc_middle/src/query/caches.rs index c1f5e5b67085..7424492ddc1f 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_middle/src/query/caches.rs @@ -7,10 +7,10 @@ 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; -use crate::ich::StableHashingContext; /// Traits that all query keys must satisfy. pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable>; diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index 594286bfa574..519259d92ea8 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -2,10 +2,11 @@ //! `tcx.$query(..)` and its variations. use rustc_query_system::dep_graph::{DepKind, DepNodeKey}; -use rustc_query_system::query::{QueryCache, QueryMode}; +use rustc_query_system::query::QueryMode; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; +use crate::query::QueryCache; use crate::query::erase::{self, Erasable, Erased}; use crate::query::plumbing::QueryVTable; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index cccb7d51bd3e..d2057e86ddda 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -6,11 +6,11 @@ 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::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 diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7083f160bd77..bbd2442ec6a5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,6 +1,9 @@ use rustc_hir::def_id::LocalDefId; pub use rustc_query_system::query::QueryMode; +pub use self::caches::{ + DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, +}; pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{ @@ -12,6 +15,7 @@ pub use crate::queries::Providers; use crate::ty::TyCtxt; pub(crate) mod arena_cached; +mod caches; pub mod erase; pub(crate) mod inner; mod job; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index f2021978aad7..b5b7e0482b31 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -9,7 +9,7 @@ use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{CycleErrorHandling, QueryCache}; +use rustc_query_system::query::CycleErrorHandling; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -20,7 +20,7 @@ use crate::queries::{ }; use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; -use crate::query::{QueryInfo, QueryJob}; +use crate::query::{QueryCache, QueryInfo, QueryJob}; use crate::ty::TyCtxt; /// For a particular query, keeps track of "active" keys, i.e. keys whose diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index 92fd9c6734d0..aa29313bcd32 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -1,8 +1,8 @@ use rustc_middle::bug; use rustc_middle::dep_graph::DepKindVTable; +use rustc_middle::query::QueryCache; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle}; -use rustc_query_system::query::QueryCache; use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner}; use crate::{QueryCtxt, QueryDispatcherUnerased, QueryFlags}; diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 38150c154e08..2d092b741e3e 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -7,14 +7,12 @@ use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_middle::dep_graph::DepsType; use rustc_middle::query::{ - ActiveKeyStatus, CycleError, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, + ActiveKeyStatus, CycleError, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, QueryState, }; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; -use rustc_query_system::query::{ - CycleErrorHandling, QueryCache, QueryMode, incremental_verify_ich, -}; +use rustc_query_system::query::{CycleErrorHandling, QueryMode, incremental_verify_ich}; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 02a86b5a4c65..90e442f33448 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,10 +20,10 @@ use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDi use rustc_middle::query::plumbing::{ HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, }; -use rustc_middle::query::{AsLocalKey, CycleError}; +use rustc_middle::query::{AsLocalKey, CycleError, QueryCache}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::query::{CycleErrorHandling, QueryCache, QueryMode}; +use rustc_query_system::query::{CycleErrorHandling, QueryMode}; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 1d549c6ecc69..438195a22fdf 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -23,14 +23,14 @@ use rustc_middle::query::on_disk_cache::{ }; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ - Key, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, + Key, QueryCache, 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::{DepNodeKey, HasDepContext}; -use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffect}; +use rustc_query_system::query::{QueryContext, QuerySideEffect}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; 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_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index e8d857cf3178..c968c4f64cb7 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -2,7 +2,6 @@ #![allow(internal_features)] #![cfg_attr(bootstrap, feature(assert_matches))] #![feature(min_specialization)] -#![feature(trait_alias)] // tidy-alphabetical-end pub mod dep_graph; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 8b84c1023b01..5d6f2669c2f2 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -4,13 +4,9 @@ use rustc_data_structures::jobserver::Proxy; use rustc_errors::DiagInner; use rustc_macros::{Decodable, Encodable}; -pub use self::caches::{ - DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, -}; pub use self::plumbing::*; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; -mod caches; mod plumbing; /// How a particular query deals with query cycle errors. From 924dbc46d9afea739aa51769f426c52a4f267e58 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 14:57:33 +1100 Subject: [PATCH 171/182] Move `CycleErrorHandling`. From `rustc_query_system` to `rustc_middle`. --- compiler/rustc_middle/src/query/mod.rs | 4 ++-- compiler/rustc_middle/src/query/plumbing.rs | 13 ++++++++++++- compiler/rustc_query_impl/src/execution.rs | 6 +++--- compiler/rustc_query_impl/src/lib.rs | 4 ++-- compiler/rustc_query_impl/src/plumbing.rs | 8 ++++---- compiler/rustc_query_system/src/query/mod.rs | 12 ------------ 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bbd2442ec6a5..5ca8e4650a9b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -7,8 +7,8 @@ pub use self::caches::{ pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{ - ActiveKeyStatus, CycleError, IntoQueryParam, QueryState, TyCtxtAt, TyCtxtEnsureDone, - TyCtxtEnsureOk, + ActiveKeyStatus, CycleError, CycleErrorHandling, IntoQueryParam, QueryState, TyCtxtAt, + TyCtxtEnsureDone, TyCtxtEnsureOk, }; pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; pub use crate::queries::Providers; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index b5b7e0482b31..09bc4033aa27 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -9,7 +9,6 @@ use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::CycleErrorHandling; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -54,6 +53,18 @@ pub enum ActiveKeyStatus<'tcx> { 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( diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 2d092b741e3e..3b7317493a2c 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -7,12 +7,12 @@ use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_middle::dep_graph::DepsType; use rustc_middle::query::{ - ActiveKeyStatus, CycleError, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, - QueryStackFrame, QueryState, + ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, + QueryStackDeferred, QueryStackFrame, QueryState, }; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; -use rustc_query_system::query::{CycleErrorHandling, QueryMode, incremental_verify_ich}; +use rustc_query_system::query::{QueryMode, incremental_verify_ich}; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 90e442f33448..1757a4ff606b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,10 +20,10 @@ use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDi use rustc_middle::query::plumbing::{ HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, }; -use rustc_middle::query::{AsLocalKey, CycleError, QueryCache}; +use rustc_middle::query::{AsLocalKey, CycleError, CycleErrorHandling, QueryCache}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::query::{CycleErrorHandling, QueryMode}; +use rustc_query_system::query::QueryMode; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 438195a22fdf..e2097919d13b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -208,16 +208,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)*]) diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 5d6f2669c2f2..e2dfffd186aa 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -9,18 +9,6 @@ use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; 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, -} - /// Tracks 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. From fa3b046aa5aed92eb7501c8c3ded322c247539ab Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 15:39:45 +1100 Subject: [PATCH 172/182] Move `QueryMode`. From `rustc_query_system::query::plumbing` to `rustc_middle::query::plumbing`. --- compiler/rustc_middle/src/query/inner.rs | 3 +-- compiler/rustc_middle/src/query/mod.rs | 5 ++--- compiler/rustc_middle/src/query/plumbing.rs | 7 +++++++ compiler/rustc_query_impl/src/execution.rs | 4 ++-- compiler/rustc_query_impl/src/lib.rs | 3 +-- compiler/rustc_query_system/src/query/plumbing.rs | 7 ------- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index 519259d92ea8..0e5e15ba2b9a 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -2,13 +2,12 @@ //! `tcx.$query(..)` and its variations. use rustc_query_system::dep_graph::{DepKind, DepNodeKey}; -use rustc_query_system::query::QueryMode; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; -use crate::query::QueryCache; 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 diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5ca8e4650a9b..66e4a77ea6a5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,5 +1,4 @@ use rustc_hir::def_id::LocalDefId; -pub use rustc_query_system::query::QueryMode; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, @@ -7,8 +6,8 @@ pub use self::caches::{ pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, IntoQueryParam, QueryState, TyCtxtAt, - TyCtxtEnsureDone, TyCtxtEnsureOk, + ActiveKeyStatus, CycleError, CycleErrorHandling, IntoQueryParam, QueryMode, QueryState, + TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, }; pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; pub use crate::queries::Providers; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 09bc4033aa27..7a4746c6ad49 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::ops::Deref; use rustc_data_structures::fingerprint::Fingerprint; @@ -95,6 +96,12 @@ impl<'tcx> CycleError> { } } +#[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, diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 3b7317493a2c..621443187295 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -8,11 +8,11 @@ use rustc_errors::{Diag, FatalError, StashKey}; use rustc_middle::dep_graph::DepsType; use rustc_middle::query::{ ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, - QueryStackDeferred, QueryStackFrame, QueryState, + QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, }; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; -use rustc_query_system::query::{QueryMode, incremental_verify_ich}; +use rustc_query_system::query::incremental_verify_ich; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 1757a4ff606b..1b67a571657f 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,10 +20,9 @@ use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDi use rustc_middle::query::plumbing::{ HashResult, QueryState, QuerySystem, QuerySystemFns, QueryVTable, }; -use rustc_middle::query::{AsLocalKey, CycleError, CycleErrorHandling, QueryCache}; +use rustc_middle::query::{AsLocalKey, CycleError, CycleErrorHandling, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::query::QueryMode; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index d53b4a430b79..fe575ed7982a 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -1,5 +1,4 @@ use std::cell::Cell; -use std::fmt::Debug; use rustc_data_structures::fingerprint::Fingerprint; use tracing::instrument; @@ -90,9 +89,3 @@ fn incremental_verify_ich_failed( INSIDE_VERIFY_PANIC.set(old_in_panic); } - -#[derive(Debug)] -pub enum QueryMode { - Get, - Ensure { check_cache: bool }, -} From ed091aaf5dcaba246cb6193872145f42ed080a3a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 11 Feb 2026 17:02:27 +1100 Subject: [PATCH 173/182] Move `rustc_query_system::query::dep_graph` to `rustc_middle`. Most of the files within the `dep_graph` module can be moved wholesale into `rustc_middle`. But two of them (`mod.rs` and `dep_node.rs`) have the same name as existing files in `rustc_middle`, so for those I just copied the contents into the existing files. The commit also moves `QueryContext` and `incremental_verify_ich*` because they are tightly intertwined with the dep graph code. And a couple of error structs moved as well. --- Cargo.lock | 3 - compiler/rustc_interface/Cargo.toml | 1 - compiler/rustc_interface/src/callbacks.rs | 9 +- .../src/dep_graph/README.md | 0 .../src/dep_graph/debug.rs | 0 .../rustc_middle/src/dep_graph/dep_node.rs | 340 +++++++++++++++++- .../src/dep_graph/dep_node_key.rs | 3 +- .../src/dep_graph/edges.rs | 0 .../src/dep_graph/graph.rs | 8 +- compiler/rustc_middle/src/dep_graph/mod.rs | 183 +++++++++- .../src/dep_graph/query.rs | 0 .../src/dep_graph/serialized.rs | 0 compiler/rustc_middle/src/error.rs | 17 + compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/mir/mono.rs | 5 +- compiler/rustc_middle/src/query/inner.rs | 2 +- compiler/rustc_middle/src/query/keys.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 18 + compiler/rustc_middle/src/query/plumbing.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 6 +- .../src/ty/context/impl_interner.rs | 2 +- .../src/verify_ich.rs} | 5 +- .../rustc_query_impl/src/dep_kind_vtables.rs | 3 +- compiler/rustc_query_impl/src/execution.rs | 5 +- compiler/rustc_query_impl/src/lib.rs | 3 +- compiler/rustc_query_impl/src/plumbing.rs | 13 +- compiler/rustc_query_system/Cargo.toml | 2 - .../src/dep_graph/dep_node.rs | 340 ------------------ .../rustc_query_system/src/dep_graph/mod.rs | 173 --------- compiler/rustc_query_system/src/error.rs | 18 - compiler/rustc_query_system/src/lib.rs | 2 - compiler/rustc_query_system/src/query/mod.rs | 21 -- triagebot.toml | 2 +- 33 files changed, 580 insertions(+), 610 deletions(-) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/README.md (100%) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/debug.rs (100%) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/edges.rs (100%) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/graph.rs (99%) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/query.rs (100%) rename compiler/{rustc_query_system => rustc_middle}/src/dep_graph/serialized.rs (100%) rename compiler/{rustc_query_system/src/query/plumbing.rs => rustc_middle/src/verify_ich.rs} (95%) delete mode 100644 compiler/rustc_query_system/src/dep_graph/dep_node.rs delete mode 100644 compiler/rustc_query_system/src/dep_graph/mod.rs delete mode 100644 compiler/rustc_query_system/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 9b8506c25473..4e0978a8cf21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4093,7 +4093,6 @@ dependencies = [ "rustc_passes", "rustc_privacy", "rustc_query_impl", - "rustc_query_system", "rustc_resolve", "rustc_session", "rustc_span", @@ -4519,13 +4518,11 @@ dependencies = [ "rustc_errors", "rustc_feature", "rustc_hir", - "rustc_index", "rustc_macros", "rustc_serialize", "rustc_session", "rustc_span", "smallvec", - "tracing", ] [[package]] diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 3a3b4d59db86..c234e21b9254 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -35,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/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_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 5f90d1b67d9d..0033a1cd2337 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -1,12 +1,333 @@ +//! 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_query_system::dep_graph::dep_node::DepKind; -use rustc_query_system::dep_graph::{DepContext, DepNode, FingerprintStyle}; +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 { ( $( @@ -172,3 +493,18 @@ pub fn dep_kind_from_label(label: &str) -> DepKind { dep_kind_from_label_string(label) .unwrap_or_else(|_| panic!("Query label {label} does not exist")) } + +// 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_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs index e2fcd82c896a..b1dfc15539bf 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -2,9 +2,8 @@ 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 rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeKey, FingerprintStyle}; -use crate::dep_graph::DepNodeExt; +use crate::dep_graph::{DepContext, DepNode, DepNodeExt, DepNodeKey, FingerprintStyle}; use crate::ty::TyCtxt; impl<'tcx> DepNodeKey> for () { 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 99% rename from compiler/rustc_query_system/src/dep_graph/graph.rs rename to compiler/rustc_middle/src/dep_graph/graph.rs index 94a04b148c4b..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>>, @@ -583,7 +585,7 @@ 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, diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 1056fa9b4462..723eed21f211 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,26 +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 rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -pub use rustc_query_system::dep_graph::{ - DepContext, DepGraphQuery, DepKind, DepNode, DepNodeIndex, Deps, SerializedDepGraph, - SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap, hash_result, -}; +pub trait DepContext: Copy { + type Deps: Deps; -pub use self::dep_node::{DepNodeExt, dep_kind_from_label, dep_kinds, label_strs}; -pub(crate) use self::dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata}; + /// Create a hashing context for hashing new results. + fn with_stable_hashing_context(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; -pub type DepGraph = rustc_query_system::dep_graph::DepGraph; + /// Access the DepGraph. + fn dep_graph(&self) -> &graph::DepGraph; -pub type DepKindVTable<'tcx> = rustc_query_system::dep_graph::DepKindVTable>; + /// 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 100% rename from compiler/rustc_query_system/src/dep_graph/query.rs rename to compiler/rustc_middle/src/dep_graph/query.rs diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs similarity index 100% rename from compiler/rustc_query_system/src/dep_graph/serialized.rs rename to compiler/rustc_middle/src/dep_graph/serialized.rs diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index d487caf4d3ac..dfb99fb98513 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -197,3 +197,20 @@ pub(crate) struct InvalidConstInValtree { 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/lib.rs b/compiler/rustc_middle/src/lib.rs index 9ed92a77431b..1c4c987aee92 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -81,6 +81,7 @@ pub mod thir; pub mod traits; pub mod ty; pub mod util; +pub mod verify_ich; #[macro_use] pub mod query; 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/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index 0e5e15ba2b9a..b977172fcf9d 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -1,10 +1,10 @@ //! Helper functions that serve as the immediate implementation of //! `tcx.$query(..)` and its variations. -use rustc_query_system::dep_graph::{DepKind, DepNodeKey}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; +use crate::dep_graph::{DepKind, DepNodeKey}; use crate::query::erase::{self, Erasable, Erased}; use crate::query::plumbing::QueryVTable; use crate::query::{QueryCache, QueryMode}; diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index d2057e86ddda..83eb4b9ad475 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -5,9 +5,9 @@ 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_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}; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 66e4a77ea6a5..d16ca3c401d2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,4 +1,6 @@ +use rustc_data_structures::jobserver::Proxy; use rustc_hir::def_id::LocalDefId; +use rustc_query_system::query::QuerySideEffect; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, @@ -10,6 +12,7 @@ pub use self::plumbing::{ TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, }; pub use self::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra}; +use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; pub use crate::queries::Providers; use crate::ty::TyCtxt; @@ -33,3 +36,18 @@ pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> Str 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/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 7a4746c6ad49..727e93148251 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -8,13 +8,12 @@ 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}; 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::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex}; use crate::queries::{ ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates, }; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f638dd80864c..430890d5a42d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,7 +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::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::Session; @@ -54,7 +53,8 @@ use rustc_type_ir::{CollectAndApply, TypeFlags, WithCachedTypeInfo, elaborate, s use tracing::{debug, instrument}; use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKindVTable}; +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; @@ -2751,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 index 5a15d132048d..7580cc65d530 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -9,11 +9,11 @@ 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_query_system::dep_graph::DepNodeIndex; 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; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_middle/src/verify_ich.rs similarity index 95% rename from compiler/rustc_query_system/src/query/plumbing.rs rename to compiler/rustc_middle/src/verify_ich.rs index fe575ed7982a..c5aec73679ec 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/verify_ich.rs @@ -1,11 +1,10 @@ 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}; -use crate::ich::StableHashingContext; -use crate::query::SerializedDepNodeIndex; +use crate::dep_graph::{DepContext, DepGraphData, SerializedDepNodeIndex}; #[inline] #[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index aa29313bcd32..99feeb86bac9 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -1,8 +1,7 @@ use rustc_middle::bug; -use rustc_middle::dep_graph::DepKindVTable; +use rustc_middle::dep_graph::{DepKindVTable, DepNodeKey, FingerprintStyle}; use rustc_middle::query::QueryCache; use rustc_middle::ty::TyCtxt; -use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle}; use crate::plumbing::{force_from_dep_node_inner, try_load_from_on_disk_cache_inner}; use crate::{QueryCtxt, QueryDispatcherUnerased, QueryFlags}; diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 621443187295..4df55e46e13e 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -5,14 +5,13 @@ use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; -use rustc_middle::dep_graph::DepsType; +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_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; -use rustc_query_system::query::incremental_verify_ich; +use rustc_middle::verify_ich::incremental_verify_ich; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 1b67a571657f..6a4171afe4bc 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -12,7 +12,7 @@ use std::marker::ConstParamTy; use rustc_data_structures::sync::AtomicU64; -use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex}; +use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::queries::{ self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, }; @@ -22,7 +22,6 @@ use rustc_middle::query::plumbing::{ }; use rustc_middle::query::{AsLocalKey, CycleError, CycleErrorHandling, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; -use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_span::{ErrorGuaranteed, Span}; pub use crate::dep_kind_vtables::make_dep_kind_vtables; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index e2097919d13b..ad782b3150b0 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -16,21 +16,22 @@ 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, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex, dep_kinds, + self, DepContext, DepNode, DepNodeIndex, DepNodeKey, DepsType, HasDepContext, + SerializedDepNodeIndex, dep_kinds, }; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, }; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ - Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, + 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::{DepNodeKey, HasDepContext}; -use rustc_query_system::query::{QueryContext, QuerySideEffect}; +use rustc_query_system::query::QuerySideEffect; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; @@ -275,8 +276,8 @@ macro_rules! feedable { macro_rules! hash_result { ([][$V:ty]) => {{ Some(|hcx, result| { - let result = ::rustc_middle::query::erase::restore_val::<$V>(*result); - ::rustc_query_system::dep_graph::hash_result(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]) => {{ diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index d2a58b341048..bd12dcbfe0d1 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -11,11 +11,9 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } 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" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing = "0.1" # tidy-alphabetical-end 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 5df50b2864b2..000000000000 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ /dev/null @@ -1,340 +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: 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: () = (); -} - -// 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 da110ad2c77c..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, DepNodeKey, WorkProductId}; -pub use graph::{ - DepGraph, DepGraphData, 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 { - 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, - } - } -} diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs deleted file mode 100644 index f48afe6f75fa..000000000000 --- a/compiler/rustc_query_system/src/error.rs +++ /dev/null @@ -1,18 +0,0 @@ -use rustc_macros::Diagnostic; - -#[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_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index c968c4f64cb7..bb077d02422b 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -4,7 +4,5 @@ #![feature(min_specialization)] // tidy-alphabetical-end -pub mod dep_graph; -mod error; pub mod ich; pub mod query; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index e2dfffd186aa..87be4358fb8b 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -1,14 +1,8 @@ use std::fmt::Debug; -use rustc_data_structures::jobserver::Proxy; use rustc_errors::DiagInner; use rustc_macros::{Decodable, Encodable}; -pub use self::plumbing::*; -use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; - -mod plumbing; - /// Tracks 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. @@ -26,18 +20,3 @@ pub enum QuerySideEffect { /// effect dep node as a dependency. Diagnostic(DiagInner), } - -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/triagebot.toml b/triagebot.toml index bc90371393b6..c9d6c1a730b7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1556,6 +1556,7 @@ dep-bumps = [ "/compiler/rustc_llvm" = ["@cuviper"] "/compiler/rustc_codegen_llvm/src/debuginfo" = ["compiler", "debuginfo"] "/compiler/rustc_codegen_ssa" = ["compiler", "codegen"] +"/compiler/rustc_middle/src/dep_graph" = ["compiler", "incremental", "query-system"] "/compiler/rustc_middle/src/mir" = ["compiler", "mir"] "/compiler/rustc_middle/src/traits" = ["compiler", "types"] "/compiler/rustc_middle/src/ty" = ["compiler", "types"] @@ -1567,7 +1568,6 @@ dep-bumps = [ "/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] "/compiler/rustc_query_impl" = ["compiler", "query-system"] "/compiler/rustc_query_system" = ["compiler", "query-system"] -"/compiler/rustc_query_system/src/dep_graph" = ["compiler", "incremental", "query-system"] "/compiler/rustc_query_system/src/ich" = ["compiler", "incremental", "query-system"] "/compiler/rustc_trait_selection" = ["compiler", "types"] "/compiler/rustc_traits" = ["compiler", "types"] From d29c931c9dc4bd4cca3695d54c7b46153ac99e2b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 14 Feb 2026 07:43:15 -0500 Subject: [PATCH 174/182] Update to nightly-2026-02-14 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ce97f300fa40..655fa6abbab2 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-02-13" +channel = "nightly-2026-02-14" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 018a5efcf7d2b115a39628c19ad7ceb79b2ce90c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 14 Feb 2026 13:47:52 +0100 Subject: [PATCH 175/182] Rename `inline_fluent!` to `msg!` --- compiler/rustc_ast_lowering/src/asm.rs | 10 +- compiler/rustc_ast_lowering/src/expr.rs | 4 +- compiler/rustc_ast_passes/src/feature_gate.rs | 4 +- .../rustc_attr_parsing/src/attributes/cfg.rs | 4 +- .../src/attributes/link_attrs.rs | 9 +- .../rustc_borrowck/src/diagnostics/mod.rs | 18 +- .../src/diagnostics/region_errors.rs | 16 +- compiler/rustc_builtin_macros/src/errors.rs | 11 +- compiler/rustc_codegen_llvm/src/errors.rs | 26 +-- compiler/rustc_codegen_ssa/src/back/apple.rs | 12 +- compiler/rustc_codegen_ssa/src/errors.rs | 107 +++++----- .../rustc_const_eval/src/check_consts/ops.rs | 4 +- .../rustc_const_eval/src/const_eval/error.rs | 18 +- .../src/const_eval/eval_queries.rs | 4 +- .../src/const_eval/machine.rs | 6 +- compiler/rustc_const_eval/src/errors.rs | 191 ++++++++---------- .../rustc_const_eval/src/interpret/call.rs | 16 +- .../rustc_const_eval/src/interpret/cast.rs | 4 +- .../src/interpret/eval_context.rs | 4 +- .../src/interpret/intrinsics.rs | 29 ++- .../rustc_const_eval/src/interpret/memory.rs | 25 +-- compiler/rustc_errors/src/diagnostic_impls.rs | 20 +- compiler/rustc_errors/src/lib.rs | 8 +- compiler/rustc_expand/src/config.rs | 8 +- compiler/rustc_expand/src/expand.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 8 +- compiler/rustc_hir_analysis/src/errors.rs | 12 +- .../src/hir_ty_lowering/errors.rs | 6 +- compiler/rustc_hir_typeck/src/callee.rs | 12 +- compiler/rustc_hir_typeck/src/errors.rs | 67 +++--- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 6 +- compiler/rustc_lint/src/errors.rs | 8 +- compiler/rustc_lint/src/if_let_rescope.rs | 6 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 10 +- compiler/rustc_lint/src/levels.rs | 6 +- compiler/rustc_lint/src/lints.rs | 142 ++++++------- compiler/rustc_lint/src/non_fmt_panic.rs | 18 +- compiler/rustc_lint/src/non_local_def.rs | 4 +- .../rustc_lint/src/types/improper_ctypes.rs | 90 ++++----- compiler/rustc_macros/src/diagnostics/mod.rs | 4 +- .../{inline_fluent.rs => msg_macro.rs} | 2 +- compiler/rustc_macros/src/lib.rs | 4 +- compiler/rustc_metadata/src/errors.rs | 33 ++- compiler/rustc_middle/src/middle/stability.rs | 8 +- compiler/rustc_middle/src/mir/terminator.rs | 48 +++-- compiler/rustc_middle/src/ty/layout.rs | 21 +- compiler/rustc_mir_build/src/errors.rs | 31 ++- .../src/thir/pattern/check_match.rs | 16 +- .../src/thir/pattern/const_to_pat.rs | 4 +- compiler/rustc_mir_transform/src/errors.rs | 23 +-- .../src/lint_tail_expr_drop_order.rs | 6 +- compiler/rustc_parse/src/errors.rs | 42 ++-- compiler/rustc_parse/src/parser/attr.rs | 48 ++--- .../rustc_parse/src/parser/diagnostics.rs | 6 +- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 8 +- compiler/rustc_passes/src/errors.rs | 72 +++---- compiler/rustc_resolve/src/errors.rs | 8 +- .../src/error_reporting/infer/region.rs | 26 +-- .../traits/fulfillment_errors.rs | 6 +- compiler/rustc_trait_selection/src/errors.rs | 98 ++++----- .../src/errors/note_and_explain.rs | 4 +- .../src/traits/normalize.rs | 4 +- 64 files changed, 647 insertions(+), 840 deletions(-) rename compiler/rustc_macros/src/diagnostics/{inline_fluent.rs => msg_macro.rs} (76%) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index fc1f198e8b2a..a7bf1c99a7e2 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -3,7 +3,7 @@ use std::fmt::Write; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::inline_fluent; +use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_session::parse::feature_err; @@ -67,7 +67,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_experimental_arch, sp, - inline_fluent!("inline assembly is not stable yet on this architecture"), + 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, - inline_fluent!("the `may_unwind` option is unstable"), + msg!("the `may_unwind` option is unstable"), ) .emit(); } @@ -499,9 +499,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { sess, sym::asm_goto_with_outputs, *op_sp, - inline_fluent!( - "using both label and output operands for inline assembly is unstable" - ), + msg!("using both label and output operands for inline assembly is unstable"), ) .emit(); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d9bf6b52f31f..b034e250b58d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -5,7 +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::inline_fluent; +use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; @@ -1702,7 +1702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &self.tcx.sess, sym::yield_expr, span, - inline_fluent!("yield syntax is experimental"), + msg!("yield syntax is experimental"), ) .emit(); } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 34c73b545df8..4523b4c14163 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,6 +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::inline_fluent; +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}; @@ -125,7 +125,7 @@ impl<'a> PostExpansionVisitor<'a> { &self, non_lifetime_binders, non_lt_param_spans, - inline_fluent!("only lifetime parameters can be used in this context") + msg!("only lifetime parameters can be used in this context") ); // FIXME(non_lifetime_binders): Const bound params are pretty broken. diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 686d98a9fc78..d2f743f6c5d8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -3,7 +3,7 @@ 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, inline_fluent}; +use rustc_errors::{Applicability, PResult, msg}; use rustc_feature::{ AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template, }; @@ -141,7 +141,7 @@ fn parse_cfg_entry_target( cx.sess(), sym::cfg_target_compact, meta_span, - inline_fluent!("compact `cfg(target(..))` is experimental and subject to change"), + msg!("compact `cfg(target(..))` is experimental and subject to change"), ) .emit(); } diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 6c52be9bd229..21c05611ce29 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,4 +1,4 @@ -use rustc_errors::inline_fluent; +use rustc_errors::msg; use rustc_feature::Features; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_hir::attrs::*; @@ -316,7 +316,7 @@ impl LinkParser { sess, sym::raw_dylib_elf, nv.value_span, - inline_fluent!("link kind `raw-dylib` is unstable on ELF platforms"), + msg!("link kind `raw-dylib` is unstable on ELF platforms"), ) .emit(); } else { @@ -331,7 +331,7 @@ impl LinkParser { sess, sym::link_arg_attribute, nv.value_span, - inline_fluent!("link kind `link-arg` is unstable"), + msg!("link kind `link-arg` is unstable"), ) .emit(); } @@ -396,8 +396,7 @@ impl LinkParser { return true; }; if !features.link_cfg() { - feature_err(sess, sym::link_cfg, item.span(), inline_fluent!("link cfg is 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 diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 04bacd049bc9..7c895ff63e07 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,9 +4,7 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{ - Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, inline_fluent, 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, @@ -1313,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( - inline_fluent!("`{$ty}` is made to be an `FnOnce` closure here"), + msg!("`{$ty}` is made to be an `FnOnce` closure here"), err.args.iter(), ); err.remove_arg("ty"); @@ -1322,12 +1320,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } span.push_span_label( fn_call_span, - inline_fluent!("this value implements `FnOnce`, which causes it to be moved when called"), - ); - err.span_note( - span, - inline_fluent!("`FnOnce` closures can only be called once"), + msg!("this value implements `FnOnce`, which causes it to be moved when called"), ); + err.span_note(span, msg!("`FnOnce` closures can only be called once")); } else { err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } @@ -1573,6 +1568,5 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } -const LIMITATION_NOTE: DiagMessage = inline_fluent!( - "due to a current limitation of the type system, this implies a `'static` lifetime" -); +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/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index ca6b9965f1e9..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, inline_fluent}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; @@ -291,7 +291,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - inline_fluent!("consider restricting the type parameter to the `'static` lifetime"), + msg!("consider restricting the type parameter to the `'static` lifetime"), suggestions, Applicability::MaybeIncorrect, ); @@ -982,18 +982,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut multi_span: MultiSpan = vec![*span].into(); multi_span.push_span_label( *span, - inline_fluent!("this has an implicit `'static` lifetime requirement"), + msg!("this has an implicit `'static` lifetime requirement"), ); multi_span.push_span_label( ident.span, - inline_fluent!( - "calling this method introduces the `impl`'s `'static` requirement" - ), + msg!("calling this method introduces the `impl`'s `'static` requirement"), ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - inline_fluent!("consider relaxing the implicit `'static` requirement"), + msg!("consider relaxing the implicit `'static` requirement"), " + '_", Applicability::MaybeIncorrect, ); @@ -1156,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(), - inline_fluent!("dereference the return value"), + msg!("dereference the return value"), "*".repeat(count), Applicability::MachineApplicable, ); @@ -1200,7 +1198,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - inline_fluent!("consider adding 'move' keyword before the nested closure"), + msg!("consider adding 'move' keyword before the nested closure"), "move ", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 862ce3e62cc9..29ab8ee505d6 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - Subdiagnostic, inline_fluent, + Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -764,7 +764,7 @@ 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(inline_fluent!( + let msg = diag.eagerly_translate(msg!( "{$named -> [true] named argument *[false] argument @@ -947,13 +947,12 @@ 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(inline_fluent!("clobber_abi"), [].into_iter()); - let lbl2 = - dcx.eagerly_translate_to_string(inline_fluent!("generic outputs"), [].into_iter()); + 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, - inline_fluent!("asm with `clobber_abi` must specify explicit registers for outputs"), + msg!("asm with `clobber_abi` must specify explicit registers for outputs"), ) .with_span(self.spans.clone()) .with_span_labels(self.clobbers, &lbl1) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 37ca2a959745..af154a1aea80 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,7 +2,7 @@ use std::ffi::CString; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, inline_fluent}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; use rustc_macros::Diagnostic; use rustc_span::Span; @@ -28,7 +28,7 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { Diag::new( dcx, level, - inline_fluent!("failed to parse target machine config to target machine: {$error}"), + msg!("failed to parse target machine config to target machine: {$error}"), ) .with_arg("error", message) } @@ -121,25 +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 { .. } => inline_fluent!("could not write output to {$path}: {$llvm_err}"), - CreateTargetMachine { .. } => inline_fluent!( - "could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}" - ), - RunLlvmPasses => inline_fluent!("failed to run LLVM passes: {$llvm_err}"), - WriteIr { .. } => inline_fluent!("failed to write LLVM IR to {$path}: {$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 => { - inline_fluent!("failed to prepare thin LTO context: {$llvm_err}") + msg!("failed to prepare thin LTO context: {$llvm_err}") } LoadBitcode { .. } => { - inline_fluent!("failed to load bitcode of module \"{$name}\": {$llvm_err}") + msg!("failed to load bitcode of module \"{$name}\": {$llvm_err}") } WriteThinLtoKey { .. } => { - inline_fluent!("error while writing ThinLTO key data: {$err}: {$llvm_err}") + msg!("error while writing ThinLTO key data: {$err}: {$llvm_err}") } PrepareThinLtoModule => { - inline_fluent!("failed to prepare thin LTO module: {$llvm_err}") + msg!("failed to prepare thin LTO module: {$llvm_err}") } - ParseBitcode => inline_fluent!("failed to parse bitcode for LTO module: {$llvm_err}"), + ParseBitcode => msg!("failed to parse bitcode for LTO module: {$llvm_err}"), }; self.0 .into_diag(dcx, level) diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 3ed5793d10c5..1b707a24066e 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::process::Command; use itertools::Itertools; -use rustc_errors::inline_fluent; +use rustc_errors::msg; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; pub(super) use rustc_target::spec::apple::OSVersion; @@ -185,21 +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(inline_fluent!("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")); + 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(inline_fluent!( - "found active developer directory at \"{$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(inline_fluent!("when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode")); + diag.help(msg!("when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode")); } } } else { - diag.help(inline_fluent!("pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable")); + 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/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index a50a1da7aaa8..74f7829ace95 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -8,8 +8,7 @@ use std::process::ExitStatus; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, - inline_fluent, + Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::layout::LayoutError; @@ -217,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(inline_fluent!("failed to read input file")), + thorin::Error::ReadInput(_) => build(msg!("failed to read input file")), thorin::Error::ParseFileKind(_) => { - build(inline_fluent!("failed to parse input file kind")) + build(msg!("failed to parse input file kind")) } thorin::Error::ParseObjectFile(_) => { - build(inline_fluent!("failed to parse input object file")) + build(msg!("failed to parse input object file")) } thorin::Error::ParseArchiveFile(_) => { - build(inline_fluent!("failed to parse input archive file")) + build(msg!("failed to parse input archive file")) } thorin::Error::ParseArchiveMember(_) => { - build(inline_fluent!("failed to parse archive member")) + build(msg!("failed to parse archive member")) } - thorin::Error::InvalidInputKind => build(inline_fluent!("input is not an archive or elf object")), - thorin::Error::DecompressData(_) => build(inline_fluent!("failed to decompress compressed section")), + 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(inline_fluent!("section without name at offset {$offset}")) + build(msg!("section without name at offset {$offset}")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - build(inline_fluent!("relocation with invalid symbol for section `{$section}` at offset {$offset}")) + 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(inline_fluent!("multiple relocations for section `{$section}` at offset {$offset}")) + 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(inline_fluent!("unsupported relocation for section {$section} at offset {$offset}")) + 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(inline_fluent!("missing path attribute to DWARF object ({$id})")) + thorin::Error::MissingDwoName(id) => build(msg!("missing path attribute to DWARF object ({$id})")) .with_arg("id", format!("0x{id:08x}")), thorin::Error::NoCompilationUnits => { - build(inline_fluent!("input object has no compilation units")) + build(msg!("input object has no compilation units")) } - thorin::Error::NoDie => build(inline_fluent!("no top-level debugging information entry in compilation/type unit")), + thorin::Error::NoDie => build(msg!("no top-level debugging information entry in compilation/type unit")), thorin::Error::TopLevelDieNotUnit => { - build(inline_fluent!("top-level debugging information entry is not a compilation/type unit")) + build(msg!("top-level debugging information entry is not a compilation/type unit")) } thorin::Error::MissingRequiredSection(section) => { - build(inline_fluent!("input object missing required section `{$section}`")) + build(msg!("input object missing required section `{$section}`")) .with_arg("section", section) } thorin::Error::ParseUnitAbbreviations(_) => { - build(inline_fluent!("failed to parse unit abbreviations")) + build(msg!("failed to parse unit abbreviations")) } thorin::Error::ParseUnitAttribute(_) => { - build(inline_fluent!("failed to parse unit attribute")) + build(msg!("failed to parse unit attribute")) } thorin::Error::ParseUnitHeader(_) => { - build(inline_fluent!("failed to parse unit header")) + build(msg!("failed to parse unit header")) } - thorin::Error::ParseUnit(_) => build(inline_fluent!("failed to parse unit")), + thorin::Error::ParseUnit(_) => build(msg!("failed to parse unit")), thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - build(inline_fluent!("incompatible `{$section}` index version: found version {$actual}, expected version {$format}")) + 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(inline_fluent!("read offset at index {$index} of `.debug_str_offsets.dwo` section")).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(inline_fluent!("read string at offset {$offset} of `.debug_str.dwo` section")) + build(msg!("read string at offset {$offset} of `.debug_str.dwo` section")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::ParseIndex(_, section) => { - build(inline_fluent!("failed to parse `{$section}` index section")).with_arg("section", section) + build(msg!("failed to parse `{$section}` index section")).with_arg("section", section) } thorin::Error::UnitNotInIndex(unit) => { - build(inline_fluent!("unit {$unit} from input package is not in its 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(inline_fluent!("row {$row} found in index's hash table not present 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(inline_fluent!("section not found in unit's row in index")), - thorin::Error::EmptyUnit(unit) => build(inline_fluent!("unit {$unit} in input DWARF object with no data")) + 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(inline_fluent!("multiple `.debug_info.dwo` sections")) + build(msg!("multiple `.debug_info.dwo` sections")) } thorin::Error::MultipleDebugTypesSection => { - build(inline_fluent!("multiple `.debug_types.dwo` sections in a package")) + build(msg!("multiple `.debug_types.dwo` sections in a package")) } - thorin::Error::NotSplitUnit => build(inline_fluent!("regular compilation unit in object (missing dwo identifier)")), - thorin::Error::DuplicateUnit(unit) => build(inline_fluent!("duplicate split compilation unit ({$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(inline_fluent!("unit {$unit} referenced by executable was not found")) + build(msg!("unit {$unit} referenced by executable was not found")) .with_arg("unit", format!("0x{unit:08x}")) } thorin::Error::NoOutputObjectCreated => { - build(inline_fluent!("no output object was created from inputs")) + build(msg!("no output object was created from inputs")) } thorin::Error::MixedInputEncodings => { - build(inline_fluent!("input objects have mixed encodings")) + build(msg!("input objects have mixed encodings")) } thorin::Error::Io(e) => { - build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectRead(e) => { - build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectWrite(e) => { - build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliRead(e) => { - build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliWrite(e) => { - build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) + build(msg!("{$error}")).with_arg("error", format!("{e}")) } _ => unimplemented!("Untranslated thorin error"), } @@ -350,11 +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, - inline_fluent!("linking with `{$linker_path}` failed: {$exit_status}"), - ); + 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)); @@ -463,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(inline_fluent!("some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified")) - .note(inline_fluent!("use the `-l` flag to specify native 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(inline_fluent!("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.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,12 +478,11 @@ 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, inline_fluent!("0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`")); - diag.note(inline_fluent!( + 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(inline_fluent!("consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code")); + diag.note(msg!("consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code")); diag } } @@ -1233,9 +1228,7 @@ impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_ let mut diag = Diag::new( dcx, level, - inline_fluent!( - "the target features {$features} must all be either enabled or disabled together" - ), + msg!("the target features {$features} must all be either enabled or disabled together"), ); if let Some(span) = self.span { diag.span(span); diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index ecf52e4aa605..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, inline_fluent}; +use rustc_errors::{Applicability, Diag, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -181,7 +181,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ); if let ConstContext::Static(_) = ccx.const_kind() { - err.note(inline_fluent!( + err.note(msg!( "consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`" )); } diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index e87d2cbb20de..69aef3b047df 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -43,40 +43,36 @@ pub enum ConstEvalErrKind { impl MachineStopType for ConstEvalErrKind { fn diagnostic_message(&self) -> DiagMessage { use ConstEvalErrKind::*; - use rustc_errors::inline_fluent; + use rustc_errors::msg; match self { ConstAccessesMutGlobal => "constant accesses mutable global memory".into(), ModifiedGlobal => { "modifying a static's initial value from another static's initializer".into() } - Panic { .. } => inline_fluent!("evaluation panicked: {$msg}"), + Panic { .. } => msg!("evaluation panicked: {$msg}"), RecursiveStatic => { "encountered static that tried to access itself during initialization".into() } AssertFailure(x) => x.diagnostic_message(), WriteThroughImmutablePointer => { - inline_fluent!( + msg!( "writing through a pointer that was derived from a shared (immutable) reference" ) } ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { - inline_fluent!( - "attempting to call `const_make_global` twice on the same allocation {$alloc}" - ) + msg!("attempting to call `const_make_global` twice on the same allocation {$alloc}") } ConstMakeGlobalPtrIsNonHeap(_) => { - inline_fluent!( + msg!( "pointer passed to `const_make_global` does not point to a heap allocation: {$ptr}" ) } ConstMakeGlobalWithDanglingPtr(_) => { - inline_fluent!("pointer passed to `const_make_global` is dangling: {$ptr}") + msg!("pointer passed to `const_make_global` is dangling: {$ptr}") } ConstMakeGlobalWithOffset(_) => { - inline_fluent!( - "making {$ptr} global which does not point to the beginning of an object" - ) + msg!("making {$ptr} global which does not point to the beginning of an object") } } } 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 ae28e3d7d192..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, inline_fluent}; +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}; @@ -469,7 +469,7 @@ fn report_eval_error<'tcx>( diag.code(E0080); diag.span_label( span, - inline_fluent!( + msg!( "evaluation of `{$instance}` failed {$num_frames -> [0] here *[other] inside this call diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 8bc515a8b1b5..e017362b8c4b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,7 +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::inline_fluent; +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; @@ -489,7 +489,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - inline_fluent!( + msg!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 [too_large] too large @@ -519,7 +519,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - inline_fluent!( + msg!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 [too_large] too large diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index cba2c462bf22..b477c998a278 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -6,7 +6,7 @@ use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, - Subdiagnostic, inline_fluent, + Subdiagnostic, msg, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -389,9 +389,9 @@ 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, inline_fluent!("the failure occurred here")); + span.push_span_label(self.span, msg!("the failure occurred here")); } - let msg = diag.eagerly_translate(inline_fluent!( + let msg = diag.eagerly_translate(msg!( r#"{$times -> [0] inside {$where_ -> [closure] closure @@ -653,25 +653,25 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { ValidationError(e) => e.diagnostic_message(), Unreachable => "entering unreachable code".into(), - BoundsCheckFailed { .. } => inline_fluent!("indexing out of bounds: the len is {$len} but the index is {$index}"), + 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 { .. } => inline_fluent!("arithmetic overflow in `{$intrinsic}`"), - ShiftOverflow { .. } => inline_fluent!("overflowing shift by {$shift_amount} in `{$intrinsic}`"), + 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(_, _) => inline_fluent!( + 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 { .. } => inline_fluent!( + PointerOutOfBounds { .. } => msg!( "{$operation -> [MemoryAccess] memory access failed [InboundsPointerArithmetic] in-bounds pointer arithmetic failed @@ -708,7 +708,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } }" ), - DanglingIntPointer { addr: 0, .. } => inline_fluent!( + DanglingIntPointer { addr: 0, .. } => msg!( "{$operation -> [MemoryAccess] memory access failed [InboundsPointerArithmetic] in-bounds pointer arithmetic failed @@ -728,7 +728,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { *[x] be dereferenceable for {$inbounds_size} bytes } }, but got null pointer"), - DanglingIntPointer { .. } => inline_fluent!( + DanglingIntPointer { .. } => msg!( "{$operation -> [MemoryAccess] memory access failed [InboundsPointerArithmetic] in-bounds pointer arithmetic failed @@ -748,34 +748,34 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { *[x] be dereferenceable for {$inbounds_size} bytes } }, but got {$pointer} which is a dangling pointer (it has no provenance)"), - AlignmentCheckFailed { .. } => inline_fluent!( + AlignmentCheckFailed { .. } => msg!( "{$msg -> [AccessedPtr] accessing memory *[other] accessing memory based on pointer } with alignment {$has}, but alignment {$required} is required" ), - WriteToReadOnly(_) => inline_fluent!("writing to {$allocation} which is read-only"), - DerefFunctionPointer(_) => inline_fluent!("accessing {$allocation} which contains a function"), - DerefVTablePointer(_) => inline_fluent!("accessing {$allocation} which contains a vtable"), - DerefTypeIdPointer(_) => inline_fluent!("accessing {$allocation} which contains a `TypeId`"), - InvalidBool(_) => inline_fluent!("interpreting an invalid 8-bit value as a bool: 0x{$value}"), - InvalidChar(_) => inline_fluent!("interpreting an invalid 32-bit value as a char: 0x{$value}"), - InvalidTag(_) => inline_fluent!("enum value has invalid tag: {$tag}"), - InvalidFunctionPointer(_) => inline_fluent!("using {$pointer} as function pointer but it does not point to a function"), - InvalidVTablePointer(_) => inline_fluent!("using {$pointer} as vtable pointer but it does not point to a vtable"), - InvalidVTableTrait { .. } => inline_fluent!("using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected"), - InvalidStr(_) => inline_fluent!("this string is not valid UTF-8: {$err}"), + 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(_)) => inline_fluent!("reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory"), + 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(_) => inline_fluent!("scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead"), + 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 { .. } => { - inline_fluent!("trying to set discriminant of a {$ty} to the niched variant, but the value does not match") + msg!("trying to set discriminant of a {$ty} to the niched variant, but the value does not match") } - AbiMismatchArgument { .. } => inline_fluent!("calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty}"), - AbiMismatchReturn { .. } => inline_fluent!("calling a function with return type {$callee_ty} passing return place of type {$caller_ty}"), + 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}"), } } @@ -920,29 +920,25 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { match self.kind { PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => { - inline_fluent!( - "{$front_matter}: encountered a box pointing to uninhabited type {$ty}" - ) + msg!("{$front_matter}: encountered a box pointing to uninhabited type {$ty}") } PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => { - inline_fluent!( - "{$front_matter}: encountered a reference pointing to uninhabited type {$ty}" - ) + msg!("{$front_matter}: encountered a reference pointing to uninhabited type {$ty}") } PointerAsInt { .. } => { - inline_fluent!("{$front_matter}: encountered a pointer, but {$expected}") + msg!("{$front_matter}: encountered a pointer, but {$expected}") + } + PartialPointer => { + msg!("{$front_matter}: encountered a partial pointer or a mix of pointers") } - PartialPointer => inline_fluent!( - "{$front_matter}: encountered a partial pointer or a mix of pointers" - ), MutableRefToImmutable => { - inline_fluent!( + msg!( "{$front_matter}: encountered mutable reference or box pointing to read-only memory" ) } NullFnPtr { .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a {$maybe -> [true] maybe-null *[false] null @@ -950,84 +946,78 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ) } NeverVal => { - inline_fluent!("{$front_matter}: encountered a value of the never type `!`") + msg!("{$front_matter}: encountered a value of the never type `!`") } NonnullPtrMaybeNull { .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero" ) } PtrOutOfRange { .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}" ) } OutOfRange { .. } => { - inline_fluent!( - "{$front_matter}: encountered {$value}, but expected something {$in_range}" - ) + msg!("{$front_matter}: encountered {$value}, but expected something {$in_range}") } UnsafeCellInImmutable => { - inline_fluent!("{$front_matter}: encountered `UnsafeCell` in read-only memory") + msg!("{$front_matter}: encountered `UnsafeCell` in read-only memory") } UninhabitedVal { .. } => { - inline_fluent!("{$front_matter}: encountered a value of uninhabited type `{$ty}`") + msg!("{$front_matter}: encountered a value of uninhabited type `{$ty}`") } InvalidEnumTag { .. } => { - inline_fluent!( - "{$front_matter}: encountered {$value}, but expected a valid enum tag" - ) + msg!("{$front_matter}: encountered {$value}, but expected a valid enum tag") } UninhabitedEnumVariant => { - inline_fluent!("{$front_matter}: encountered an uninhabited enum variant") + msg!("{$front_matter}: encountered an uninhabited enum variant") } Uninit { .. } => { - inline_fluent!("{$front_matter}: encountered uninitialized memory, but {$expected}") + msg!("{$front_matter}: encountered uninitialized memory, but {$expected}") } InvalidVTablePtr { .. } => { - inline_fluent!( - "{$front_matter}: encountered {$value}, but expected a vtable pointer" - ) + msg!("{$front_matter}: encountered {$value}, but expected a vtable pointer") } InvalidMetaWrongTrait { .. } => { - inline_fluent!( + msg!( "{$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`" ) } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => { - inline_fluent!( + msg!( "{$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object" ) } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => { - inline_fluent!( + msg!( "{$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object" ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => { - inline_fluent!( + msg!( "{$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object" ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => { - inline_fluent!( + msg!( "{$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object" ) } UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})" ) } UnalignedPtr { ptr_kind: PointerKind::Box, .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})" ) } NullPtr { ptr_kind: PointerKind::Box, .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a {$maybe -> [true] maybe-null *[false] null @@ -1035,7 +1025,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ) } NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a {$maybe -> [true] maybe-null *[false] null @@ -1043,66 +1033,59 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ) } DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { - inline_fluent!( - "{$front_matter}: encountered a dangling box ({$pointer} has no provenance)" - ) + msg!("{$front_matter}: encountered a dangling box ({$pointer} has no provenance)") } DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a dangling reference ({$pointer} has no provenance)" ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)" ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => { - inline_fluent!( + msg!( "{$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)" ) } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => { - inline_fluent!("{$front_matter}: encountered a dangling box (use-after-free)") + msg!("{$front_matter}: encountered a dangling box (use-after-free)") } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => { - inline_fluent!("{$front_matter}: encountered a dangling reference (use-after-free)") + msg!("{$front_matter}: encountered a dangling reference (use-after-free)") } InvalidBool { .. } => { - inline_fluent!("{$front_matter}: encountered {$value}, but expected a boolean") + msg!("{$front_matter}: encountered {$value}, but expected a boolean") } InvalidChar { .. } => { - inline_fluent!( + msg!( "{$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" ) } InvalidFnPtr { .. } => { - inline_fluent!( - "{$front_matter}: encountered {$value}, but expected a function pointer" - ) + msg!("{$front_matter}: encountered {$value}, but expected a function pointer") } } } fn add_args(self, err: &mut Diag<'_, G>) { - use rustc_errors::inline_fluent; + use rustc_errors::msg; use rustc_middle::mir::interpret::ValidationErrorKind::*; if let PointerAsInt { .. } | PartialPointer = self.kind { - err.help(inline_fluent!("this code performed an operation that depends on the underlying bytes representing a pointer")); - err.help(inline_fluent!("the absolute address of a pointer is not known at compile-time, so such operations are not supported")); + 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( - inline_fluent!("constructing invalid value at {$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( - inline_fluent!("constructing invalid value"), - [].into_iter(), - ) + err.dcx.eagerly_translate_to_string(msg!("constructing invalid value"), [].into_iter()) }; err.arg("front_matter", message); @@ -1115,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 { - inline_fluent!("less or equal to {$hi}, or greater or equal to {$lo}") + msg!("less or equal to {$hi}, or greater or equal to {$lo}") } else if lo == hi { - inline_fluent!("equal to {$lo}") + msg!("equal to {$lo}") } else if lo == 0 { assert!(hi < max_hi, "should not be printing if the range covers everything"); - inline_fluent!("less or equal to {$hi}") + msg!("less or equal to {$hi}") } else if hi == max_hi { assert!(lo > 0, "should not be printing if the range covers everything"); - inline_fluent!("greater or equal to {$lo}") + msg!("greater or equal to {$lo}") } else { - inline_fluent!("in the range {$lo}..={$hi}") + msg!("in the range {$lo}..={$hi}") }; let args = [ @@ -1143,17 +1126,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { - ExpectedKind::Reference => inline_fluent!("expected a reference"), - ExpectedKind::Box => inline_fluent!("expected a box"), - ExpectedKind::RawPtr => inline_fluent!("expected a raw pointer"), - ExpectedKind::InitScalar => inline_fluent!("expected initialized scalar value"), - ExpectedKind::Bool => inline_fluent!("expected a boolean"), - ExpectedKind::Char => inline_fluent!("expected a unicode scalar value"), - ExpectedKind::Float => inline_fluent!("expected a floating point number"), - ExpectedKind::Int => inline_fluent!("expected an integer"), - ExpectedKind::FnPtr => inline_fluent!("expected a function pointer"), - ExpectedKind::EnumTag => inline_fluent!("expected a valid enum tag"), - ExpectedKind::Str => inline_fluent!("expected a string"), + 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); @@ -1207,14 +1190,14 @@ impl ReportErrorExt for UnsupportedOpInfo { } UnsupportedOpInfo::UnsizedLocal => "unsized locals are not supported".into(), UnsupportedOpInfo::ReadPartialPointer(_) => { - inline_fluent!("unable to read parts of a pointer from memory at {$ptr}") + msg!("unable to read parts of a pointer from memory at {$ptr}") } UnsupportedOpInfo::ReadPointerAsInt(_) => "unable to turn pointer into integer".into(), UnsupportedOpInfo::ThreadLocalStatic(_) => { - inline_fluent!("cannot access thread local static `{$did}`") + msg!("cannot access thread local static `{$did}`") } UnsupportedOpInfo::ExternStatic(_) => { - inline_fluent!("cannot access extern static `{$did}`") + msg!("cannot access extern static `{$did}`") } } .into() diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ffa7b09205d5..b17740f57f78 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -6,7 +6,7 @@ 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::inline_fluent; +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}; @@ -297,9 +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!(inline_fluent!( - "calling a function with fewer arguments than it requires" - )); + 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 @@ -366,7 +364,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if caller_fn_abi.conv != callee_fn_abi.conv { throw_ub_custom!( - rustc_errors::inline_fluent!( + rustc_errors::msg!( "calling a function with calling convention \"{$callee_conv}\" using calling convention \"{$caller_conv}\"" ), callee_conv = format!("{}", callee_fn_abi.conv), @@ -499,9 +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!(inline_fluent!( - "calling a function with more arguments than it expected" - )); + 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)? { @@ -701,7 +697,7 @@ 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!(inline_fluent!( + throw_ub_custom!(msg!( "`dyn` call trying to call something that is not a method" )); }; @@ -900,7 +896,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } ); if unwinding && self.frame_idx() == 0 { - throw_ub_custom!(inline_fluent!("unwinding past the topmost frame of the stack")); + 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 44ca20ab4c03..6ea83167157c 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -2,7 +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::inline_fluent; +use rustc_errors::msg; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; @@ -139,7 +139,7 @@ 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!( - inline_fluent!( + msg!( "transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}`" ), src_bytes = src.layout.size.bytes(), diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 8c9a79abe48d..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, inline_fluent}; +use rustc_errors::{DiagCtxtHandle, msg}; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; @@ -555,7 +555,7 @@ 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!(inline_fluent!( + throw_ub_custom!(msg!( "unwinding past a stack frame that does not allow unwinding" )); } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c70038f5b18f..c9a3b578e793 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,7 +7,7 @@ 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::inline_fluent; +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}; @@ -443,7 +443,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { _ => { // Not into the same allocation -- this is UB. throw_ub_custom!( - inline_fluent!( + msg!( "`{$name}` called on two different pointers that are not both derived from the same allocation" ), name = intrinsic_name, @@ -466,7 +466,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( - inline_fluent!( + msg!( "`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> [true] address *[false] offset @@ -483,7 +483,7 @@ 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!( - inline_fluent!( + msg!( "`{$name}` called when first pointer is too far before second" ), name = intrinsic_name, @@ -497,7 +497,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // because they were more than isize::MAX apart. if dist < 0 { throw_ub_custom!( - inline_fluent!( + msg!( "`{$name}` called when first pointer is too far ahead of second" ), name = intrinsic_name, @@ -518,12 +518,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { && a_alloc_id == b_alloc_id { err_ub_custom!( - inline_fluent!("`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation"), + 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!( - inline_fluent!("`{$name}` called on two different pointers that are not both derived from the same allocation"), + msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) } @@ -538,7 +538,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .map_err_kind(|_| { // Make the error more specific. err_ub_custom!( - inline_fluent!("`{$name}` called on two different pointers that are not both derived from the same allocation"), + msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) })?; @@ -768,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!(inline_fluent!("`assume` called with `false`")); + throw_ub_custom!(msg!("`assume` called with `false`")); } interp_ok(()) } @@ -798,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!(inline_fluent!("`{$name}` called on 0"), 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, @@ -831,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!( - inline_fluent!("exact_div: {$a} cannot be divided by {$b} without remainder"), + msg!("exact_div: {$a} cannot be divided by {$b} without remainder"), a = format!("{a}"), b = format!("{b}") ) @@ -916,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!( - inline_fluent!("overflow computing total size of `{$name}`"), + msg!("overflow computing total size of `{$name}`"), name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" } ) })?; @@ -980,10 +980,7 @@ 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!( - inline_fluent!("overflow computing total size of `{$name}`"), - name = name - ) + err_ub_custom!(msg!("overflow computing total size of `{$name}`"), name = name) })?; let bytes = std::iter::repeat_n(byte, len.bytes_usize()); diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 200155ab010e..0049feee523c 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,7 +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::inline_fluent; +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}; @@ -291,7 +291,7 @@ 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!( - inline_fluent!( + msg!( "{$kind -> [dealloc] deallocating [realloc] reallocating @@ -377,7 +377,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if offset.bytes() != 0 { throw_ub_custom!( - inline_fluent!( + msg!( "{$kind -> [dealloc] deallocating [realloc] reallocating @@ -394,7 +394,7 @@ 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!( - inline_fluent!( + msg!( "deallocating {$alloc_id}, which is {$kind -> [fn] a function [vtable] a vtable @@ -408,7 +408,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } Some(GlobalAlloc::VTable(..)) => { err_ub_custom!( - inline_fluent!( + msg!( "deallocating {$alloc_id}, which is {$kind -> [fn] a function [vtable] a vtable @@ -422,7 +422,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } Some(GlobalAlloc::TypeId { .. }) => { err_ub_custom!( - inline_fluent!( + msg!( "deallocating {$alloc_id}, which is {$kind -> [fn] a function [vtable] a vtable @@ -436,7 +436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { err_ub_custom!( - inline_fluent!( + msg!( "deallocating {$alloc_id}, which is {$kind -> [fn] a function [vtable] a vtable @@ -454,14 +454,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; if alloc.mutability.is_not() { - throw_ub_custom!( - inline_fluent!("deallocating immutable allocation {$alloc}"), - alloc = alloc_id, - ); + throw_ub_custom!(msg!("deallocating immutable allocation {$alloc}"), alloc = alloc_id,); } if alloc_kind != kind { throw_ub_custom!( - inline_fluent!( + msg!( "deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation" ), alloc = alloc_id, @@ -472,7 +469,7 @@ 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!( - inline_fluent!( + msg!( "incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found}" ), alloc = alloc_id, @@ -1593,7 +1590,7 @@ 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!(inline_fluent!( + throw_ub_custom!(msg!( "`copy_nonoverlapping` called on overlapping ranges" )); } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index ae3e33498ea1..42c605d34814 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -6,9 +6,7 @@ use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; use crate::diagnostic::DiagLocation; -use crate::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, inline_fluent, -}; +use crate::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, msg}; impl IntoDiagArg for DiagLocation { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { @@ -43,24 +41,24 @@ 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, inline_fluent!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}")) + 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, inline_fluent!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}")) + 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, inline_fluent!("missing alignment for `{$cause}` in \"data-layout\"")) + Diag::new(dcx, level, msg!("missing alignment for `{$cause}` in \"data-layout\"")) .with_arg("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - Diag::new(dcx, level, inline_fluent!( + 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 @@ -72,21 +70,21 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { .with_arg("align", err.align()) } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - Diag::new(dcx, level, inline_fluent!( + 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, inline_fluent!( + 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, inline_fluent!("{$err}")).with_arg("err", err) + Diag::new(dcx, level, msg!("{$err}")).with_arg("err", err) } TargetDataLayoutErrors::UnknownPointerSpecification { err } => { - Diag::new(dcx, level, inline_fluent!("unknown pointer specification `{$err}` in datalayout string")) + Diag::new(dcx, level, msg!("unknown pointer specification `{$err}` in datalayout string")) .with_arg("err", err) } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 1a95b7db60a7..989d28eac455 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -61,7 +61,7 @@ pub use rustc_error_messages::{ use rustc_hashes::Hash128; use rustc_lint_defs::LintExpectationId; pub use rustc_lint_defs::{Applicability, listify, pluralize}; -pub use rustc_macros::inline_fluent; +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}; @@ -1514,7 +1514,7 @@ impl DiagCtxtInner { // the usual `Diag`/`DiagCtxt` level, so we must augment `bug` // in a lower-level fashion. bug.arg("level", bug.level); - let msg = inline_fluent!( + 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 @@ -1558,13 +1558,13 @@ impl DelayedDiagInner { // lower-level fashion. let mut diag = self.inner; let msg = match self.note.status() { - BacktraceStatus::Captured => inline_fluent!( + 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. - _ => inline_fluent!("delayed at {$emitted_at} - {$note}"), + _ => msg!("delayed at {$emitted_at} - {$note}"), }; diag.arg("emitted_at", diag.emitted_at.clone()); diag.arg("note", self.note); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index c9d0319a97c5..c7d2e273a76f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -15,7 +15,7 @@ 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::inline_fluent; +use rustc_errors::msg; use rustc_feature::{ ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES, @@ -433,14 +433,14 @@ impl<'a> StripUnconfigured<'a> { &self.sess, sym::stmt_expr_attributes, attr.span, - inline_fluent!("attributes on expressions are experimental"), + msg!("attributes on expressions are experimental"), ); if attr.is_doc_comment() { err.help(if attr.style == AttrStyle::Outer { - inline_fluent!("`///` is used for outer documentation comments; for a plain comment, use `//`") + msg!("`///` is used for outer documentation comments; for a plain comment, use `//`") } else { - inline_fluent!("`//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`") + 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/expand.rs b/compiler/rustc_expand/src/expand.rs index da678ff70346..76a9a6f9d03d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -19,7 +19,7 @@ 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, inline_fluent}; +use rustc_errors::{PResult, msg}; use rustc_feature::Features; use rustc_hir::Target; use rustc_hir::def::MacroKinds; @@ -1051,7 +1051,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.sess, sym::proc_macro_hygiene, item.span, - inline_fluent!("file modules in proc macro input are unstable"), + msg!("file modules in proc macro input are unstable"), ) .emit(); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 32af13b88a1a..b1daf2f2be9c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -5,9 +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, inline_fluent, 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}; @@ -1771,7 +1769,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types` feature", ), ) - .with_help(inline_fluent!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) + .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) @@ -1795,7 +1793,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types_pointers` feature", ), ) - .with_help(inline_fluent!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) + .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() } _ => diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index fb79789df76e..4b0f1016029e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -4,7 +4,7 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, inline_fluent, listify, + MultiSpan, listify, msg, }; use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -444,7 +444,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { let mut err = Diag::new( dcx, level, - inline_fluent!( + msg!( "the {$descr} {$parameterCount -> [one] parameter *[other] parameters @@ -455,7 +455,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { err.code(E0393); err.span_label( self.def_span, - inline_fluent!( + msg!( "{$descr} {$parameterCount -> [one] parameter *[other] parameters @@ -511,7 +511,7 @@ 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(), - inline_fluent!( + msg!( "explicitly specify the {$descr} {$parameterCount -> [one] parameter *[other] parameters @@ -533,7 +533,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { if !suggested { err.span_label( self.span, - inline_fluent!( + msg!( "missing {$parameterCount -> [one] reference *[other] references @@ -542,7 +542,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { ); } - err.note(inline_fluent!( + err.note(msg!( "because the parameter {$parameterCount -> [one] default references *[other] defaults reference 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 36dae4c2798e..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,8 +3,8 @@ 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, inline_fluent, listify, - pluralize, struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, msg, pluralize, + struct_span_code_err, }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -304,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, - inline_fluent!("...and changing the associated {$assoc_kind} name"), + msg!("...and changing the associated {$assoc_kind} name"), suggested_name, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index e20d5cdf2889..7ad0b85ee53f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey, inline_fluent}; +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; @@ -836,12 +836,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (Some((_, kind, path)), _) => { err.arg("kind", kind); err.arg("path", path); - Some(inline_fluent!("{$kind} `{$path}` defined here")) + 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); - inline_fluent!("`{$func}` defined here returns `{$ty}`") + msg!("`{$func}` defined here returns `{$ty}`") }) } _ => { @@ -850,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(inline_fluent!("`{$local_name}` has type `{$ty}`")) + 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(inline_fluent!("`{$path}` defined here")) + Some(msg!("`{$path}` defined here")) } _ => { err.arg("path", callee_ty); - Some(inline_fluent!("`{$path}` defined here")) + Some(msg!("`{$path}` defined here")) } } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index ad0467ddec96..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, inline_fluent, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir as hir; use rustc_hir::ExprKind; @@ -343,28 +343,24 @@ impl Subdiagnostic for TypeMismatchFruTypo { if self.expr_span.between(self.fru_span).is_empty() { diag.span_note( self.expr_span.to(self.fru_span), - inline_fluent!( - "this expression may have been misinterpreted as a `..` range expression" - ), + 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, - inline_fluent!("this expression does not end in a comma..."), + msg!("this expression does not end in a comma..."), ); - multispan.push_span_label(self.fru_span, inline_fluent!("... so this is interpreted as a `..` range expression, instead of functional record update syntax")); + 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, - inline_fluent!( - "this expression may have been misinterpreted as a `..` range expression" - ), + msg!("this expression may have been misinterpreted as a `..` range expression"), ); } diag.span_suggestion( self.expr_span.shrink_to_hi(), - inline_fluent!( + msg!( "to set the remaining fields{$expr -> [NONE]{\"\"} *[other] {\" \"}from `{$expr}` @@ -651,28 +647,19 @@ impl Subdiagnostic for RemoveSemiForCoerce { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label( self.expr, - inline_fluent!( - "this could be implicitly returned but it is a statement, not a tail expression" - ), - ); - multispan.push_span_label( - self.ret, - inline_fluent!("the `match` arms can conform to this return type"), + 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, - inline_fluent!( - "the `match` is a statement because of this semicolon, consider removing it" - ), - ); - diag.span_note( - multispan, - inline_fluent!("you might have meant to return the `match` expression"), + 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, - inline_fluent!("remove this semicolon"), + msg!("remove this semicolon"), "", Applicability::MaybeIncorrect, ); @@ -802,24 +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, inline_fluent!("`break` with value from a `{$kind}` 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, - inline_fluent!("can only break with a value inside `loop` or breakable block"), + msg!("can only break with a value inside `loop` or breakable block"), ); if let Some(head) = self.head { - diag.span_label( - head, - inline_fluent!("you can't `break` with a value in a `{$kind}` loop"), - ); + diag.span_label(head, msg!("you can't `break` with a value in a `{$kind}` loop")); } diag.span_suggestion( self.span, - inline_fluent!("use `break` on its own without a value inside this `{$kind}` loop"), + msg!("use `break` on its own without a value inside this `{$kind}` loop"), self.suggestion, Applicability::MaybeIncorrect, ); @@ -837,9 +820,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { _ => { diag.span_suggestion( self.break_expr_span, - inline_fluent!( - "alternatively, you might have meant to use the available loop label" - ), + msg!("alternatively, you might have meant to use the available loop label"), label.ident, Applicability::MaybeIncorrect, ); @@ -1007,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(inline_fluent!("needs more type information")); + let msg = diag.eagerly_translate(msg!("needs more type information")); diag.span_label(span, msg); - let msg = diag.eagerly_translate(inline_fluent!("the type information given here is insufficient to check whether the pointer cast is valid")); + 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(inline_fluent!("the type information given here is insufficient to check whether the pointer cast is valid")); + 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); } } @@ -1302,20 +1283,18 @@ impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { let mut diag = Diag::new( dcx, level, - inline_fluent!("naked functions must contain a single `naked_asm!` invocation"), + 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, - inline_fluent!( - "multiple `naked_asm!` invocations are not allowed in naked functions" - ), + msg!("multiple `naked_asm!` invocations are not allowed in naked functions"), ); } for span in self.non_asms.iter() { - diag.span_label(*span, inline_fluent!("not allowed in naked functions")); + diag.span_label(*span, msg!("not allowed in naked functions")); } diag } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index c703057a30fb..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, inline_fluent, 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::{ @@ -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(), - inline_fluent!("try converting the passed type into a `&str`"), + msg!("try converting the passed type into a `&str`"), sugg, Applicability::MachineApplicable, ); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ef21b3f573be..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, inline_fluent}; +use rustc_errors::{Applicability, LintDiagnostic, msg}; use rustc_feature::GateIssue; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, DocAttribute}; @@ -2653,10 +2653,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { let msg = match init { InitKind::Zeroed => { - inline_fluent!("the type `{$ty}` does not permit zero-initialization") + msg!("the type `{$ty}` does not permit zero-initialization") } InitKind::Uninit => { - inline_fluent!("the type `{$ty}` does not permit being left uninitialized") + msg!("the type `{$ty}` does not permit being left uninitialized") } }; let sub = BuiltinUnpermittedTypeInitSub { err }; diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index b0154bed1a51..51b97bc67d2c 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic, inline_fluent}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -27,17 +27,17 @@ impl Subdiagnostic for OverruledAttributeSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverruledAttributeSub::DefaultSource { id } => { - diag.note(inline_fluent!("`forbid` lint level is the default for {$id}")); + diag.note(msg!("`forbid` lint level is the default for {$id}")); diag.arg("id", id); } OverruledAttributeSub::NodeSource { span, reason } => { - diag.span_label(span, inline_fluent!("`forbid` level set here")); + diag.span_label(span, msg!("`forbid` level set here")); if let Some(rationale) = reason { diag.note(rationale.to_string()); } } OverruledAttributeSub::CommandLineSource => { - diag.note(inline_fluent!("`forbid` lint level was set on command line")); + diag.note(msg!("`forbid` lint level was set on command line")); } } } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 8569070a43ca..7899d4690ea5 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -3,9 +3,7 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use rustc_ast::Recovered; -use rustc_errors::{ - Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle, inline_fluent, -}; +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; @@ -356,7 +354,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat_n('}', closing_brackets.count)) .collect(), )); - let msg = diag.eagerly_translate(inline_fluent!( + 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( diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index aef0021d0660..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, inline_fluent}; +use rustc_errors::{LintDiagnostic, Subdiagnostic, msg}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -435,23 +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(inline_fluent!( + 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, - inline_fluent!( + msg!( "specifically, {$num_captured -> [one] this lifetime is *[other] these lifetimes are } in scope but not mentioned in the type's bounds" ), ) - .note(inline_fluent!( - "all lifetimes in scope will be captured by `impl Trait`s in edition 2024" - )); + .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); } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index cebe1a5dc373..048118875712 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, inline_fluent}; +use rustc_errors::{Diag, LintDiagnostic, MultiSpan, msg}; use rustc_feature::{Features, GateIssue}; use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; @@ -941,9 +941,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(inline_fluent!("unknown lint: `{$name}`")); + lint.primary_message(msg!("unknown lint: `{$name}`")); lint.arg("name", lint_id.lint.name_lower()); - lint.note(inline_fluent!("the `{$name}` lint is unstable")); + 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/lints.rs b/compiler/rustc_lint/src/lints.rs index 8c6507f68231..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, inline_fluent, + EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, msg, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -228,7 +228,7 @@ 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(inline_fluent!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation")); + 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)); } } @@ -298,11 +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(inline_fluent!("`#[track_caller]` on async functions is a no-op")); - diag.span_label( - self.label, - inline_fluent!("this function will not propagate the caller location"), - ); + 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, @@ -345,20 +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 { - inline_fluent!("where clauses on type aliases are not enforced") + msg!("where clauses on type aliases are not enforced") } else { - inline_fluent!("bounds on generic parameters in type aliases are not enforced") + msg!("bounds on generic parameters in type aliases are not enforced") }); - diag.span_label( - self.label, - inline_fluent!("will not be checked at usage sites of the type alias"), - ); - diag.note(inline_fluent!( + 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(inline_fluent!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); + 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 @@ -385,9 +379,9 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { diag.arg("count", self.suggestions.len()); diag.multipart_suggestion( if self.in_where_clause { - inline_fluent!("remove this where clause") + msg!("remove this where clause") } else { - inline_fluent!( + msg!( "remove {$count -> [one] this bound *[other] these bounds @@ -410,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( - inline_fluent!("fully qualify this associated type"), + msg!("fully qualify this associated type"), vec![ (qself.shrink_to_lo(), "<".into()), (qself.shrink_to_hi(), " as /* Trait */>".into()), @@ -551,15 +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, - inline_fluent!("this code causes undefined behavior when executed"), - ); + 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, - inline_fluent!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), + msg!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), ); } self.sub.add_to_diag(diag); @@ -1183,7 +1174,7 @@ impl Subdiagnostic for NonBindingLetSub { let prefix = if self.is_assign_desugar { "let " } else { "" }; diag.span_suggestion_verbose( self.suggestion, - inline_fluent!( + msg!( "consider binding to an unused variable to avoid immediately dropping the value" ), format!("{prefix}_unused"), @@ -1192,14 +1183,14 @@ impl Subdiagnostic for NonBindingLetSub { } else { diag.span_help( self.suggestion, - inline_fluent!( + 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( - inline_fluent!("consider immediately dropping the value"), + msg!("consider immediately dropping the value"), vec![ (drop_fn_start_end.0, "drop(".to_string()), (drop_fn_start_end.1, ")".to_string()), @@ -1207,7 +1198,7 @@ impl Subdiagnostic for NonBindingLetSub { Applicability::MachineApplicable, ); } else { - diag.help(inline_fluent!( + diag.help(msg!( "consider immediately dropping the value using `drop(..)` after the `let` statement" )); } @@ -1454,7 +1445,7 @@ 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(inline_fluent!( + diag.primary_message(msg!( "panic message contains {$count -> [one] an unused *[other] unused @@ -1464,11 +1455,11 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { }" )); diag.arg("count", self.count); - diag.note(inline_fluent!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); + 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(), - inline_fluent!( + msg!( "add the missing {$count -> [one] argument *[other] arguments @@ -1479,9 +1470,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { ); diag.span_suggestion( span.shrink_to_lo(), - inline_fluent!( - r#"or add a "{"{"}{"}"}" format string to use the message literally"# - ), + msg!(r#"or add a "{"{"}{"}"}" format string to use the message literally"#), "\"{}\", ", Applicability::MachineApplicable, ); @@ -1558,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, inline_fluent!("should have a snake_case name")); + diag.span_label(span, msg!("should have a snake_case name")); } NonSnakeCaseDiagSub::Help => { - diag.help(inline_fluent!("convert the identifier to snake case: `{$sc}`")); + diag.help(msg!("convert the identifier to snake case: `{$sc}`")); } NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - inline_fluent!("convert the identifier to snake case"), + msg!("convert the identifier to snake case"), suggestion, Applicability::MaybeIncorrect, ); @@ -1574,18 +1563,16 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - inline_fluent!( - "rename the identifier or convert it to a snake case raw identifier" - ), + msg!("rename the identifier or convert it to a snake case raw identifier"), suggestion, Applicability::MaybeIncorrect, ); } NonSnakeCaseDiagSub::SuggestionAndNote { span } => { - diag.note(inline_fluent!("`{$sc}` cannot be used as a raw identifier")); + diag.note(msg!("`{$sc}` cannot be used as a raw identifier")); diag.span_suggestion( span, - inline_fluent!("rename the identifier"), + msg!("rename the identifier"), "", Applicability::MaybeIncorrect, ); @@ -1703,7 +1690,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, macro_to_change, } => { - diag.primary_message(inline_fluent!("non-local `impl` definition, `impl` blocks should be written at the same level as their item")); + 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); @@ -1711,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(inline_fluent!("the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed")); + 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(inline_fluent!("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`")); + 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(inline_fluent!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); + diag.help(msg!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); } if let Some(const_anon) = const_anon { - diag.note(inline_fluent!("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")); + 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, - inline_fluent!("use a const-anon item to suppress this lint"), + msg!("use a const-anon item to suppress this lint"), "_", Applicability::MachineApplicable, ); @@ -1742,15 +1729,15 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, cargo_update, } => { - diag.primary_message(inline_fluent!("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")); + 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(inline_fluent!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); + diag.help(msg!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); } else { - diag.help(inline_fluent!( + 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 @@ -1758,7 +1745,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { )); } - diag.note(inline_fluent!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); + 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); @@ -1861,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(inline_fluent!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")); + 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)); } @@ -1875,7 +1862,7 @@ 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(inline_fluent!("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.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)); } } @@ -2317,18 +2304,16 @@ 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(inline_fluent!( - "`extern` {$desc} uses type `{$ty}`, which is not FFI-safe" - )); + 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, inline_fluent!("not FFI-safe")); + 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, inline_fluent!("the type is defined here")); + diag.span_note(note, msg!("the type is defined here")); } } } @@ -2491,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(inline_fluent!("unused {$pre}`{$def}`{$post} that must be used")); + 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)); @@ -2575,10 +2560,10 @@ pub(crate) struct AsyncFnInTraitDiag { impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(inline_fluent!("use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified")); - diag.note(inline_fluent!("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`")); + 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(inline_fluent!("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); + 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); } } } @@ -3450,44 +3435,44 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta } LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { - inline_fluent!("hiding a lifetime that's elided elsewhere is confusing") + msg!("hiding a lifetime that's elided elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { - inline_fluent!("hiding a lifetime that's named elsewhere is confusing") + msg!("hiding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { - inline_fluent!("eliding a lifetime that's named elsewhere is confusing") + msg!("eliding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { - inline_fluent!("hiding or eliding a lifetime that's named elsewhere is confusing") + 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, inline_fluent!("the lifetime is hidden here")); + diag.span_label(s, msg!("the lifetime is hidden here")); } for s in self.inputs.elided { - diag.span_label(s, inline_fluent!("the lifetime is elided here")); + diag.span_label(s, msg!("the lifetime is elided here")); } for s in self.inputs.named { - diag.span_label(s, inline_fluent!("the lifetime is named here")); + diag.span_label(s, msg!("the lifetime is named here")); } for s in self.outputs.hidden { - diag.span_label(s, inline_fluent!("the same lifetime is hidden here")); + diag.span_label(s, msg!("the same lifetime is hidden here")); } for s in self.outputs.elided { - diag.span_label(s, inline_fluent!("the same lifetime is elided here")); + diag.span_label(s, msg!("the same lifetime is elided here")); } for s in self.outputs.named { - diag.span_label(s, inline_fluent!("the same lifetime is named here")); + diag.span_label(s, msg!("the same lifetime is named here")); } - diag.help(inline_fluent!( + diag.help(msg!( "the same lifetime is referred to in inconsistent ways, making the signature confusing" )); @@ -3563,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( - inline_fluent!("remove the lifetime name from references"), + msg!("remove the lifetime name from references"), suggestions, applicability(optional_alternative), style(optional_alternative), @@ -3576,11 +3561,9 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { optional_alternative, } => { let message = if implicit_suggestions.is_empty() { - inline_fluent!("use `'_` for type paths") + msg!("use `'_` for type paths") } else { - inline_fluent!( - "remove the lifetime name from references and use `'_` for type paths" - ) + msg!("remove the lifetime name from references and use `'_` for type paths") }; let implicit_suggestions = @@ -3599,8 +3582,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { Explicit { lifetime_name, suggestions, optional_alternative } => { diag.arg("lifetime_name", lifetime_name); - let msg = - diag.eagerly_translate(inline_fluent!("consistently use `{$lifetime_name}`")); + let msg = diag.eagerly_translate(msg!("consistently use `{$lifetime_name}`")); diag.remove_arg("lifetime_name"); diag.multipart_suggestion_with_style( msg, diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 10a37637400b..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, inline_fluent}; +use rustc_errors::{Applicability, msg}; use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::{bug, ty}; @@ -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(inline_fluent!("panic message is not a string literal")); + lint.primary_message(msg!("panic message is not a string literal")); lint.arg("name", symbol); - lint.note(inline_fluent!("this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021")); - lint.note(inline_fluent!("for more information, see ")); + 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(inline_fluent!("the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here")); + 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( - inline_fluent!("remove the `format!(..)` macro call"), + 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(), - inline_fluent!(r#"add a "{"{"}{"}"}" format string to `Display` the message"#), + 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(), - inline_fluent!(r#"add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`"#), + msg!(r#"add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`"#), "\"{:?}\", ", fmt_applicability, ); @@ -196,7 +196,7 @@ 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( - inline_fluent!( + msg!( "{$already_suggested -> [true] or use *[false] use diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index fc7e5a821b02..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, inline_fluent}; +use rustc_errors::{MultiSpan, msg}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; @@ -210,7 +210,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { if !doctest { ms.push_span_label( cx.tcx.def_span(parent), - inline_fluent!( + 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/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index fb9b55efa220..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, inline_fluent}; +use rustc_errors::{DiagMessage, msg}; use rustc_hir::def::CtorKind; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg}; @@ -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(inline_fluent!("this enum is non-exhaustive")); + return ControlFlow::Break(msg!("this enum is non-exhaustive")); } } if variant.field_list_has_applicable_non_exhaustive() { - return ControlFlow::Break(inline_fluent!("this enum has non-exhaustive variants")); + return ControlFlow::Break(msg!("this enum has non-exhaustive variants")); } ControlFlow::Continue(()) @@ -426,7 +426,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else if transparent_with_all_zst_fields { FfiUnsafe { ty, - reason: inline_fluent!("this struct contains only zero-sized fields"), + reason: msg!("this struct contains only zero-sized fields"), help: None, } } else { @@ -464,7 +464,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else { return FfiUnsafe { ty, - reason: inline_fluent!("box cannot be represented as a single pointer"), + reason: msg!("box cannot be represented as a single pointer"), help: None, }; } @@ -480,10 +480,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { return FfiUnsafe { ty, - reason: inline_fluent!( - "`CStr`/`CString` do not have a guaranteed layout" - ), - help: Some(inline_fluent!( + 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()`" )), }; @@ -493,16 +491,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - inline_fluent!("this struct has unspecified layout") + msg!("this struct has unspecified layout") } else { - inline_fluent!("this union has unspecified layout") + msg!("this union has unspecified layout") }, help: if def.is_struct() { - Some(inline_fluent!( + Some(msg!( "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct" )) } else { - Some(inline_fluent!( + Some(msg!( "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union" )) }, @@ -513,9 +511,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - inline_fluent!("this struct is non-exhaustive") + msg!("this struct is non-exhaustive") } else { - inline_fluent!("this union is non-exhaustive") + msg!("this union is non-exhaustive") }, help: None, }; @@ -525,14 +523,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - inline_fluent!("this struct has no fields") + msg!("this struct has no fields") } else { - inline_fluent!("this union has no fields") + msg!("this union has no fields") }, help: if def.is_struct() { - Some(inline_fluent!("consider adding a member to this struct")) + Some(msg!("consider adding a member to this struct")) } else { - Some(inline_fluent!("consider adding a member to this union")) + Some(msg!("consider adding a member to this union")) }, }; } @@ -557,8 +555,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, - reason: inline_fluent!("enum has no representation hint"), - help: Some(inline_fluent!( + reason: msg!("enum has no representation hint"), + help: Some(msg!( "consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum" )), }; @@ -586,8 +584,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Char => FfiUnsafe { ty, - reason: inline_fluent!("the `char` type has no C equivalent"), - help: Some(inline_fluent!("consider using `u32` or `libc::wchar_t` instead")), + 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, @@ -599,26 +597,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Slice(_) => FfiUnsafe { ty, - reason: inline_fluent!("slices have no C equivalent"), - help: Some(inline_fluent!("consider using a raw pointer instead")), + reason: msg!("slices have no C equivalent"), + help: Some(msg!("consider using a raw pointer instead")), }, - ty::Dynamic(..) => FfiUnsafe { - ty, - reason: inline_fluent!("trait objects have no C equivalent"), - help: None, - }, + ty::Dynamic(..) => { + FfiUnsafe { ty, reason: msg!("trait objects have no C equivalent"), help: None } + } ty::Str => FfiUnsafe { ty, - reason: inline_fluent!("string slices have no C equivalent"), - help: Some(inline_fluent!("consider using `*const u8` and a length instead")), + reason: msg!("string slices have no C equivalent"), + help: Some(msg!("consider using `*const u8` and a length instead")), }, ty::Tuple(..) => FfiUnsafe { ty, - reason: inline_fluent!("tuples have unspecified layout"), - help: Some(inline_fluent!("consider using a struct instead")), + reason: msg!("tuples have unspecified layout"), + help: Some(msg!("consider using a struct instead")), }, ty::RawPtr(ty, _) | ty::Ref(_, ty, _) @@ -648,10 +644,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if sig.abi().is_rustic_abi() { return FfiUnsafe { ty, - reason: inline_fluent!( - "this function pointer has Rust-specific calling convention" - ), - help: Some(inline_fluent!( + reason: msg!("this function pointer has Rust-specific calling convention"), + help: Some(msg!( "consider using an `extern fn(...) -> ...` function pointer instead" )), }; @@ -677,11 +671,9 @@ 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: inline_fluent!("opaque types have no C equivalent"), - help: None, - }, + ty::Alias(ty::Opaque, ..) => { + 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, // so they are currently ignored for the purposes of this lint. @@ -693,9 +685,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::UnsafeBinder(_) => FfiUnsafe { ty, - reason: inline_fluent!( - "unsafe binders are incompatible with foreign function interfaces" - ), + reason: msg!("unsafe binders are incompatible with foreign function interfaces"), help: None, }, @@ -741,7 +731,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { Some(FfiResult::FfiUnsafe { ty, - reason: inline_fluent!("opaque types have no C equivalent"), + reason: msg!("opaque types have no C equivalent"), help: None, }) } else { @@ -754,8 +744,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let ty::Array(..) = ty.kind() { Some(FfiResult::FfiUnsafe { ty, - reason: inline_fluent!("passing raw arrays by value is not FFI-safe"), - help: Some(inline_fluent!("consider passing a pointer to the array")), + reason: msg!("passing raw arrays by value is not FFI-safe"), + help: Some(msg!("consider passing a pointer to the array")), }) } else { None @@ -934,7 +924,7 @@ impl<'tcx> ImproperCTypesLint { cx, ty, sp, - inline_fluent!("composed only of `PhantomData`"), + msg!("composed only of `PhantomData`"), None, fn_mode, ); diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index aef062a3d550..c0512e86bbcb 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,13 +1,13 @@ mod diagnostic; mod diagnostic_builder; mod error; -mod inline_fluent; mod message; +mod msg_macro; mod subdiagnostic; mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; -pub(super) use inline_fluent::inline_fluent; +pub(super) use msg_macro::msg_macro; use proc_macro2::TokenStream; use subdiagnostic::SubdiagnosticDerive; use synstructure::Structure; diff --git a/compiler/rustc_macros/src/diagnostics/inline_fluent.rs b/compiler/rustc_macros/src/diagnostics/msg_macro.rs similarity index 76% rename from compiler/rustc_macros/src/diagnostics/inline_fluent.rs rename to compiler/rustc_macros/src/diagnostics/msg_macro.rs index ab0ed6aa6e0e..66bc200707ef 100644 --- a/compiler/rustc_macros/src/diagnostics/inline_fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/msg_macro.rs @@ -2,7 +2,7 @@ use syn::{LitStr, parse_macro_input}; use crate::diagnostics::message::Message; -pub(crate) fn inline_fluent(input: proc_macro::TokenStream) -> proc_macro::TokenStream { +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() }; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 29551e5af6b6..e4f43a22738d 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -245,8 +245,8 @@ decl_derive!( /// /// This macro statically checks that the message is valid Fluent, but not that variables in the Fluent message actually exist. #[proc_macro] -pub fn inline_fluent(input: TokenStream) -> TokenStream { - diagnostics::inline_fluent(input) +pub fn msg(input: TokenStream) -> TokenStream { + diagnostics::msg_macro(input) } decl_derive! { diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index e8b6cb8d02f6..7320ad98d113 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -2,7 +2,7 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, inline_fluent}; +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}; @@ -360,7 +360,7 @@ impl Diagnostic<'_, G> for MultipleCandidates { let mut diag = Diag::new( dcx, level, - inline_fluent!("multiple candidates for `{$flavor}` dependency `{$crate_name}` found"), + msg!("multiple candidates for `{$flavor}` dependency `{$crate_name}` found"), ); diag.arg("crate_name", self.crate_name); diag.arg("flavor", self.flavor); @@ -474,7 +474,7 @@ impl Diagnostic<'_, G> for InvalidMetadataFiles { let mut diag = Diag::new( dcx, level, - inline_fluent!("found invalid metadata files for crate `{$crate_name}`{$add_info}"), + 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); @@ -503,11 +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, - inline_fluent!("can't find crate for `{$crate_name}`{$add_info}"), - ); + 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); @@ -516,9 +513,9 @@ 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(inline_fluent!("the `{$locator_triple}` target may not be installed")); + diag.note(msg!("the `{$locator_triple}` target may not be installed")); } else { - diag.note(inline_fluent!( + diag.note(msg!( "the `{$locator_triple}` target may not support the standard library" )); } @@ -528,12 +525,12 @@ 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(inline_fluent!("consider adding the standard library to the sysroot with `x build library --target {$locator_triple}`")); + 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(inline_fluent!( + diag.help(msg!( "consider downloading the target with `rustup target add {$locator_triple}`" )); } @@ -544,21 +541,19 @@ 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(inline_fluent!("`std` is required by `{$current_crate}` because it does not declare `#![no_std]`")); + 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(inline_fluent!("consider building the standard library from source with `cargo build -Zbuild-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(inline_fluent!( - "the compiler may have been built without the profiler runtime" - )); + 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(inline_fluent!("maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`")); + 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, inline_fluent!("can't find crate")); + diag.span_label(self.span, msg!("can't find crate")); diag } } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 903ef645207d..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, inline_fluent}; +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}; @@ -128,20 +128,20 @@ 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 => inline_fluent!( + DeprecatedSinceKind::InEffect => msg!( "use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} *[other] {\"\"} }" ), - DeprecatedSinceKind::InFuture => inline_fluent!( + DeprecatedSinceKind::InFuture => msg!( "use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> [true] : {$note} *[other] {\"\"} }" ), DeprecatedSinceKind::InVersion(_) => { - inline_fluent!( + msg!( "use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> [true] : {$note} *[other] {\"\"} diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 8032d6b9316c..1e7729bd8d65 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -337,25 +337,25 @@ impl AssertKind { use AssertKind::*; match self { - BoundsCheck { .. } => inline_fluent!( - "index out of bounds: the length is {$len} but the index is {$index}" - ), + BoundsCheck { .. } => { + msg!("index out of bounds: the length is {$len} but the index is {$index}") + } Overflow(BinOp::Shl, _, _) => { - inline_fluent!("attempt to shift left by `{$val}`, which would overflow") + msg!("attempt to shift left by `{$val}`, which would overflow") } Overflow(BinOp::Shr, _, _) => { - inline_fluent!("attempt to shift right by `{$val}`, which would overflow") + msg!("attempt to shift right by `{$val}`, which would overflow") } Overflow(_, _, _) => { - inline_fluent!("attempt to compute `{$left} {$op} {$right}`, which would 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") } - OverflowNeg(_) => inline_fluent!("attempt to negate `{$val}`, which would overflow"), - DivisionByZero(_) => inline_fluent!("attempt to divide `{$val}` by zero"), - RemainderByZero(_) => inline_fluent!( - "attempt to calculate the remainder of `{$val}` with a divisor of zero" - ), ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - inline_fluent!("`async fn` resumed after completion") + msg!("`async fn` resumed after completion") } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() @@ -364,40 +364,38 @@ impl AssertKind { bug!("gen blocks can be resumed after they return and will keep returning `None`") } ResumedAfterReturn(CoroutineKind::Coroutine(_)) => { - inline_fluent!("coroutine resumed after completion") + msg!("coroutine resumed after completion") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - inline_fluent!("`async fn` resumed after panicking") + msg!("`async fn` resumed after panicking") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - inline_fluent!("`gen` fn or block cannot be further iterated on after it panicked") + msg!("`gen` fn or block cannot be further iterated on after it panicked") } ResumedAfterPanic(CoroutineKind::Coroutine(_)) => { - inline_fluent!("coroutine resumed after panicking") + msg!("coroutine resumed after panicking") } - NullPointerDereference => inline_fluent!("null pointer dereference occurred"), + NullPointerDereference => msg!("null pointer dereference occurred"), InvalidEnumConstruction(_) => { - inline_fluent!("trying to construct an enum from an invalid value `{$source}`") + msg!("trying to construct an enum from an invalid value `{$source}`") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - inline_fluent!("`async fn` resumed after async drop") + msg!("`async fn` resumed after async drop") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - inline_fluent!( - "`gen` fn or block cannot be further iterated on after it async dropped" - ) + msg!("`gen` fn or block cannot be further iterated on after it async dropped") } ResumedAfterDrop(CoroutineKind::Coroutine(_)) => { - inline_fluent!("coroutine resumed after async drop") + msg!("coroutine resumed after async drop") } - MisalignedPointerDereference { .. } => inline_fluent!( + MisalignedPointerDereference { .. } => msg!( "misaligned pointer dereference: address must be a multiple of {$required} but is {$found}" ), } @@ -512,7 +510,7 @@ impl<'tcx> TerminatorKind<'tcx> { } pub use helper::*; -use rustc_errors::inline_fluent; +use rustc_errors::msg; mod helper { use super::*; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d3b4654a8d79..be41a556f852 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -8,8 +8,7 @@ use rustc_abi::{ }; use rustc_error_messages::DiagMessage; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, - inline_fluent, + Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg, }; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; @@ -270,24 +269,22 @@ impl<'tcx> LayoutError<'tcx> { use LayoutError::*; match self { - Unknown(_) => inline_fluent!("the type `{$ty}` has an unknown layout"), + Unknown(_) => msg!("the type `{$ty}` has an unknown layout"), SizeOverflow(_) => { - inline_fluent!("values of the type `{$ty}` are too big for the target architecture") + msg!("values of the type `{$ty}` are too big for the target architecture") } InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { - inline_fluent!( - "the SIMD type `{$ty}` has more elements than the limit {$max_lanes}" - ) + msg!("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}") } InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => { - inline_fluent!("the SIMD type `{$ty}` has zero elements") + msg!("the SIMD type `{$ty}` has zero elements") } - TooGeneric(_) => inline_fluent!("the type `{$ty}` does not have a fixed layout"), - NormalizationFailure(_, _) => inline_fluent!( + 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(_) => inline_fluent!("a cycle occurred during layout computation"), - ReferencesError(_) => inline_fluent!("the type has an unknown layout"), + Cycle(_) => msg!("a cycle occurred during layout computation"), + ReferencesError(_) => msg!("the type has an unknown layout"), } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index fed0435f59a0..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, inline_fluent, + MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -619,14 +619,12 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_note( self.signature_span, - inline_fluent!( - "an unsafe function restricts its caller, but its body is safe by default" - ), + 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( - inline_fluent!("consider wrapping the function body in an unsafe block"), + msg!("consider wrapping the function body in an unsafe block"), vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], Applicability::MachineApplicable, ); @@ -660,11 +658,8 @@ 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, - inline_fluent!("non-exhaustive patterns: type `{$ty}` is non-empty"), - ); + let mut diag = + 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(); @@ -684,22 +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, inline_fluent!("`{$peeled_ty}` defined here")); + 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(inline_fluent!( + diag.note(msg!( "the matched value is of type `{$ty}`, which is marked as non-exhaustive" )); } else { - diag.note(inline_fluent!("the matched value is of type `{$ty}`")); + 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(inline_fluent!("references are always considered inhabited")); + diag.note(msg!("references are always considered inhabited")); } } @@ -714,12 +709,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo }; diag.span_suggestion_verbose( braces_span, - inline_fluent!("ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown"), + 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(inline_fluent!( + diag.help(msg!( "ensure that all possible cases are being handled by adding a match arm with a wildcard pattern" )); } @@ -1240,10 +1235,10 @@ 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, inline_fluent!("not covered")); + spans.push_span_label(span, msg!("not covered")); } - diag.span_note(spans, inline_fluent!("`{$ty}` defined here")); + diag.span_note(spans, msg!("`{$ty}` defined here")); } } 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 4eb7b3671e9c..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,9 +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, inline_fluent, 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}; @@ -987,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, - inline_fluent!("matches some of the 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, - inline_fluent!("collectively 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, - inline_fluent!("...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable"), + 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 6f0f6478f2d7..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, inline_fluent}; +use rustc_errors::{Diag, msg}; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; @@ -82,7 +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), inline_fluent!("constant 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_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 7407a0e022d3..7421a55f2a79 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,7 +1,5 @@ use rustc_errors::codes::*; -use rustc_errors::{ - Applicability, Diag, EmissionGuarantee, LintDiagnostic, Subdiagnostic, inline_fluent, -}; +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; @@ -135,10 +133,10 @@ 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 => { - inline_fluent!("this arithmetic operation will overflow") + msg!("this arithmetic operation will overflow") } AssertLintKind::UnconditionalPanic => { - inline_fluent!("this operation will panic at runtime") + msg!("this operation will panic at runtime") } }); let label = self.assert_kind.diagnostic_message(); @@ -295,12 +293,10 @@ impl Subdiagnostic for UnusedVariableStringInterp { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label( self.lit, - inline_fluent!( - "you might have meant to use string interpolation in this string literal" - ), + msg!("you might have meant to use string interpolation in this string literal"), ); diag.multipart_suggestion( - inline_fluent!("string interpolation only works in `format!` invocations"), + msg!("string interpolation only works in `format!` invocations"), vec![ (self.lit.shrink_to_lo(), String::from("format!(")), (self.lit.shrink_to_hi(), String::from(")")), @@ -337,17 +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(inline_fluent!( + diag.primary_message(msg!( "{$pre}`{$def_path}`{$post} held across a suspend point, but should not be" )); - diag.span_label( - self.yield_sp, - inline_fluent!("the value is held across this suspend point"), - ); + 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, inline_fluent!("consider using a block (`{\"{ ... }\"}`) to shrink the value's scope, ending before the suspend point")); + 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); 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 448ed78702b7..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, inline_fluent}; +use rustc_errors::{Subdiagnostic, msg}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::MixedBitSet; @@ -531,7 +531,7 @@ 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(inline_fluent!( + 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 @@ -542,7 +542,7 @@ impl Subdiagnostic for LocalLabel<'_> { dtor.add_to_diag(diag); } let msg = - diag.eagerly_translate(inline_fluent!( + 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 diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e73d9a1bf56a..0d8d403625a7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -9,7 +9,7 @@ use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, Subdiagnostic, SuggestionStyle, inline_fluent, + Level, Subdiagnostic, SuggestionStyle, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1463,22 +1463,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - inline_fluent!("expected identifier, found reserved identifier `{$token}`") + msg!("expected identifier, found reserved identifier `{$token}`") } Some(TokenDescription::Keyword) => { - inline_fluent!("expected identifier, found keyword `{$token}`") + msg!("expected identifier, found keyword `{$token}`") } Some(TokenDescription::ReservedKeyword) => { - inline_fluent!("expected identifier, found reserved keyword `{$token}`") + msg!("expected identifier, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - inline_fluent!("expected identifier, found doc comment `{$token}`") + msg!("expected identifier, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - inline_fluent!("expected identifier, found metavariable") + msg!("expected identifier, found metavariable") } - None => inline_fluent!("expected identifier, found `{$token}`"), + None => msg!("expected identifier, found `{$token}`"), }, ); diag.span(self.span); @@ -1530,22 +1530,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - inline_fluent!("expected `;`, found reserved identifier `{$token}`") + msg!("expected `;`, found reserved identifier `{$token}`") } Some(TokenDescription::Keyword) => { - inline_fluent!("expected `;`, found keyword `{$token}`") + msg!("expected `;`, found keyword `{$token}`") } Some(TokenDescription::ReservedKeyword) => { - inline_fluent!("expected `;`, found reserved keyword `{$token}`") + msg!("expected `;`, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - inline_fluent!("expected `;`, found doc comment `{$token}`") + msg!("expected `;`, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - inline_fluent!("expected `;`, found metavariable") + msg!("expected `;`, found metavariable") } - None => inline_fluent!("expected `;`, found `{$token}`"), + None => msg!("expected `;`, found `{$token}`"), }, ); diag.span(self.span); @@ -1554,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, inline_fluent!("unexpected token")); + diag.span_label(unexpected_token_label, msg!("unexpected token")); } self.sugg.add_to_diag(&mut diag); @@ -1980,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, inline_fluent!("`Fn` bounds require arguments in parentheses")); + diag.span_label(self.span, msg!("`Fn` bounds require arguments in parentheses")); diag.span_suggestion_short( self.span.shrink_to_hi(), - inline_fluent!("try adding parentheses"), + msg!("try adding parentheses"), "()", Applicability::MachineApplicable, ); @@ -4303,13 +4303,13 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( - inline_fluent!("if their presence wasn't intentional, you can remove them"), + 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( - inline_fluent!("if you want to keep them but make them visible in your source code, you can escape them"), + 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)| { @@ -4332,10 +4332,8 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { .collect::>() .join(", "), ); - diag.note(inline_fluent!( - "if their presence wasn't intentional, you can remove them" - )); - diag.note(inline_fluent!("if you want to keep them but make them visible in your source code, you can escape them: {$escaped}")); + 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}")); } } } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 3d16f37c000e..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, inline_fluent}; +use rustc_errors::{Diag, PResult, msg}; use rustc_span::{BytePos, Span}; use thin_vec::ThinVec; use tracing::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, inline_fluent!("expected outer doc comment")); + 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,12 +78,12 @@ impl<'a> Parser<'a> { }, true, ) { - err.note(inline_fluent!( + err.note(msg!( "inner doc comments like this (starting with `//!` or `/*!`) can only appear before items" )); err.span_suggestion_verbose( replacement_span, - inline_fluent!("you might have meant to write a regular comment"), + msg!("you might have meant to write a regular comment"), "", rustc_errors::Applicability::MachineApplicable, ); @@ -214,10 +213,10 @@ impl<'a> Parser<'a> { item.span, match attr_type { OuterAttributeType::Attribute => { - inline_fluent!("the inner attribute doesn't annotate this {$item}") + msg!("the inner attribute doesn't annotate this {$item}") } OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => { - inline_fluent!("the inner doc comment doesn't annotate this {$item}") + msg!("the inner doc comment doesn't annotate this {$item}") } }, ); @@ -225,8 +224,8 @@ impl<'a> Parser<'a> { err.span_suggestion_verbose( replacement_span, match attr_type { - OuterAttributeType::Attribute => inline_fluent!("to annotate the {$item}, change the attribute from inner to outer style"), - OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => inline_fluent!("to annotate the {$item}, change the doc comment from inner to outer style"), + 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 => "", @@ -258,42 +257,31 @@ impl<'a> Parser<'a> { self.dcx() .struct_span_err( attr_sp, - inline_fluent!( + msg!( "an inner attribute is not permitted following an outer doc comment" ), ) .with_span_label( attr_sp, - inline_fluent!("not permitted following an outer doc comment"), - ) - .with_span_label( - prev_doc_comment_span, - inline_fluent!("previous doc comment"), + 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, - inline_fluent!( - "an inner attribute is not permitted following an outer attribute" - ), + msg!("an inner attribute is not permitted following an outer attribute"), ) - .with_span_label( - attr_sp, - inline_fluent!("not permitted following an outer attribute"), - ) - .with_span_label( - prev_outer_attr_sp, - inline_fluent!("previous outer attribute"), - ), + .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, - inline_fluent!("an inner attribute is not permitted in this context"), + msg!("an inner attribute is not permitted in this context"), ), }; - diag.note(inline_fluent!("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files")); + 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, @@ -303,7 +291,7 @@ impl<'a> Parser<'a> { ) .is_some() { - diag.note(inline_fluent!( + diag.note(msg!( "outer attributes, like `#[test]`, annotate the item following them" )); }; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c7eb1b9b5638..b8672f6cafdf 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -12,8 +12,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions, - inline_fluent, pluralize, + Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions, msg, + pluralize, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -1272,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(), - inline_fluent!("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"), + msg!("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"), "::", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index b7ba92bac524..c0f5afb952fd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -9,7 +9,7 @@ use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; -use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, 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; @@ -1743,7 +1743,7 @@ impl<'a> Parser<'a> { if this.token == token::Bang { if let Err(err) = this.unexpected() { - err.with_note(inline_fluent!("macros cannot expand to enum variants")).emit(); + err.with_note(msg!("macros cannot expand to enum variants")).emit(); } this.bump(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3362ea667b93..35bc5a3ca094 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, inline_fluent}; +use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, msg}; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, @@ -1003,10 +1003,10 @@ 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, inline_fluent!("this attribute...")); + spans.push_span_label(*span, msg!("this attribute...")); spans.push_span_label( *span2, - inline_fluent!("{\".\"}..conflicts with this attribute"), + msg!("{\".\"}..conflicts with this attribute"), ); self.dcx().emit_err(errors::DocInlineConflict { spans }); return; @@ -1151,7 +1151,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self.tcx.sess, sym::rustdoc_internals, *span, - inline_fluent!("the `#[doc(rust_logo)]` attribute is used for Rust branding"), + msg!("the `#[doc(rust_logo)]` attribute is used for Rust branding"), ) .emit(); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 128a07292a03..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, inline_fluent, + MultiSpan, msg, }; use rustc_hir::Target; use rustc_hir::attrs::{MirDialect, MirPhase}; @@ -481,11 +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, - inline_fluent!("`{$name}` attribute cannot be used 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 @@ -493,17 +490,14 @@ impl Diagnostic<'_, G> for InvalidAttrAtCrateLevel { if let Some(span) = self.sugg_span { diag.span_suggestion_verbose( span, - inline_fluent!("perhaps you meant to use an outer attribute"), + 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, - inline_fluent!("the inner attribute doesn't annotate this {$kind}"), - ); + diag.span_label(item.span, msg!("the inner attribute doesn't annotate this {$kind}")); } diag } @@ -654,11 +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, - inline_fluent!("`main` function not found in crate `{$crate_name}`"), - ); + 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); @@ -666,23 +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, inline_fluent!("here is a function named `main`")); + diag.span_note(span, msg!("here is a function named `main`")); } - diag.note(inline_fluent!( + diag.note(msg!( "you have one or more functions named `main` not defined at the crate level" )); - diag.help(inline_fluent!("consider moving the `main` function definitions")); + diag.help(msg!("consider moving the `main` function definitions")); // There were some functions named `main` though. Try to give the user a hint. - inline_fluent!( + msg!( "the main function must be defined at the crate level{$has_filename -> [true] {\" \"}(in `{$filename}`) *[false] {\"\"} }" ) } else if self.has_filename { - inline_fluent!("consider adding a `main` function to `{$filename}`") + msg!("consider adding a `main` function to `{$filename}`") } else { - inline_fluent!("consider adding a `main` function at the crate level") + msg!("consider adding a `main` function at the crate level") }; if self.file_empty { diag.note(note); @@ -695,14 +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, - inline_fluent!("non-function item at `crate::main` is found"), - ); + diag.span_label(main_def.span, msg!("non-function item at `crate::main` is found")); } if self.add_teach_note { - diag.note(inline_fluent!("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.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 } @@ -730,11 +718,11 @@ impl Diagnostic<'_, G> for DuplicateLangItem { dcx, level, match self.duplicate { - Duplicate::Plain => inline_fluent!("found duplicate lang item `{$lang_item_name}`"), - Duplicate::Crate => inline_fluent!( - "duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`" - ), - Duplicate::CrateDepends => inline_fluent!( + 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}`" ), }, @@ -757,32 +745,26 @@ impl Diagnostic<'_, G> for DuplicateLangItem { diag.span(span); } if let Some(span) = self.first_defined_span { - diag.span_note(span, inline_fluent!("the lang item is first defined here")); + diag.span_note(span, msg!("the lang item is first defined here")); } else { if self.orig_dependency_of.is_none() { - diag.note(inline_fluent!( - "the lang item is first defined in crate `{$orig_crate_name}`" - )); + diag.note(msg!("the lang item is first defined in crate `{$orig_crate_name}`")); } else { - diag.note(inline_fluent!("the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)")); + 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(inline_fluent!( - "first definition in the local crate (`{$orig_crate_name}`)" - )); + diag.note(msg!("first definition in the local crate (`{$orig_crate_name}`)")); } else { - diag.note(inline_fluent!( + diag.note(msg!( "first definition in `{$orig_crate_name}` loaded from {$orig_path}" )); } if self.is_local { - diag.note(inline_fluent!("second definition in the local crate (`{$crate_name}`)")); + diag.note(msg!("second definition in the local crate (`{$crate_name}`)")); } else { - diag.note(inline_fluent!( - "second definition in `{$crate_name}` loaded from {$path}" - )); + diag.note(msg!("second definition in `{$crate_name}` loaded from {$path}")); } } diag diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 28c5a128ea36..a9b2dabc8ebe 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, inline_fluent, + EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::source_map::Spanned; @@ -1371,16 +1371,16 @@ impl Subdiagnostic for FoundItemConfigureOut { let key = "feature".into(); let value = feature.into_diag_arg(&mut None); let msg = diag.dcx.eagerly_translate_to_string( - inline_fluent!("the item is gated behind the `{$feature}` 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, inline_fluent!("the item is gated here")); + multispan.push_span_label(span, msg!("the item is gated here")); } } - diag.span_note(multispan, inline_fluent!("found an item that was configured out")); + diag.span_note(multispan, msg!("found an item that was configured out")); } } 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 2ba2254c274e..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,8 +2,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, inline_fluent, - 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}; @@ -230,20 +229,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .add_to_diag(err), SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain { span, - msg: inline_fluent!("...so that reference does not outlive borrowed content"), + msg: msg!("...so that reference does not outlive borrowed content"), } .add_to_diag(err), SubregionOrigin::RelateObjectBound(span) => { RegionOriginNote::Plain { span, - msg: inline_fluent!("...so that it can be closed over into an object"), + msg: msg!("...so that it can be closed over into an object"), } .add_to_diag(err); } SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: inline_fluent!("...so that the reference type `{$name}` does not outlive the data it points at"), + msg: msg!("...so that the reference type `{$name}` does not outlive the data it points at"), name: &self.ty_to_string(ty), continues: false, } @@ -252,7 +251,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: inline_fluent!( + msg: msg!( "...so that the type `{$name}` will meet its required lifetime bounds{$continues -> [true] ... *[false] {\"\"} @@ -265,7 +264,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(span) = opt_span { RegionOriginNote::Plain { span, - msg: inline_fluent!("...that is required by this bound"), + msg: msg!("...that is required by this bound"), } .add_to_diag(err); } @@ -273,16 +272,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, - msg: inline_fluent!( - "...so that the declared lifetime parameter bounds are satisfied" - ), + msg: msg!("...so that the declared lifetime parameter bounds are satisfied"), } .add_to_diag(err); } SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, - msg: inline_fluent!( + msg: msg!( "...so that the definition in impl matches the definition from the trait" ), } @@ -292,11 +289,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_region_origin(err, parent); } SubregionOrigin::AscribeUserTypeProvePredicate(span) => { - RegionOriginNote::Plain { - span, - msg: inline_fluent!("...so that the where clause holds"), - } - .add_to_diag(err); + RegionOriginNote::Plain { span, msg: msg!("...so that the where clause holds") } + .add_to_diag(err); } } } 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 68240f5ea599..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,8 +11,8 @@ 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, - inline_fluent, pluralize, struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg, + pluralize, struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -3088,7 +3088,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { err.span_help( self.tcx.def_span(trait_def_id), - inline_fluent!("this trait has no implementations, consider adding one"), + 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/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 03364e412f00..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, inline_fluent, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -105,7 +105,7 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { let mut diag = Diag::new( dcx, level, - inline_fluent!( + msg!( "found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> [none] {\"\"} *[default] {\" \"}for type `{$self_desc}` @@ -118,23 +118,19 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { diag.code(E0751); match self.negative_impl_span { Ok(span) => { - diag.span_label(span, inline_fluent!("negative implementation here")); + diag.span_label(span, msg!("negative implementation here")); } Err(cname) => { - diag.note(inline_fluent!( - "negative implementation in crate `{$negative_impl_cname}`" - )); + 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, inline_fluent!("positive implementation here")); + diag.span_label(span, msg!("positive implementation here")); } Err(cname) => { - diag.note(inline_fluent!( - "positive implementation in crate `{$positive_impl_cname}`" - )); + diag.note(msg!("positive implementation in crate `{$positive_impl_cname}`")); diag.arg("positive_impl_cname", cname.to_string()); } } @@ -161,7 +157,7 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("borrow_len", to_borrow.len()); diag.multipart_suggestion_verbose( - inline_fluent!( + msg!( "consider adjusting the signature so it borrows its {$borrow_len -> [one] argument *[other] arguments @@ -174,7 +170,7 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { diag.arg("remove_borrow_len", remove_borrow.len()); diag.multipart_suggestion_verbose( - inline_fluent!( + msg!( "consider adjusting the signature so it does not borrow its {$remove_borrow_len -> [one] argument *[other] arguments @@ -509,7 +505,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { } => { label_or_note( span, - inline_fluent!( + msg!( "...so that the {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait @@ -535,7 +531,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { // *terrible*. label_or_note( span, - inline_fluent!( + msg!( "...so that {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait @@ -578,11 +574,11 @@ 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, inline_fluent!("this parameter and the return type are declared with different lifetimes...")); - diag.span_label(ret_span, inline_fluent!("{\"\"}")); + 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, - inline_fluent!( + msg!( "...but data{$label_var1_exists -> [true] {\" \"}from `{$label_var1}` *[false] {\"\"} @@ -603,22 +599,22 @@ impl Subdiagnostic for LifetimeMismatchLabels { if hir_equal { diag.span_label( ty_sup, - inline_fluent!("this type is declared with multiple lifetimes..."), + msg!("this type is declared with multiple lifetimes..."), ); - diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label(ty_sub, msg!("{\"\"}")); diag.span_label( span, - inline_fluent!("...but data with one lifetime flows into the other here"), + msg!("...but data with one lifetime flows into the other here"), ); } else { diag.span_label( ty_sup, - inline_fluent!("these two types are declared with different lifetimes..."), + msg!("these two types are declared with different lifetimes..."), ); - diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label(ty_sub, msg!("{\"\"}")); diag.span_label( span, - inline_fluent!( + msg!( "...but data{$label_var1_exists -> [true] {\" \"}from `{$label_var1}` *[false] {\"\"} @@ -793,7 +789,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { visitor.suggestions.push(new_param_suggestion); } diag.multipart_suggestion_verbose( - inline_fluent!( + msg!( "consider {$is_reuse -> [true] reusing *[false] introducing @@ -811,9 +807,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { true }; if mk_suggestion() && self.add_note { - diag.note(inline_fluent!( - "each elided lifetime in input position becomes a distinct lifetime" - )); + diag.note(msg!("each elided lifetime in input position becomes a distinct lifetime")); } } } @@ -838,11 +832,11 @@ impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { self.unmet_requirements.push_span_label( self.binding_span, - inline_fluent!("introduces a `'static` lifetime requirement"), + msg!("introduces a `'static` lifetime requirement"), ); diag.span_note( self.unmet_requirements, - inline_fluent!("because this has an unmet lifetime requirement"), + msg!("because this has an unmet lifetime requirement"), ); } } @@ -1226,12 +1220,10 @@ 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, - inline_fluent!("consider borrowing this type parameter in the trait"), - ); + type_param_span + .push_span_label(span, msg!("consider borrowing this type parameter in the trait")); } - let msg = diag.eagerly_translate(inline_fluent!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); + 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); } } @@ -1269,18 +1261,16 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label( self.span, - inline_fluent!("this has an implicit `'static` lifetime requirement"), + msg!("this has an implicit `'static` lifetime requirement"), ); multi_span.push_span_label( self.ident.span, - inline_fluent!("calling this method introduces the `impl`'s `'static` requirement"), + msg!("calling this method introduces the `impl`'s `'static` requirement"), ); - let msg = - diag.eagerly_translate(inline_fluent!("the used `impl` has a `'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(inline_fluent!( - "consider relaxing the implicit `'static` requirement" - )); + let msg = + diag.eagerly_translate(msg!("consider relaxing the implicit `'static` requirement")); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1333,20 +1323,17 @@ 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, inline_fluent!("`'static` requirement 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, - inline_fluent!("requirement introduced by this return type"), + msg!("requirement introduced by this return type"), ); } - self.span.push_span_label( - self.cause_span, - inline_fluent!("because of this returned expression"), - ); - let msg = diag.eagerly_translate(inline_fluent!( + 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); @@ -1788,9 +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(inline_fluent!( - "try wrapping the pattern in a variant of `{$path}`" - )); + 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| { @@ -2034,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( - inline_fluent!("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"), + 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, - inline_fluent!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), + msg!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), ); } } @@ -2181,16 +2167,14 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { Applicability::MaybeIncorrect }; diag.multipart_suggestion_verbose( - inline_fluent!( - "use the precise capturing `use<...>` syntax to make the captures explicit" - ), + 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, - inline_fluent!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), + msg!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), ); } } 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 6a7e1d252806..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,4 +1,4 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, inline_fluent}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, msg}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; @@ -169,7 +169,7 @@ impl Subdiagnostic for RegionExplanation<'_> { diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = diag.eagerly_translate(inline_fluent!( + let msg = diag.eagerly_translate(msg!( "{$pref_kind -> *[should_not_happen] [{$pref_kind}] [ref_valid_for] ...the reference is valid for diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 3f4c75a5b133..1475e5f5f243 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,7 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::inline_fluent; +use rustc_errors::msg; use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -295,7 +295,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.cause.span, false, |diag| { - diag.note(inline_fluent!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); + diag.note(msg!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); }, ); } From 3fdb366140b46097434b608707fc93e0b3e26439 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 14 Feb 2026 07:47:54 -0500 Subject: [PATCH 176/182] Fix clippy warning --- src/declare.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/declare.rs b/src/declare.rs index e4130b221ee3..6450e2d4039c 100644 --- a/src/declare.rs +++ b/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, From 6ed7615608bf0330f65a9438292038f24aa63ce5 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Fri, 13 Feb 2026 11:18:24 +0000 Subject: [PATCH 177/182] Port #[rustc_test_marker] to the attribute parser --- .../src/attributes/test_attrs.rs | 33 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 6 +--- 6 files changed, 40 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 41b1836588de..ac1d360c6280 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -257,3 +257,36 @@ impl SingleAttributeParser for TestRunnerParser { 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/context.rs b/compiler/rustc_attr_parsing/src/context.rs index e11bb6668539..b0a6ef34195b 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -217,6 +217,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 8d9b53498934..d6a9c2dc872f 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1336,6 +1336,9 @@ pub enum AttributeKind { /// Represents `#[rustc_symbol_name]` RustcSymbolName(Span), + /// Represents `#[rustc_test_marker]` + RustcTestMarker(Symbol), + /// Represents `#[rustc_then_this_would_need]` RustcThenThisWouldNeed(Span, ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index ec4d543fdc20..f103be915a5a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -170,6 +170,7 @@ impl AttributeKind { RustcStdInternalSymbol(..) => No, RustcStrictCoherence(..) => Yes, RustcSymbolName(..) => Yes, + RustcTestMarker(..) => No, RustcThenThisWouldNeed(..) => No, RustcTrivialFieldReads => Yes, RustcUnsafeSpecializationMarker(..) => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3362ea667b93..d2cea0392129 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -361,6 +361,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcStdInternalSymbol (..) | AttributeKind::RustcStrictCoherence(..) | AttributeKind::RustcSymbolName(..) + | AttributeKind::RustcTestMarker(..) | AttributeKind::RustcThenThisWouldNeed(..) | AttributeKind::RustcTrivialFieldReads | AttributeKind::RustcUnsafeSpecializationMarker(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check | sym::rustc_doc_primitive - | sym::rustc_test_marker | sym::rustc_layout | sym::rustc_proc_macro_decls | sym::rustc_autodiff diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 269a7f333dc5..c479ea59b884 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2343,11 +2343,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(& // We could also check for the type name `test::TestDescAndFn` && let Res::Def(DefKind::Struct, _) = path.res { - let has_test_marker = tcx - .hir_attrs(item.hir_id()) - .iter() - .any(|a| a.has_name(sym::rustc_test_marker)); - if has_test_marker { + if find_attr!(tcx.hir_attrs(item.hir_id()), AttributeKind::RustcTestMarker(..)) { names.push(ident.name); } } From b0366ce93563434b71f11189c1f75d5c54563a53 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 13 Feb 2026 23:39:37 +0300 Subject: [PATCH 178/182] DepGraphQuery: correctly skip adding edges with not-yet-added nodes --- compiler/rustc_middle/src/dep_graph/query.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/query.rs b/compiler/rustc_middle/src/dep_graph/query.rs index 724a01327aba..f145e1cba2d7 100644 --- a/compiler/rustc_middle/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, ()); } } From 27d5b14aef576787388c7f5fe0bef4c5a9a61988 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Feb 2026 16:59:09 +0100 Subject: [PATCH 179/182] Update GCC submodule --- src/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc b/src/gcc index 0081ca6631ab..efdd0a7290c2 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 0081ca6631abdfa02bf42bc85aaf507b8a0e6beb +Subproject commit efdd0a7290c22f5438d7c5380105d353ee3e8518 From 1f94802603aa571c4d7cdf7045b35b8907eb2ee9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Feb 2026 17:12:51 +0100 Subject: [PATCH 180/182] Fix libgccjit version --- compiler/rustc_codegen_gcc/libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version index 25e1105ab07f..abc967702fb0 100644 --- a/compiler/rustc_codegen_gcc/libgccjit.version +++ b/compiler/rustc_codegen_gcc/libgccjit.version @@ -1 +1 @@ -896045775f7c40fafe48c6e398f6c53bf6af889e +efdd0a7290c22f5438d7c5380105d353ee3e8518 From d888b1c1082217d7b084aa02cab2c59783edffd1 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 15 Feb 2026 05:18:09 +0000 Subject: [PATCH 181/182] Prepare for merging from rust-lang/rust This updates the rust-version file to 7bee525095c0872e87c038c412c781b9bbb3f5dc. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index a79511cea30a..28c3e88535f6 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -47611e16044c68ef27bac31c35fda2ba1dc20b73 +7bee525095c0872e87c038c412c781b9bbb3f5dc From 702793191fd51ec36803f620553fee675ed93157 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 15 Feb 2026 05:27:15 +0000 Subject: [PATCH 182/182] fmt --- .../miri/tests/fail/match/all_variants_uninhabited.rs | 2 +- .../miri/tests/fail/match/closures/uninhabited-variant2.rs | 3 ++- src/tools/miri/tests/fail/match/only_inhabited_variant.rs | 7 ++++--- src/tools/miri/tests/fail/match/single_variant.rs | 7 ++++--- src/tools/miri/tests/fail/match/single_variant_uninit.rs | 3 ++- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs index e7ca45579d84..b073d339f10c 100644 --- a/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs +++ b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs @@ -5,7 +5,7 @@ enum Never {} fn main() { unsafe { match *std::ptr::null::>() { - //~^ ERROR: read discriminant of an uninhabited enum variant + //~^ ERROR: read discriminant of an uninhabited enum variant Ok(_) => { lol(); } diff --git a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs index ed68e357fbd5..050e83884d1e 100644 --- a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs @@ -22,7 +22,8 @@ fn main() { // After rust-lang/rust#138961, constructing the closure performs a reborrow of r. // Nevertheless, the discriminant is only actually inspected when the closure // is called. - match r { //~ ERROR: read discriminant of an uninhabited enum variant + match r { + //~^ ERROR: read discriminant of an uninhabited enum variant E::V0 => {} E::V1(_) => {} } diff --git a/src/tools/miri/tests/fail/match/only_inhabited_variant.rs b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs index 30a7350d2b66..2be5e8083aa7 100644 --- a/src/tools/miri/tests/fail/match/only_inhabited_variant.rs +++ b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs @@ -4,8 +4,8 @@ #[repr(C)] #[allow(dead_code)] enum E { - V0, // discriminant: 0 - V1(!), // 1 + V0, // discriminant: 0 + V1(!), // 1 } fn main() { @@ -14,7 +14,8 @@ fn main() { let val = 1u32; let ptr = (&raw const val).cast::(); let r = unsafe { &*ptr }; - match r { //~ ERROR: read discriminant of an uninhabited enum variant + match r { + //~^ ERROR: read discriminant of an uninhabited enum variant E::V0 => {} E::V1(_) => {} } diff --git a/src/tools/miri/tests/fail/match/single_variant.rs b/src/tools/miri/tests/fail/match/single_variant.rs index dcef6d461a2c..35bb63620ea2 100644 --- a/src/tools/miri/tests/fail/match/single_variant.rs +++ b/src/tools/miri/tests/fail/match/single_variant.rs @@ -20,12 +20,13 @@ fn main() { let x: &[u8; 2] = &[21, 37]; let y: &Exhaustive = std::mem::transmute(x); match y { - Exhaustive::A(_) => {}, + Exhaustive::A(_) => {} } let y: &NonExhaustive = std::mem::transmute(x); - match y { //~ ERROR: enum value has invalid tag - NonExhaustive::A(_) => {}, + match y { + //~^ ERROR: enum value has invalid tag + NonExhaustive::A(_) => {} } } } diff --git a/src/tools/miri/tests/fail/match/single_variant_uninit.rs b/src/tools/miri/tests/fail/match/single_variant_uninit.rs index 51e8bc57c837..e04947f99628 100644 --- a/src/tools/miri/tests/fail/match/single_variant_uninit.rs +++ b/src/tools/miri/tests/fail/match/single_variant_uninit.rs @@ -28,7 +28,8 @@ fn main() { _ => {} } - match *nexh { //~ ERROR: memory is uninitialized + match *nexh { + //~^ ERROR: memory is uninitialized NonExhaustive::A(ref _val) => {} _ => {} }