From 249e5b5a0302830eafb914bff5ff80033e065b62 Mon Sep 17 00:00:00 2001 From: Samson <16504129+sagudev@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:29:45 +0100 Subject: [PATCH 001/333] Fix rib example related zulip thread: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Ribs.20in.20name.20resolution --- src/doc/rustc-dev-guide/src/name-resolution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 2727b8142f2a8..719ebce855366 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -120,9 +120,9 @@ even though they should be visible by ordinary scoping rules. An example: fn do_something(val: T) { // <- New rib in both types and values (1) // `val` is accessible, as is the helper function // `T` is accessible - let helper = || { // New rib on `helper` (2) and another on the block (3) + let helper = || { // New rib on the block (2) // `val` is accessible here - }; // End of (3) + }; // End of (2), new rib on `helper` (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) // `val` is not accessible here, (4) is not transparent for locals @@ -130,7 +130,7 @@ fn do_something(val: T) { // <- New rib in both types and values (1) } // End of (4) let val = T::default(); // New rib (5) // `val` is the variable, not the parameter here -} // End of (5), (2) and (1) +} // End of (5), (3) and (1) ``` Because the rules for different namespaces are a bit different, each namespace From f1010442cc650aba832a11b95a2b1a75f23cdf0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Feb 2025 15:15:28 +0100 Subject: [PATCH 002/333] intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic --- src/intrinsics/mod.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 26f14532b458e..4d9bed8652cbd 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -340,14 +340,10 @@ fn codegen_float_intrinsic_call<'tcx>( sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), - sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), - sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32), + sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), - sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32), - sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64), - sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32), - sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), @@ -399,8 +395,8 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf64 | sym::truncf32 | sym::truncf64 - | sym::nearbyintf32 - | sym::nearbyintf64 + | sym::round_ties_even_f32 + | sym::round_ties_even_f64 | sym::sqrtf32 | sym::sqrtf64 => { let val = match intrinsic { @@ -408,7 +404,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => { + fx.bcx.ins().nearest(args[0]) + } sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), _ => unreachable!(), }; From 0b90953a2d35b1886829fb8ec986d59d337f9c3a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:13:01 +0000 Subject: [PATCH 003/333] Merge commit '557ed8ebb7e981817d03c87352892c394183dd70' into sync_cg_clif-2025-02-15 --- .github/workflows/main.yml | 4 ++-- rust-toolchain | 2 +- rustfmt.toml | 3 ++- src/abi/pass_mode.rs | 2 +- src/common.rs | 7 ++++++- src/debuginfo/mod.rs | 2 +- src/debuginfo/types.rs | 4 ++-- src/inline_asm.rs | 3 ++- src/value_and_place.rs | 6 +++--- 9 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a8333df77e6e7..61a4c1270c993 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -188,8 +188,8 @@ jobs: fail-fast: false matrix: include: - # FIXME update at some point in the future once most distros use a newer glibc - - os: ubuntu-20.04 + # Intentionally using an older ubuntu version to lower the glibc requirements of the distributed cg_clif + - os: ubuntu-22.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu - os: macos-latest diff --git a/rust-toolchain b/rust-toolchain index 8d423319fa977..481903c6afb28 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-07" +channel = "nightly-2025-02-15" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/rustfmt.toml b/rustfmt.toml index d9e6ac3d543c9..f31fa9c76abc6 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,8 +3,9 @@ ignore = [ ] # Matches rustfmt.toml of rustc -version = "Two" +style_edition = "2024" use_small_heuristics = "Max" merge_derives = false group_imports = "StdExternalCrate" imports_granularity = "Module" +use_field_init_shorthand = true diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7594a53fc758f..b28c4c9539cef 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -195,7 +195,7 @@ pub(super) fn from_casted_value<'tcx>( // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. std::cmp::max(abi_param_size, layout_size), - u32::try_from(layout.align.pref.bytes()).unwrap(), + u32::try_from(layout.align.abi.bytes()).unwrap(), ); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); diff --git a/src/common.rs b/src/common.rs index 534557fcd41be..766278d87183b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -382,6 +382,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { + assert!( + size % align == 0, + "size must be a multiple of alignment (size={size}, align={align})" + ); + let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 }; if align <= abi_align { let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { @@ -403,7 +408,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { align_shift: 4, }); let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); - let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); + let misalign_offset = self.bcx.ins().band_imm(base_ptr, i64::from(align - 1)); let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index f3a8623e21611..bba6567774d7e 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -304,7 +304,7 @@ impl DebugContext { entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line)); - entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.pref.bytes())); + entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.abi.bytes())); let mut expr = Expression::new(); expr.op_addr(address_for_data(data_id)); diff --git a/src/debuginfo/types.rs b/src/debuginfo/types.rs index a2f6691cdd232..017d7784dc032 100644 --- a/src/debuginfo/types.rs +++ b/src/debuginfo/types.rs @@ -166,7 +166,7 @@ impl DebugContext { let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id); tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name))); tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes())); - tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.pref.bytes())); + tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.abi.bytes())); for (i, (ty, dw_ty)) in components.into_iter().enumerate() { let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member); @@ -179,7 +179,7 @@ impl DebugContext { member_entry.set( gimli::DW_AT_alignment, AttributeValue::Udata( - FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.pref.bytes(), + FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.abi.bytes(), ), ); member_entry.set( diff --git a/src/inline_asm.rs b/src/inline_asm.rs index f2b0ec977c63d..310b226814d40 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -871,7 +871,8 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16); + let stack_slot = + fx.create_stack_slot(u32::try_from(slot_size.bytes().next_multiple_of(16)).unwrap(), 16); let inline_asm_func = fx .module diff --git a/src/value_and_place.rs b/src/value_and_place.rs index c17d1f30fbe3a..a9b8e1bd39353 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -101,7 +101,7 @@ impl<'tcx> CValue<'tcx> { /// The is represented by a dangling pointer of suitable alignment. pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> { assert!(layout.is_zst()); - CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout) + CValue::by_ref(crate::Pointer::dangling(layout.align.abi), layout) } pub(crate) fn layout(&self) -> TyAndLayout<'tcx> { @@ -392,7 +392,7 @@ impl<'tcx> CPlace<'tcx> { assert!(layout.is_sized()); if layout.size.bytes() == 0 { return CPlace { - inner: CPlaceInner::Addr(Pointer::dangling(layout.align.pref), None), + inner: CPlaceInner::Addr(Pointer::dangling(layout.align.abi), None), layout, }; } @@ -405,7 +405,7 @@ impl<'tcx> CPlace<'tcx> { let stack_slot = fx.create_stack_slot( u32::try_from(layout.size.bytes()).unwrap(), - u32::try_from(layout.align.pref.bytes()).unwrap(), + u32::try_from(layout.align.abi.bytes()).unwrap(), ); CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout } } From b141440f8621e238941f1b79a4e9ea7bcd9c38bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 10:45:49 +1100 Subject: [PATCH 004/333] Move some `Map` methods onto `TyCtxt`. The end goal is to eliminate `Map` altogether. I added a `hir_` prefix to all of them, that seemed simplest. The exceptions are `module_items` which became `hir_module_free_items` because there was already a `hir_module_items`, and `items` which became `hir_free_items` for consistency with `hir_module_free_items`. --- src/driver/jit.rs | 2 +- src/global_asm.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 2e713171ae064..57c88f4b0f9f5 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -124,7 +124,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< crate::constant::codegen_static(tcx, &mut jit_module, def_id); } MonoItem::GlobalAsm(item_id) => { - let item = tcx.hir().item(item_id); + let item = tcx.hir_item(item_id); tcx.dcx().span_fatal(item.span, "Global asm is not supported in JIT mode"); } } diff --git a/src/global_asm.rs b/src/global_asm.rs index c0a3ce84d5292..54745b0d8c104 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -15,7 +15,7 @@ use rustc_target::asm::InlineAsmArch; use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { - let item = tcx.hir().item(item_id); + let item = tcx.hir_item(item_id); if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); From 44af9d30ff49f0d9fa360222a5a8f68c1a42877b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Feb 2025 22:33:18 -0800 Subject: [PATCH 005/333] cg_clif: use exclusively ABI alignment --- src/abi/comments.rs | 5 ++--- src/constant.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index 521a250ab82cc..e2c9f40d14799 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -65,7 +65,7 @@ pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { if fx.clif_comments.enabled() { fx.add_global_comment(String::new()); fx.add_global_comment( - "kind local ty size align (abi,pref)".to_string(), + "kind local ty size align (abi)".to_string(), ); } } @@ -84,13 +84,12 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}{}", + "{:<5} {:5} {:30} {:4}b {}, {}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - align.pref.bytes(), if extra.is_empty() { "" } else { " " }, extra, )); diff --git a/src/constant.rs b/src/constant.rs index 425b2adf32a37..bcc70f4567fbd 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -272,7 +272,7 @@ fn data_id_for_static( .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .unwrap() .align - .pref + .abi .bytes(); let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak From 616fe134c258e0aa4e139a2caf3280a4249a66b4 Mon Sep 17 00:00:00 2001 From: Jubilee Date: Tue, 18 Feb 2025 01:29:23 -0800 Subject: [PATCH 006/333] cg_clif: Tweak formatting of global comments Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- src/abi/comments.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index e2c9f40d14799..c74efeb59f3fc 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -84,13 +84,13 @@ pub(super) fn add_local_place_comments<'tcx>( let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( - "{:<5} {:5} {:30} {:4}b {}, {}{}", + "{:<5} {:5} {:30} {:4}b {}{}{}", kind, format!("{:?}", local), format!("{:?}", ty), size.bytes(), align.abi.bytes(), - if extra.is_empty() { "" } else { " " }, + if extra.is_empty() { "" } else { " " }, extra, )); } From 3fc1a5852193e6be4d9ef3d05f70ac167eb31091 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:25:24 +0000 Subject: [PATCH 007/333] Rustup to rustc 1.87.0-nightly (827a0d638 2025-02-18) --- patches/coretests-lock.toml | 73 +++++++++++++++++++++++++++++++++---- rust-toolchain | 2 +- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/patches/coretests-lock.toml b/patches/coretests-lock.toml index af8f28a193bcd..bb7f519f7a7c0 100644 --- a/patches/coretests-lock.toml +++ b/patches/coretests-lock.toml @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "coretests" @@ -10,26 +10,85 @@ dependencies = [ "rand_xorshift", ] +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_core", + "zerocopy", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" +dependencies = [ + "zerocopy", +] [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ "rand_core", ] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" + +[[package]] +name = "zerocopy" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust-toolchain b/rust-toolchain index 481903c6afb28..854ca5db8011a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-15" +channel = "nightly-2025-02-19" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 410a68a907b14db7eaa2152eccbbcef9ae357f7c Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: [PATCH 008/333] Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- src/value_and_place.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index a9b8e1bd39353..1b3f86c8405de 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> { } CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), CPlaceInner::Addr(to_ptr, None) => { - if dst_layout.size == Size::ZERO - || dst_layout.backend_repr == BackendRepr::Uninhabited - { + if dst_layout.size == Size::ZERO { return; } From 8622c818e2474b1973cce49b11c4826c2d3f93d9 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 22:25:23 +0000 Subject: [PATCH 009/333] Use `public-dependencies` in all sysroot crates In [1], most dependencies of `std` and other sysroot crates were marked private, but this did not happen for `alloc` and `test`. Update these here, marking public standard library crates as the only non-private dependencies. [1]: https://github.com/rust-lang/rust/pull/111076 --- .../0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index e3a9512dda9c6..eb1fc4b0ad59f 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -15,7 +15,7 @@ index 7165c3e48af..968552ad435 100644 edition = "2021" [dependencies] - core = { path = "../core" } + core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } From 9dd86e64cc19d24d5e62a028cae4515a1fbe95c2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 05:33:06 +0000 Subject: [PATCH 010/333] Make asm a named field --- src/global_asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 54745b0d8c104..0a23f63d6ba9b 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); From ea760dd09911d5bd73fd8a4321f319620e0cc53a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:09:46 +0000 Subject: [PATCH 011/333] Make a fake body to store typeck results for global_asm --- src/global_asm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 0a23f63d6ba9b..9ea92c300f898 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); @@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } } - InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { if cfg!(not(feature = "inline_asm_sym")) { tcx.dcx().span_err( item.span, @@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, ); } - let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(op_sp, "asm sym is not a function"), From 5ff55a4783e09ce3eda33e0db0a419c15a7f8b00 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 22 Feb 2025 11:42:10 +0000 Subject: [PATCH 012/333] Rustup to rustc 1.87.0-nightly (794c12416 2025-02-21) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 854ca5db8011a..1017b9550d036 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-19" +channel = "nightly-2025-02-22" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From c7b251e09e097a9b33bcaf5ae677ac641da9a360 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 19 Feb 2025 20:17:02 -0500 Subject: [PATCH 013/333] Update `compiler-builtins` to 0.1.147 Removes an ABI hack that used `<2 x i64>` to return `i128` in `xmm0` on Windows [1]. [1]: https://github.com/rust-lang/compiler-builtins/pull/759 Link: https://github.com/rust-lang/rust/issues/116558 Link: https://github.com/rust-lang/compiler-builtins/issues/758 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index eb1fc4b0ad59f..364a6a035ab88 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 447d85845de2dc68ec366c27cb1d1b65a1ba6e75 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Nov 2024 14:21:23 +0800 Subject: [PATCH 014/333] The embedded bitcode should always be prepared for LTO/ThinLTO --- src/driver/aot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index a52b18573b152..366e83853e51a 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -210,7 +210,7 @@ fn produce_final_output_artifacts( // to get rid of it. for output_type in crate_output.outputs.keys() { match *output_type { - OutputType::Bitcode | OutputType::ThinLinkBitcode => { + OutputType::Bitcode | OutputType::ThinLinkBitcode | OutputType::ThinBitcode => { // Cranelift doesn't have bitcode // user_wants_bitcode = true; // // Copy to .bc, but always keep the .0.bc. There is a later From 016f429c56992f2d62717fe2b6554ca4c4dd1f4a Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 22:01:08 +0800 Subject: [PATCH 015/333] Remove unused `OutputType::ThinLinkBitcode` --- src/driver/aot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 366e83853e51a..a52b18573b152 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -210,7 +210,7 @@ fn produce_final_output_artifacts( // to get rid of it. for output_type in crate_output.outputs.keys() { match *output_type { - OutputType::Bitcode | OutputType::ThinLinkBitcode | OutputType::ThinBitcode => { + OutputType::Bitcode | OutputType::ThinLinkBitcode => { // Cranelift doesn't have bitcode // user_wants_bitcode = true; // // Copy to .bc, but always keep the .0.bc. There is a later From 63a3ab4fae27ffc6af807598a5634546f9c05a9f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 24 Feb 2025 02:47:59 +0000 Subject: [PATCH 016/333] Add a span to `CompilerBuiltinsCannotCall` Currently, this error emit a diagnostic with no context like: error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from ` as core::fmt::LowerHex>::fmt` to `core::fmt::num::::fmt` With this change, it at least usually points to the problematic function: error: `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from ` as core::fmt::LowerHex>::fmt` to `core::fmt::num::::fmt` --> src/../libm/src/math/support/hex_float.rs:270:5 | 270 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | --- src/abi/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 756a2226753f6..e8076ce77abcf 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -402,9 +402,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { if target.is_some() { - let caller = with_no_trimmed_paths!(fx.tcx.def_path_str(fx.instance.def_id())); - let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)); - fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee }); + let caller_def = fx.instance.def_id(); + let e = CompilerBuiltinsCannotCall { + span: fx.tcx.def_span(caller_def), + caller: with_no_trimmed_paths!(fx.tcx.def_path_str(caller_def)), + callee: with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)), + }; + fx.tcx.dcx().emit_err(e); } else { fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; From 957389c196d744a68c51dd265e6ec63f984f80a4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2025 17:34:50 +0100 Subject: [PATCH 017/333] remove support for rustc_intrinsic_must_be_overridden from the compiler --- example/mini_core.rs | 65 +++++++++----------------------------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 79820232496a5..72c9df59d833f 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -620,70 +620,31 @@ pub union MaybeUninit { pub mod intrinsics { #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn size_of() -> usize { - loop {} - } + pub fn size_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn size_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn size_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn min_align_of() -> usize { - loop {} - } + pub fn min_align_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn min_align_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn min_align_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { - loop {} - } + pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn transmute(_e: T) -> U { - loop {} - } + pub unsafe fn transmute(_e: T) -> U; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn ctlz_nonzero(_x: T) -> u32 { - loop {} - } + pub unsafe fn ctlz_nonzero(_x: T) -> u32; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn needs_drop() -> bool { - loop {} - } + pub fn needs_drop() -> bool; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bitreverse(_x: T) -> T { - loop {} - } + pub fn bitreverse(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bswap(_x: T) -> T { - loop {} - } + pub fn bswap(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { - loop {} - } + pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn unreachable() -> ! { - loop {} - } + pub unsafe fn unreachable() -> !; } pub mod libc { From be4eb9a3aa976e864d69f7c361cca8779c8d09f7 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 24 Feb 2025 07:46:55 +0000 Subject: [PATCH 018/333] Update `compiler-builtins` to 0.1.148 Includes `f16` symbols on MIPS [1], updates for `libm` [2], and reapplies the patch that drops the `public_test_deps!` macro [3]. [1]: https://github.com/rust-lang/compiler-builtins/pull/762 [2]: https://github.com/rust-lang/compiler-builtins/pull/765 [3]: https://github.com/rust-lang/compiler-builtins/pull/766 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 364a6a035ab88..bedc6ca11b3f6 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.147", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From fb85ef70fc599827ed520df32eb486b0d80ce29e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:21:50 +0000 Subject: [PATCH 019/333] Rustup to rustc 1.87.0-nightly (f8a913b13 2025-02-23) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1017b9550d036..94b1403e47c10 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-22" +channel = "nightly-2025-02-24" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From ae5f2c2d5cd7734d77c9b87de272b96783e5e18b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:35:19 +0000 Subject: [PATCH 020/333] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 55230a0b5988d..599ce63bab56d 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -57,7 +57,6 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo -rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported # requires LTO rm -r tests/run-make/cdylib @@ -120,6 +119,7 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same rm tests/ui/consts/issue-33537.rs # same rm tests/ui/consts/const-mut-refs-crate.rs # same rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift +rm tests/ui/abi/simd-abi-checks-avx.rs # attempts to declare function with two different signatures # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended From a91db48ecf32f3e4c188679aee9897e107d31295 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 24 Feb 2025 19:10:55 +0100 Subject: [PATCH 021/333] =?UTF-8?q?rename=20simd=5Fshuffle=5Fgeneric=20?= =?UTF-8?q?=E2=86=92=20simd=5Fshuffle=5Fconst=5Fgeneric?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/intrinsics/simd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index fcccda62355c7..0929218ea2b2d 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -116,8 +116,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - // simd_shuffle_generic(x: T, y: T) -> U - sym::simd_shuffle_generic => { + // simd_shuffle_const_generic(x: T, y: T) -> U + sym::simd_shuffle_const_generic => { let [x, y] = args else { bug!("wrong number of args for intrinsic {intrinsic}"); }; From 12f7ae1ebbfcbe9ab38c92b95b9306312fbef720 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 28 Jul 2024 16:54:14 -0400 Subject: [PATCH 022/333] Avoid no-op unlink+link dances in incr comp --- src/driver/aot.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index a52b18573b152..d1843f90a07d0 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -103,12 +103,14 @@ impl OngoingCodegen { ("o", &module_regular.object.as_ref().unwrap()), ("asm.o", &module_global_asm.object.as_ref().unwrap()), ], + &[], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, &module_regular.name, &[("o", &module_regular.object.as_ref().unwrap())], + &[], ) }; if let Some((work_product_id, work_product)) = work_product { @@ -381,6 +383,7 @@ fn emit_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: None, }) @@ -437,6 +440,7 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }) } @@ -487,6 +491,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }, module_global_asm: has_global_asm.then(|| CompiledModule { name: cgu.name().to_string(), @@ -496,6 +501,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -637,6 +643,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } } @@ -745,7 +752,6 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; - Box::new(OngoingCodegen { modules, allocator_module, From 143cf8da3dbf7d3a7d5a16766d48058bec8a299d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 25 Feb 2025 09:20:10 +0100 Subject: [PATCH 023/333] remove `simd_fpow` and `simd_fpowi` --- src/intrinsics/simd.rs | 58 ------------------------------------------ 1 file changed, 58 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index fcccda62355c7..0c13fa91f7a73 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -460,64 +460,6 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_fpow => { - intrinsic_args!(fx, args => (a, b); intrinsic); - - if !a.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); - return; - } - - simd_pair_for_each_lane(fx, a, b, ret, &|fx, lane_ty, _ret_lane_ty, a_lane, b_lane| { - match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.lib_call( - "powf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[a_lane, b_lane], - )[0], - ty::Float(FloatTy::F64) => fx.lib_call( - "pow", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[a_lane, b_lane], - )[0], - _ => unreachable!("{:?}", lane_ty), - } - }); - } - - sym::simd_fpowi => { - intrinsic_args!(fx, args => (a, exp); intrinsic); - let exp = exp.load_scalar(fx); - - if !a.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); - return; - } - - simd_for_each_lane( - fx, - a, - ret, - &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.lib_call( - "__powisf2", // compiler-builtins - vec![AbiParam::new(types::F32), AbiParam::new(types::I32)], - vec![AbiParam::new(types::F32)], - &[lane, exp], - )[0], - ty::Float(FloatTy::F64) => fx.lib_call( - "__powidf2", // compiler-builtins - vec![AbiParam::new(types::F64), AbiParam::new(types::I32)], - vec![AbiParam::new(types::F64)], - &[lane, exp], - )[0], - _ => unreachable!("{:?}", lane_ty), - }, - ); - } - sym::simd_fsin | sym::simd_fcos | sym::simd_fexp From 94ac6e557f5ea35aee52089f66a20f3ae9230bc8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 9 Jan 2025 12:07:50 +0000 Subject: [PATCH 024/333] Update to Cranelift 0.117 --- Cargo.lock | 87 ++++++++++++++++++++++++++++++------------------------ Cargo.toml | 24 +++++++-------- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca66ec5c6e930..011e291cd2032 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,28 +41,44 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cranelift-assembler-x64" +version = "0.117.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b83fcf2fc1c8954561490d02079b496fd0c757da88129981e15bfe3a548229" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.117.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7496a6e92b5cee48c5d772b0443df58816dee30fed6ba19b2a28e78037ecedf" + [[package]] name = "cranelift-bforest" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e15d04a0ce86cb36ead88ad68cf693ffd6cda47052b9e0ac114bc47fd9cd23c4" +checksum = "73a9dc0a8d3d49ee772101924968830f1c1937d650c571d3c2dd69dc36a68f41" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6e3969a7ce267259ce244b7867c5d3bc9e65b0a87e81039588dfdeaede9f34" +checksum = "573c641174c40ef31021ae4a5a3ad78974e280633502d0dfc6e362385e0c100f" [[package]] name = "cranelift-codegen" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c22032c4cb42558371cf516bb47f26cdad1819d3475c133e93c49f50ebf304e" +checksum = "2d7c94d572615156f2db682181cadbd96342892c31e08cc26a757344319a9220" dependencies = [ "bumpalo", + "cranelift-assembler-x64", "cranelift-bforest", "cranelift-bitset", "cranelift-codegen-meta", @@ -71,7 +87,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.5", + "hashbrown", "log", "regalloc2", "rustc-hash", @@ -82,42 +98,43 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c904bc71c61b27fc57827f4a1379f29de64fe95653b620a3db77d59655eee0b8" +checksum = "beecd9fcf2c3e06da436d565de61a42676097ea6eb6b4499346ac6264b6bb9ce" dependencies = [ + "cranelift-assembler-x64", "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40180f5497572f644ce88c255480981ae2ec1d7bb4d8e0c0136a13b87a2f2ceb" +checksum = "0f4ff8d2e1235f2d6e7fc3c6738be6954ba972cd295f09079ebffeca2f864e22" [[package]] name = "cranelift-control" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d132c6d0bd8a489563472afc171759da0707804a65ece7ceb15a8c6d7dd5ef" +checksum = "001312e9fbc7d9ca9517474d6fe71e29d07e52997fd7efe18f19e8836446ceb2" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d0d9618275474fbf679dd018ac6e009acbd6ae6850f6a67be33fb3b00b323" +checksum = "eb0fd6d4aae680275fcbceb08683416b744e65c8b607352043d3f0951d72b3b2" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fac41e16729107393174b0c9e3730fb072866100e1e64e80a1a963b2e484d57" +checksum = "9fd44e7e5dcea20ca104d45894748205c51365ce4cdb18f4418e3ba955971d1b" dependencies = [ "cranelift-codegen", "log", @@ -127,15 +144,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca20d576e5070044d0a72a9effc2deacf4d6aa650403189d8ea50126483944d" +checksum = "f900e0a3847d51eed0321f0777947fb852ccfce0da7fb070100357f69a2f37fc" [[package]] name = "cranelift-jit" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e65c42755a719b09662b00c700daaf76cc35d5ace1f5c002ad404b591ff1978" +checksum = "55e37088dec72b7819f980558faaba9215d248fec4a2c3b89357b474f9e46f21" dependencies = [ "anyhow", "cranelift-codegen", @@ -153,9 +170,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d55612bebcf16ff7306c8a6f5bdb6d45662b8aa1ee058ecce8807ad87db719b" +checksum = "e9c3d728819ff644e8613d808378cbfed54fef464790f32e62079e638639eeff" dependencies = [ "anyhow", "cranelift-codegen", @@ -164,9 +181,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dee82f3f1f2c4cba9177f1cc5e350fe98764379bcd29340caa7b01f85076c7" +checksum = "7617f13f392ebb63c5126258aca8b8eca739636ca7e4eeee301d3eff68489a6a" dependencies = [ "cranelift-codegen", "libc", @@ -175,9 +192,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.116.1" +version = "0.117.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad5a6d3e379493c3f8b35dc61c93d0bf5f27003bbe20614e0200b0ec372ef52" +checksum = "60fc9092f7d9bba17c96ce51de5d91461f7905f3e1c43d1ba965df4b884d16ce" dependencies = [ "anyhow", "cranelift-codegen", @@ -226,12 +243,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.2" @@ -248,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown", ] [[package]] @@ -295,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown", "indexmap", "memchr", ] @@ -326,7 +337,7 @@ checksum = "145c1c267e14f20fb0f88aa76a1c5ffec42d592c1d28b3cd9148ae35916158d3" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown", "log", "rustc-hash", "smallvec", @@ -425,9 +436,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "29.0.1" +version = "30.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5e8552e01692e6c2e5293171704fed8abdec79d1a6995a0870ab190e5747d1" +checksum = "3f180cc0d2745e3a5df5d02231cd3046f49c75512eaa987b8202363b112e125d" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 670d6f4eef5c1..fa3037e77a0cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.116.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.116.0" } -cranelift-module = { version = "0.116.0" } -cranelift-native = { version = "0.116.0" } -cranelift-jit = { version = "0.116.0", optional = true } -cranelift-object = { version = "0.116.0" } +cranelift-codegen = { version = "0.117.2", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.117.2" } +cranelift-module = { version = "0.117.2" } +cranelift-native = { version = "0.117.2" } +cranelift-jit = { version = "0.117.2", optional = true } +cranelift-object = { version = "0.117.2" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-29.0.0", version = "0.116.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } From 439062052e9103a6286a4da462303ce56189eaa3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:02:21 +0000 Subject: [PATCH 025/333] Test and dist for arm64 linux on CI --- .github/workflows/abi-cafe.yml | 3 +++ .github/workflows/main.yml | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 30dc5cb16154b..a32a275a027ac 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -25,6 +25,9 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 61a4c1270c993..da0f95c77bb82 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -53,13 +53,12 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin - - os: ubuntu-latest - env: - TARGET_TRIPLE: aarch64-unknown-linux-gnu - apt_deps: gcc-aarch64-linux-gnu qemu-user - os: macos-latest env: TARGET_TRIPLE: aarch64-apple-darwin @@ -192,6 +191,9 @@ jobs: - os: ubuntu-22.04 env: TARGET_TRIPLE: x86_64-unknown-linux-gnu + - os: ubuntu-24.04-arm + env: + TARGET_TRIPLE: aarch64-unknown-linux-gnu - os: macos-latest env: TARGET_TRIPLE: x86_64-apple-darwin From bdcd07466b14db4965536b565c2b6ea5cf4d09d9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:10:43 +0000 Subject: [PATCH 026/333] Use native x86_64 macOS runners for x86_64 builds Rather than running in Rosetta 2. This should make testing on CI faster. --- .github/workflows/main.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index da0f95c77bb82..137504bc0aaa6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -56,7 +56,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -94,10 +94,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Install toolchain and emulator if: matrix.apt_deps != null run: | @@ -194,7 +190,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -220,10 +216,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Prepare dependencies run: ./y.sh prepare From 2695a19fb0fee087899616fe2f5b87e701732520 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:35:27 +0000 Subject: [PATCH 027/333] Use native x86_64 runners for macOS abi-cafe tests too --- .github/workflows/abi-cafe.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index a32a275a027ac..23e15866f52d5 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -28,7 +28,7 @@ jobs: - os: ubuntu-24.04-arm env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - - os: macos-latest + - os: macos-13 env: TARGET_TRIPLE: x86_64-apple-darwin - os: macos-latest @@ -59,10 +59,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use x86_64 compiler on macOS - if: matrix.os == 'macos-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-apple-darwin' - run: rustup set default-host x86_64-apple-darwin - - name: Prepare dependencies run: ./y.sh prepare From 4698eb627647fe6fb78293024585ef27383e6f5a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:52:47 +0000 Subject: [PATCH 028/333] Rustup to rustc 1.87.0-nightly (85abb2763 2025-02-25) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 94b1403e47c10..86052b4df764d 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-24" +channel = "nightly-2025-02-26" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From e173b714aa4307d136871025b1ef6e2a409d06ca Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:05:26 +0000 Subject: [PATCH 029/333] You don't need y.sh prepare to build, only to test Also improve the error message when trying to test without having run y.sh prepare first. --- Readme.md | 2 +- build_system/prepare.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 18a840f8a50e0..28edb5795ce3c 100644 --- a/Readme.md +++ b/Readme.md @@ -49,13 +49,13 @@ If you want to build the backend manually, you can download it from GitHub and b ```bash $ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift -$ ./y.sh prepare $ ./y.sh build ``` To run the test suite replace the last command with: ```bash +$ ./y.sh prepare # only needs to be run the first time $ ./test.sh ``` diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 11f73bdb61f97..ba5cc9a29f599 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -91,6 +91,13 @@ impl GitRepo { fn verify_checksum(&self, dirs: &Dirs) { let download_dir = self.download_dir(dirs); + if !download_dir.exists() { + eprintln!( + "Missing directory {download_dir}: Please run ./y.sh prepare to download.", + download_dir = download_dir.display(), + ); + std::process::exit(1); + } let actual_hash = format!("{:016x}", hash_dir(&download_dir)); if actual_hash != self.content_hash { eprintln!( From 994c8cfaf6c3e717365d5484a43bb20090e85460 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:11:44 +0000 Subject: [PATCH 030/333] Skip downloading test crates in CI jobs that don't need them --- .github/workflows/abi-cafe.yml | 3 --- .github/workflows/main.yml | 6 ------ .github/workflows/rustc.yml | 6 ------ 3 files changed, 15 deletions(-) diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index 23e15866f52d5..6ad041a796c92 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -59,9 +59,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 137504bc0aaa6..7d941887100d8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -165,9 +165,6 @@ jobs: sudo apt update sudo apt install -y hyperfine - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build run: ./y.sh build --sysroot none @@ -216,9 +213,6 @@ jobs: if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Prepare dependencies - run: ./y.sh prepare - - name: Build backend run: ./y.sh build --sysroot none diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index 70c214ce8b147..9253ab96353c3 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -22,9 +22,6 @@ jobs: path: build/cg_clif key: ${{ runner.os }}-rustc-test-cargo-build-target-${{ hashFiles('rust-toolchain', 'Cargo.lock') }} - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_bootstrap.sh @@ -50,8 +47,5 @@ jobs: sudo apt update sudo apt install -y ripgrep - - name: Prepare dependencies - run: ./y.sh prepare - - name: Test run: ./scripts/test_rustc_tests.sh From d27c67c941a0fa14dabfed98b475c8e84ffcc958 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:24:41 +0000 Subject: [PATCH 031/333] Fix FIXME about unversioned macOS target names --- src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a3f4374487578..2c019e7544604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,6 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; -use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -247,9 +246,7 @@ fn enable_verifier(sess: &Session) -> bool { } fn target_triple(sess: &Session) -> target_lexicon::Triple { - // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. - // See - match versioned_llvm_target(sess).parse() { + match sess.target.llvm_target.parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } From 30ece8da06882b9cbca9f7e73f6804c669449a17 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:06:01 +0000 Subject: [PATCH 032/333] Make tiny-skia work on arm64 --- src/intrinsics/llvm.rs | 8 +++ src/intrinsics/llvm_aarch64.rs | 119 +++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 720a0d8fbf593..eb0dfbb69c3b7 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( ); } + "llvm.fptosi.sat.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { + fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane) + }); + } + _ => { fx.tcx .dcx() diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index 4c59c81296bad..b77c99fa2896d 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -1,5 +1,9 @@ //! Emulate AArch64 LLVM intrinsics +use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_target::asm::*; + +use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner}; use crate::intrinsics::*; use crate::prelude::*; @@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( }); } + "llvm.aarch64.neon.fcvtns.v4i32.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + // Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + fcvtns v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecpe.v4f32" => { + intrinsic_args!(fx, args => (a); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + frecpe v0.4s, v0.4s + str q0, [x1]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + + "llvm.aarch64.neon.frecps.v4f32" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a_ptr = a.force_stack(fx).0.get_addr(fx); + let b_ptr = b.force_stack(fx).0.get_addr(fx); + let res_place = CPlace::new_stack_slot(fx, ret.layout()); + let res_ptr = res_place.to_ptr().get_addr(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String( + "ldr q0, [x0] + ldr q1, [x1] + frecps v0.4s, v0.4s, v1.4s + str q0, [x2]" + .into(), + )], + &[ + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x0, + )), + value: a_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x1, + )), + value: b_ptr, + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64( + AArch64InlineAsmReg::x2, + )), + value: res_ptr, + }, + ], + InlineAsmOptions::NOSTACK, + ); + let res = res_place.to_cvalue(fx); + ret.write_cvalue_transmute(fx, res); + } + _ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v") || intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") => { From af9f91696bb3f504a6fc7c235e7eb1999d064acb Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 25 Feb 2025 18:41:49 -0500 Subject: [PATCH 033/333] Fill out links_from_incr_cache in cg_clif --- src/driver/aot.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d1843f90a07d0..fb7864ae6124b 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -464,22 +464,23 @@ fn reuse_workproduct_for_cgu( err )); } + let obj_out_global_asm = crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); - let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { return Err(format!( "unable to copy {} to {}: {}", - source_file_regular.display(), - obj_out_regular.display(), + source_file_global_asm.display(), + obj_out_global_asm.display(), err )); } - true + Some(source_file_global_asm) } else { - false + None }; Ok(ModuleCodegenResult { @@ -491,9 +492,9 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file_regular], }, - module_global_asm: has_global_asm.then(|| CompiledModule { + module_global_asm: source_file_global_asm.map(|source_file| CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_global_asm), @@ -501,7 +502,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), + links_from_incr_cache: vec![source_file], }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -752,6 +753,7 @@ pub(crate) fn run_aot( let metadata_module = if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; + Box::new(OngoingCodegen { modules, allocator_module, From b9ca52582bb6a5b73fc633539b267579e82be422 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2025 16:29:07 +0100 Subject: [PATCH 034/333] =?UTF-8?q?rename=20BackendRepr::Vector=20?= =?UTF-8?q?=E2=86=92=20SimdVector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/abi/pass_mode.rs | 4 ++-- src/intrinsics/mod.rs | 2 +- src/value_and_place.rs | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index b28c4c9539cef..06d89bc9ea7d7 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -84,7 +84,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { AbiParam::new(scalar_to_clif_type(tcx, scalar)), attrs )], - BackendRepr::Vector { .. } => { + BackendRepr::SimdVector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); smallvec![AbiParam::new(vector_ty)] } @@ -135,7 +135,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { BackendRepr::Scalar(scalar) => { (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))]) } - BackendRepr::Vector { .. } => { + BackendRepr::SimdVector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); (None, vec![AbiParam::new(vector_ty)]) } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4d9bed8652cbd..6735ae024d1c5 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -53,7 +53,7 @@ fn report_atomic_type_validation_error<'tcx>( pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type { let (element, count) = match layout.backend_repr { - BackendRepr::Vector { element, count } => (element, count), + BackendRepr::SimdVector { element, count } => (element, count), _ => unreachable!(), }; diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 1b3f86c8405de..cc739fefcd066 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -173,9 +173,11 @@ impl<'tcx> CValue<'tcx> { CValueInner::ByRef(ptr, None) => { let clif_ty = match layout.backend_repr { BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), - BackendRepr::Vector { element, count } => scalar_to_clif_type(fx.tcx, element) - .by(u32::try_from(count).unwrap()) - .unwrap(), + BackendRepr::SimdVector { element, count } => { + scalar_to_clif_type(fx.tcx, element) + .by(u32::try_from(count).unwrap()) + .unwrap() + } _ => unreachable!("{:?}", layout.ty), }; let mut flags = MemFlags::new(); From c4d642616d8fb74d9884bdc0b8df270d13739de3 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 1 Mar 2025 04:47:36 +0100 Subject: [PATCH 035/333] Set target_vendor = "openwrt" On mips64-openwrt-linux-musl target. --- .../rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs | 1 + tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.feature.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 1300280e35b0f..71b3fbe00b2fe 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { + vendor: "openwrt".into(), abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index e7b8f35505761..b07d630e5f5dc 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ba1900fcddb2d..4636b6945d060 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 5328983b077f98a41d6dc3c3af303ae4f3ecccf2 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 25 Feb 2025 19:08:03 +0000 Subject: [PATCH 036/333] Update `compiler-builtins` to 0.1.150 Includes a change to make a subset of math symbols available on all platforms [1], and disables `f16` on aarch64 without neon [2]. [1]: https://github.com/rust-lang/compiler-builtins/pull/763 [2]: https://github.com/rust-lang/compiler-builtins/pull/775 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index bedc6ca11b3f6..d8db7d63f2dda 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From e31bb45e47d78798f6b6d31316f525316bfcaecf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Mar 2025 10:53:58 +0100 Subject: [PATCH 037/333] stabilize const_cell --- library/core/src/cell.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cbf00106c5173..79051588f4432 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -495,7 +495,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] #[rustc_confusables("swap")] pub const fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, @@ -537,7 +537,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get(&self) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -617,7 +617,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -637,7 +637,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn from_mut(t: &mut T) -> &Cell { // SAFETY: `&mut` ensures unique access. unsafe { &*(t as *mut T as *const Cell) } @@ -695,7 +695,7 @@ impl Cell<[T]> { /// assert_eq!(slice_cell.len(), 3); /// ``` #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn as_slice_of_cells(&self) -> &[Cell] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T]> as *const [Cell]) } From 57767d6d998c9998049df14e9c4ccc903396f013 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:35:10 +0000 Subject: [PATCH 038/333] Rustup to rustc 1.87.0-nightly (f4a216d28 2025-03-02) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 86052b4df764d..d9b4f2fc67434 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-02-26" +channel = "nightly-2025-03-03" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 0f9c09fb3a64ff11ea81446a96907cd5e86490c2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:43:05 +0000 Subject: [PATCH 039/333] Remoe has_ptr_meta in favor of tcx.type_has_metadata() --- src/base.rs | 6 ++++-- src/common.rs | 18 ++---------------- src/debuginfo/types.rs | 4 ++-- src/num.rs | 8 ++++++-- src/value_and_place.rs | 6 +++--- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/base.rs b/src/base.rs index 125a9201831ca..adaa754491e56 100644 --- a/src/base.rs +++ b/src/base.rs @@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>( let to_ty = fx.monomorphize(to_ty); fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { - ty.builtin_deref(true) - .is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty)) + ty.builtin_deref(true).is_some_and(|pointee_ty| { + fx.tcx + .type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized()) + }) } if is_wide_ptr(fx, from_ty) { diff --git a/src/common.rs b/src/common.rs index 766278d87183b..abe2972ba0cbd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option pointer_ty(tcx), ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { return None; } else { pointer_ty(tcx) @@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>( (clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?) } ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => { - if has_ptr_meta(tcx, *pointee_ty) { + if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) { (pointer_ty(tcx), pointer_ty(tcx)) } else { return None; @@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>( }) } -/// Is a pointer to this type a wide ptr? -pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) { - return false; - } - - let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized()); - match tail.kind() { - ty::Foreign(..) => false, - ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail), - } -} - pub(crate) fn codegen_icmp_imm( fx: &mut FunctionCx<'_, '_, '_>, intcc: IntCC, diff --git a/src/debuginfo/types.rs b/src/debuginfo/types.rs index 017d7784dc032..25b922c8be4c7 100644 --- a/src/debuginfo/types.rs +++ b/src/debuginfo/types.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; -use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta}; +use crate::{DebugContext, FullyMonomorphizedLayoutCx}; #[derive(Default)] pub(crate) struct TypeDebugContext<'tcx> { @@ -129,7 +129,7 @@ impl DebugContext { let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true); - if !has_ptr_meta(tcx, ptr_type) { + if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) { let pointer_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type); let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id); diff --git a/src/num.rs b/src/num.rs index f44e2459a784d..2a4d1e3ae571d 100644 --- a/src/num.rs +++ b/src/num.rs @@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>( in_lhs: CValue<'tcx>, in_rhs: CValue<'tcx>, ) -> CValue<'tcx> { - let is_thin_ptr = - in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true); + let is_thin_ptr = in_lhs + .layout() + .ty + .builtin_deref(true) + .map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized())) + .unwrap_or(true); if is_thin_ptr { match bin_op { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index cc739fefcd066..f8a19589fdd72 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -746,7 +746,7 @@ impl<'tcx> CPlace<'tcx> { }; let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); - if has_ptr_meta(fx.tcx, field_layout.ty) { + if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) { CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) } else { CPlace::for_ptr(field_ptr, field_layout) @@ -832,7 +832,7 @@ impl<'tcx> CPlace<'tcx> { pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> { let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap()); - if has_ptr_meta(fx.tcx, inner_layout.ty) { + if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) { let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx); CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout) } else { @@ -845,7 +845,7 @@ impl<'tcx> CPlace<'tcx> { fx: &mut FunctionCx<'_, '_, 'tcx>, layout: TyAndLayout<'tcx>, ) -> CValue<'tcx> { - if has_ptr_meta(fx.tcx, self.layout().ty) { + if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) { let (ptr, extra) = self.to_ptr_unsized(); CValue::by_val_pair(ptr.get_addr(fx), extra, layout) } else { From 157137a64aeba7fb6e6571bcc046c97d63d368a7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Feb 2025 15:25:54 +1100 Subject: [PATCH 040/333] Change signature of `target_features_cfg`. Currently it is called twice, once with `allow_unstable` set to true and once with it set to false. This results in some duplicated work. Most notably, for the LLVM backend, `LLVMRustHasFeature` is called twice for every feature, and it's moderately slow. For very short running compilations on platforms with many features (e.g. a `check` build of hello-world on x86) this is a significant fraction of runtime. This commit changes `target_features_cfg` so it is only called once, and it now returns a pair of feature sets. This halves the number of `LLVMRustHasFeature` calls. --- src/lib.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a3f4374487578..06939beb37423 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,13 +176,9 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features_cfg( - &self, - sess: &Session, - _allow_unstable: bool, - ) -> Vec { + fn target_features_cfg(&self, sess: &Session) -> (Vec, Vec) { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] - if sess.target.arch == "x86_64" && sess.target.os != "none" { + let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")] } else if sess.target.arch == "aarch64" { @@ -196,7 +192,10 @@ impl CodegenBackend for CraneliftCodegenBackend { } } else { vec![] - } + }; + // FIXME do `unstable_target_features` properly + let unstable_target_features = target_features.clone(); + (target_features, unstable_target_features) } fn print_version(&self) { From 0ec1d460bb898a22de37bcc040f86449371bdbdb Mon Sep 17 00:00:00 2001 From: sayantn Date: Tue, 4 Mar 2025 20:07:25 +0530 Subject: [PATCH 041/333] Add the new `amx` target features --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 6 ++++++ compiler/rustc_target/src/target_features.rs | 5 +++++ tests/ui/check-cfg/target_feature.stderr | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5cc4f4ab9e673..e3e2e8f2c0be1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -298,6 +298,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("v9")), ("sparc", "v8plus") if get_version().0 < 19 => None, ("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")), + // These new `amx` variants and `movrs` were introduced in LLVM20 + ("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose") + if get_version().0 < 20 => + { + None + } (_, s) => Some(LLVMFeature::new(s)), } } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d05466bb48431..1a4903cdbfa36 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -380,11 +380,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("adx", Stable, &[]), ("aes", Stable, &["sse2"]), + ("amx-avx512", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-fp8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-movrs", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), + ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]), + ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]), ("avx", Stable, &["sse4.2"]), ("avx2", Stable, &["avx"]), ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 5b82d3f539fe1..2060dcc61600c 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -17,11 +17,16 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `aes` `altivec` `alu32` +`amx-avx512` `amx-bf16` `amx-complex` `amx-fp16` +`amx-fp8` `amx-int8` +`amx-movrs` +`amx-tf32` `amx-tile` +`amx-transpose` `atomics` `avx` `avx2` From 7c2434c52caf1fc4269dd2e376fb332d0dd78143 Mon Sep 17 00:00:00 2001 From: sayantn Date: Tue, 4 Mar 2025 20:08:28 +0530 Subject: [PATCH 042/333] Add the `movrs` target feature and `movrs_target_feature` feature gate --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 1 + compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 1 + tests/ui/check-cfg/target_feature.stderr | 1 + .../feature-gate-movrs_target_feature.rs | 6 ++++++ .../feature-gate-movrs_target_feature.stderr | 13 +++++++++++++ 7 files changed, 24 insertions(+) create mode 100644 tests/ui/feature-gates/feature-gate-movrs_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index e3e2e8f2c0be1..7e244e0b2680b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -304,6 +304,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, (_, s) => Some(LLVMFeature::new(s)), } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 841d308418566..4248cac5812be 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -323,6 +323,7 @@ declare_features! ( (unstable, loongarch_target_feature, "1.73.0", Some(44839)), (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), + (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1dc84150cbe50..b932b525aea5a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1348,6 +1348,7 @@ symbols! { movbe_target_feature, move_ref_pattern, move_size_limit, + movrs_target_feature, mul, mul_assign, mul_with_overflow, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 1a4903cdbfa36..e46da2359b97b 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -423,6 +423,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), + ("movrs", Unstable(sym::movrs_target_feature), &[]), ("pclmulqdq", Stable, &["sse2"]), ("popcnt", Stable, &[]), ("prfchw", Unstable(sym::prfchw_target_feature), &[]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 2060dcc61600c..e3133b0af3c5a 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -153,6 +153,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `mclass` `mops` `movbe` +`movrs` `mp` `mp1e2` `msa` diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs new file mode 100644 index 0000000000000..738cab5a06d69 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "movrs")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr new file mode 100644 index 0000000000000..16fe7aaead5c8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movrs_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `movrs` is currently unstable + --> $DIR/feature-gate-movrs_target_feature.rs:2:18 + | +LL | #[target_feature(enable = "movrs")] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #137976 for more information + = help: add `#![feature(movrs_target_feature)]` 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 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 75485a2c093304e93831e6789b38d7aa0024ff3b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 5 Mar 2025 01:35:02 -0500 Subject: [PATCH 043/333] Update `compiler-builtins` to 0.1.151 This enables `f16` builtins for loongarch [1] and adds support for Cygwin [2]. [1]: https://github.com/rust-lang/compiler-builtins/pull/770 [2]: https://github.com/rust-lang/compiler-builtins/pull/774 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index d8db7d63f2dda..c2027863b00b1 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 0fcd068bec1aab1a596f23328769a26f253dfee2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:12:57 +0000 Subject: [PATCH 044/333] Refactor the cli of cg_clif --- docs/usage.md | 4 ++-- scripts/cargo-clif.rs | 5 +++-- scripts/filter_profile.rs | 2 +- src/config.rs | 41 +++++++++++++-------------------------- src/driver/jit.rs | 19 ++++++++---------- src/lib.rs | 17 ++++++++-------- 6 files changed, 35 insertions(+), 53 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 135a51ce392b5..785adbbdf9a82 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -38,7 +38,7 @@ $ $cg_clif_dir/dist/cargo-clif jit or ```bash -$ $cg_clif_dir/dist/rustc-clif -Zunstable-features -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs +$ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs ``` There is also an experimental lazy jit mode. In this mode functions are only compiled once they are @@ -54,7 +54,7 @@ These are a few functions that allow you to easily run rust code from the shell ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cllvm-args=jit-lazy -Cprefer-dynamic } function jit() { diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index ebbb687961058..1ca02bc6a2ce1 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -50,7 +50,7 @@ fn main() { .chain([ "--".to_string(), "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit".to_string(), + "-Cllvm-args=jit-mode".to_string(), ]) .collect() } @@ -62,7 +62,8 @@ fn main() { .chain([ "--".to_string(), "-Zunstable-options".to_string(), - "-Cllvm-args=mode=jit-lazy".to_string(), + "-Cllvm-args=jit-mode".to_string(), + "-Cllvm-args=jit-lazy".to_string(), ]) .collect() } diff --git a/scripts/filter_profile.rs b/scripts/filter_profile.rs index 0252d5b334036..4595063c032dc 100755 --- a/scripts/filter_profile.rs +++ b/scripts/filter_profile.rs @@ -4,7 +4,7 @@ pushd $(dirname "$0")/../ RUSTC="$(pwd)/dist/rustc-clif" popd -PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic $0 +PROFILE=$1 OUTPUT=$2 exec $RUSTC -Zunstable-options -Cllvm-args=jit-mode -Cprefer-dynamic $0 #*/ //! This program filters away uninteresting samples and trims uninteresting frames for stackcollapse diff --git a/src/config.rs b/src/config.rs index d784f6e9d9eb7..30b48786cdc4e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,21 +1,15 @@ -/// The mode to use for compilation. -#[derive(Copy, Clone, Debug)] -pub enum CodegenMode { - /// AOT compile the crate. This is the default. - Aot, - /// JIT compile and execute the crate. - Jit, - /// JIT compile and execute the crate, but only compile functions the first time they are used. - JitLazy, -} - /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars. #[derive(Clone, Debug)] pub struct BackendConfig { /// Should the crate be AOT compiled or JIT executed. /// - /// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`. - pub codegen_mode: CodegenMode, + /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`. + pub jit_mode: bool, + + /// When JIT executing should the lazy JIT mode be used. + /// + /// Defaults to false. Can be set using `-Cllvm-args=jit-lazy`. + pub lazy_jit: bool, /// When JIT mode is enable pass these arguments to the program. /// @@ -27,7 +21,8 @@ impl BackendConfig { /// Parse the configuration passed in using `-Cllvm-args`. pub fn from_opts(opts: &[String]) -> Result { let mut config = BackendConfig { - codegen_mode: CodegenMode::Aot, + jit_mode: false, + lazy_jit: false, jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), Err(std::env::VarError::NotPresent) => vec![], @@ -43,20 +38,10 @@ impl BackendConfig { // testing cg_clif. continue; } - if let Some((name, value)) = opt.split_once('=') { - match name { - "mode" => { - config.codegen_mode = match value { - "aot" => CodegenMode::Aot, - "jit" => CodegenMode::Jit, - "jit-lazy" => CodegenMode::JitLazy, - _ => return Err(format!("Unknown codegen mode `{}`", value)), - }; - } - _ => return Err(format!("Unknown option `{}`", name)), - } - } else { - return Err(format!("Invalid option `{}`", opt)); + match &**opt { + "jit-mode" => config.jit_mode = true, + "jit-lazy" => config.lazy_jit = true, + _ => return Err(format!("Unknown option `{}`", opt)), } } diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 57c88f4b0f9f5..17d55a82e8b5c 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -13,10 +13,10 @@ use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; use rustc_span::sym; +use crate::CodegenCx; use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -use crate::{CodegenCx, CodegenMode}; struct JitState { jit_module: UnwindModule, @@ -79,7 +79,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -88,8 +88,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = - create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy)); + let (mut jit_module, mut cx) = create_jit_module(tcx, jit_lazy); let mut cached_context = Context::new(); let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; @@ -105,9 +104,10 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< super::predefine_mono_items(tcx, &mut jit_module, &mono_items); for (mono_item, _) in mono_items { match mono_item { - MonoItem::Fn(inst) => match codegen_mode { - CodegenMode::Aot => unreachable!(), - CodegenMode::Jit => { + MonoItem::Fn(inst) => { + if jit_lazy { + codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) + } else { codegen_and_compile_fn( tcx, &mut cx, @@ -116,10 +116,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec< inst, ); } - CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) - } - }, + } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); } diff --git a/src/lib.rs b/src/lib.rs index 2c019e7544604..c5ca6565a86b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -213,15 +213,14 @@ impl CodegenBackend for CraneliftCodegenBackend { BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) .unwrap_or_else(|err| tcx.sess.dcx().fatal(err)) }); - match config.codegen_mode { - CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module), - CodegenMode::Jit | CodegenMode::JitLazy => { - #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args); - - #[cfg(not(feature = "jit"))] - tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); - } + if config.jit_mode { + #[cfg(feature = "jit")] + driver::jit::run_jit(tcx, config.lazy_jit, config.jit_args); + + #[cfg(not(feature = "jit"))] + tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); + } else { + driver::aot::run_aot(tcx, metadata, need_metadata_module) } } From 5d03df9431833ad992c1507fedc7daee3e232443 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:35:51 +0000 Subject: [PATCH 045/333] Remove support for the lazy jit mode I might re-implement it in the future, but would probably do so by replacing cranelift-jit. cranelift-jit's api doesn't quite work well for lazy jitting. And even so it adds complexity to cranelift-jit and breaks cranelift-jit outside of x86_64. --- build_system/tests.rs | 14 --- docs/usage.md | 9 +- scripts/cargo-clif.rs | 13 --- src/config.rs | 7 -- src/driver/jit.rs | 214 ++++-------------------------------------- src/lib.rs | 2 +- 6 files changed, 18 insertions(+), 241 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index ea7e94c345ad0..1b1f0f483a334 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -384,20 +384,6 @@ impl<'a> TestRunner<'a> { jit_cmd.env("CG_CLIF_JIT_ARGS", args); } spawn_and_wait(jit_cmd); - - eprintln!("[JIT-lazy] {testname}"); - let mut jit_cmd = self.rustc_command([ - "-Zunstable-options", - "-Cllvm-args=mode=jit-lazy", - "-Cprefer-dynamic", - source, - "--cfg", - "jit", - ]); - if !args.is_empty() { - jit_cmd.env("CG_CLIF_JIT_ARGS", args); - } - spawn_and_wait(jit_cmd); } } } diff --git a/docs/usage.md b/docs/usage.md index 785adbbdf9a82..dbe36109f83e9 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -41,20 +41,13 @@ or $ $cg_clif_dir/dist/rustc-clif -Cllvm-args=jit-mode -Cprefer-dynamic my_crate.rs ``` -There is also an experimental lazy jit mode. In this mode functions are only compiled once they are -first called. - -```bash -$ $cg_clif_dir/dist/cargo-clif lazy-jit -``` - ## Shell These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit. ```bash function jit_naked() { - echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode -Cllvm-args=jit-lazy -Cprefer-dynamic + echo "$@" | $cg_clif_dir/dist/rustc-clif - -Zunstable-options -Cllvm-args=jit-mode-Cprefer-dynamic } function jit() { diff --git a/scripts/cargo-clif.rs b/scripts/cargo-clif.rs index 1ca02bc6a2ce1..e6c63bf5e6508 100644 --- a/scripts/cargo-clif.rs +++ b/scripts/cargo-clif.rs @@ -54,19 +54,6 @@ fn main() { ]) .collect() } - Some("lazy-jit") => { - rustflags.push("-Cprefer-dynamic".to_owned()); - args.remove(0); - IntoIterator::into_iter(["rustc".to_string()]) - .chain(args) - .chain([ - "--".to_string(), - "-Zunstable-options".to_string(), - "-Cllvm-args=jit-mode".to_string(), - "-Cllvm-args=jit-lazy".to_string(), - ]) - .collect() - } _ => args, }; diff --git a/src/config.rs b/src/config.rs index 30b48786cdc4e..d328b33a704f5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,11 +6,6 @@ pub struct BackendConfig { /// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`. pub jit_mode: bool, - /// When JIT executing should the lazy JIT mode be used. - /// - /// Defaults to false. Can be set using `-Cllvm-args=jit-lazy`. - pub lazy_jit: bool, - /// When JIT mode is enable pass these arguments to the program. /// /// Defaults to the value of `CG_CLIF_JIT_ARGS`. @@ -22,7 +17,6 @@ impl BackendConfig { pub fn from_opts(opts: &[String]) -> Result { let mut config = BackendConfig { jit_mode: false, - lazy_jit: false, jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), Err(std::env::VarError::NotPresent) => vec![], @@ -40,7 +34,6 @@ impl BackendConfig { } match &**opt { "jit-mode" => config.jit_mode = true, - "jit-lazy" => config.lazy_jit = true, _ => return Err(format!("Unknown option `{}`", opt)), } } diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 17d55a82e8b5c..4a08937f4aa94 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -1,12 +1,9 @@ //! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object //! files. -use std::cell::RefCell; use std::ffi::CString; use std::os::raw::{c_char, c_int}; -use std::sync::{Mutex, OnceLock, mpsc}; -use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; @@ -18,58 +15,13 @@ use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -struct JitState { - jit_module: UnwindModule, -} - -thread_local! { - static LAZY_JIT_STATE: RefCell> = const { RefCell::new(None) }; -} - -/// The Sender owned by the rustc thread -static GLOBAL_MESSAGE_SENDER: OnceLock>> = OnceLock::new(); - -/// A message that is sent from the jitted runtime to the rustc thread. -/// Senders are responsible for upholding `Send` semantics. -enum UnsafeMessage { - /// Request that the specified `Instance` be lazily jitted. - /// - /// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after - /// this message is sent. - JitFn { - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, - tx: mpsc::Sender<*const u8>, - }, -} -unsafe impl Send for UnsafeMessage {} - -impl UnsafeMessage { - /// Send the message. - fn send(self) { - thread_local! { - /// The Sender owned by the local thread - static LOCAL_MESSAGE_SENDER: mpsc::Sender = - GLOBAL_MESSAGE_SENDER - .get().unwrap() - .lock().unwrap() - .clone(); - } - LOCAL_MESSAGE_SENDER.with(|sender| { - sender.send(self).expect("rustc thread hung up before lazy JIT request was sent") - }) - } -} - -fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule, CodegenCx) { +fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let isa = crate::build_isa(tcx.sess); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); - jit_builder.hotswap(hotswap); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); - jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); @@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -88,7 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = create_jit_module(tcx, jit_lazy); + let (mut jit_module, mut cx) = create_jit_module(tcx); let mut cached_context = Context::new(); let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; @@ -105,17 +57,13 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - if jit_lazy { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) - } else { - codegen_and_compile_fn( - tcx, - &mut cx, - &mut cached_context, - &mut jit_module, - inst, - ); - } + codegen_and_compile_fn( + tcx, + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ); } MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); @@ -158,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_lazy: bool, jit_args: Vec) -> let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap(); let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id); - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - assert!(lazy_jit_state.is_none()); - *lazy_jit_state = Some(JitState { jit_module }); - }); - let f: extern "C" fn(c_int, *const *const c_char) -> c_int = unsafe { ::std::mem::transmute(finalized_start) }; - let (tx, rx) = mpsc::channel(); - GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap(); - - // Spawn the jitted runtime in a new thread so that this rustc thread can handle messages - // (eg to lazily JIT further functions as required) - std::thread::spawn(move || { - let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); + let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::>(); - // Push a null pointer as a terminating argument. This is required by POSIX and - // useful as some dynamic linkers use it as a marker to jump over. - argv.push(std::ptr::null()); + // Push a null pointer as a terminating argument. This is required by POSIX and + // useful as some dynamic linkers use it as a marker to jump over. + argv.push(std::ptr::null()); - let ret = f(args.len() as c_int, argv.as_ptr()); - std::process::exit(ret); - }); - - // Handle messages - loop { - match rx.recv().unwrap() { - // lazy JIT compilation request - compile requested instance and return pointer to result - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => { - tx.send(jit_fn(instance_ptr, trampoline_ptr)) - .expect("jitted runtime hung up before response to lazy JIT request was sent"); - } - } - } + let ret = f(args.len() as c_int, argv.as_ptr()); + std::process::exit(ret); } pub(crate) fn codegen_and_compile_fn<'tcx>( @@ -224,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( }); } -extern "C" fn clif_jit_fn( - instance_ptr: *const Instance<'static>, - trampoline_ptr: *const u8, -) -> *const u8 { - // send the JIT request to the rustc thread, with a channel for the response - let (tx, rx) = mpsc::channel(); - UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send(); - - // block on JIT compilation result - rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request") -} - -fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 { - rustc_middle::ty::tls::with(|tcx| { - // lift is used to ensure the correct lifetime for instance. - let instance = tcx.lift(unsafe { *instance_ptr }).unwrap(); - - LAZY_JIT_STATE.with(|lazy_jit_state| { - let mut lazy_jit_state = lazy_jit_state.borrow_mut(); - let lazy_jit_state = lazy_jit_state.as_mut().unwrap(); - let jit_module = &mut lazy_jit_state.jit_module; - - let name = tcx.symbol_name(instance).name; - let sig = crate::abi::get_function_sig( - tcx, - jit_module.target_config().default_call_conv, - instance, - ); - let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let current_ptr = jit_module.module.read_got_entry(func_id); - - // If the function's GOT entry has already been updated to point at something other - // than the shim trampoline, don't re-jit but just return the new pointer instead. - // This does not need synchronization as this code is executed only by a sole rustc - // thread. - if current_ptr != trampoline_ptr { - return current_ptr; - } - - jit_module.module.prepare_for_function_redefine(func_id).unwrap(); - - let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); - codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); - - assert!(cx.global_asm.is_empty()); - jit_module.finalize_definitions(); - jit_module.module.get_finalized_function(func_id) - }) - }) -} - fn dep_symbol_lookup_fn( sess: &Session, crate_info: CrateInfo, @@ -323,57 +195,3 @@ fn dep_symbol_lookup_fn( None }) } - -fn codegen_shim<'tcx>( - tcx: TyCtxt<'tcx>, - cached_context: &mut Context, - module: &mut UnwindModule, - inst: Instance<'tcx>, -) { - let pointer_type = module.target_config().pointer_type(); - - let name = tcx.symbol_name(inst).name; - let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst); - let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap(); - - let instance_ptr = Box::into_raw(Box::new(inst)); - - let jit_fn = module - .declare_function( - "__clif_jit_fn", - Linkage::Import, - &Signature { - call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)], - returns: vec![AbiParam::new(pointer_type)], - }, - ) - .unwrap(); - - let context = cached_context; - context.clear(); - let trampoline = &mut context.func; - trampoline.signature = sig.clone(); - - let mut builder_ctx = FunctionBuilderContext::new(); - let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx); - - let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func); - let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func); - let sig_ref = trampoline_builder.func.import_signature(sig); - - let entry_block = trampoline_builder.create_block(); - trampoline_builder.append_block_params_for_function_params(entry_block); - let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec(); - - trampoline_builder.switch_to_block(entry_block); - let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64); - let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn); - let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]); - let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0]; - let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args); - let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); - trampoline_builder.ins().return_(&ret_vals); - - module.define_function(func_id, context).unwrap(); -} diff --git a/src/lib.rs b/src/lib.rs index c5ca6565a86b9..4d97c3ae6048a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,7 +215,7 @@ impl CodegenBackend for CraneliftCodegenBackend { }); if config.jit_mode { #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config.lazy_jit, config.jit_args); + driver::jit::run_jit(tcx, config.jit_args); #[cfg(not(feature = "jit"))] tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); From 5cdb8663563fa1fc47a869d790e5cd06eaf1de3e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:51:35 +0000 Subject: [PATCH 046/333] Update rust-analyzer config mod_bench no longer exists and there is no benefit to not having a sysroot available for mini_core and mini_core_hello_world. --- .vscode/settings.json | 33 ++++++++++++++++----------------- .zed/settings.json | 25 ++++++++++--------------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 491646ce59bb3..68bd93aea8901 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,41 +1,40 @@ { "editor.formatOnSave": true, - // in case rustc.source is disabled for performance reasons; disable the errors about this - "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], + "rust-analyzer.diagnostics.disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ], "rust-analyzer.rustc.source": "discover", "rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.prefix": "crate", - "rust-analyzer.cargo.features": ["unstable-features"], + "rust-analyzer.cargo.features": [ + "unstable-features" + ], "rust-analyzer.linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [], }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", - "deps": [{ "crate": 0, "name": "mini_core" }], - "cfg": [], - }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], + "edition": "2015", + "deps": [ + { + "crate": 0, + "name": "mini_core" + } + ], "cfg": [], }, - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", diff --git a/.zed/settings.json b/.zed/settings.json index e93bed3694921..4338a3473311b 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -5,7 +5,10 @@ "initialization_options": { "diagnostics": { // in case rustc.source is disabled for performance reasons; disable the errors about this - "disabled": ["unresolved-extern-crate", "unresolved-macro-call"] + "disabled": [ + "unresolved-extern-crate", + "unresolved-macro-call" + ] }, "rustc": { "source": "discover" @@ -18,22 +21,25 @@ "prefix": "crate" }, "cargo": { - "features": ["unstable-features"] + "features": [ + "unstable-features" + ] }, "linkedProjects": [ "./Cargo.toml", "./build_system/Cargo.toml", { + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/mini_core.rs", - "edition": "2018", + "edition": "2015", "deps": [], "cfg": [] }, { "root_module": "./example/mini_core_hello_world.rs", - "edition": "2018", + "edition": "2015", "deps": [ { "crate": 0, @@ -42,17 +48,6 @@ ], "cfg": [] }, - { - "root_module": "./example/mod_bench.rs", - "edition": "2018", - "deps": [], - "cfg": [] - } - ] - }, - { - "sysroot_src": "./build/stdlib/library", - "crates": [ { "root_module": "./example/std_example.rs", "edition": "2015", From 7eb0a99fc9ff5ee3870a07926d5137d434ee22ab Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:55:41 +0000 Subject: [PATCH 047/333] Fix jit mode testing --- build_system/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 1b1f0f483a334..9ec0d3850f115 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -374,7 +374,7 @@ impl<'a> TestRunner<'a> { TestCaseCmd::JitBin { source, args } => { let mut jit_cmd = self.rustc_command([ "-Zunstable-options", - "-Cllvm-args=mode=jit", + "-Cllvm-args=jit-mode", "-Cprefer-dynamic", source, "--cfg", From f048c4501839701e27443abe68407f2824197137 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:40:11 +0000 Subject: [PATCH 048/333] Rustup to rustc 1.87.0-nightly (30f168ef8 2025-03-05) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d9b4f2fc67434..4a566552322aa 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-03" +channel = "nightly-2025-03-06" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 75109ec1ba2fe1b5182f2accab3e31a1b6e810f7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:46:54 +0000 Subject: [PATCH 049/333] FIx rustc test suite --- scripts/test_rustc_tests.sh | 40 +++++++------------------------------ 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 599ce63bab56d..63f3c8b05036f 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -152,46 +152,20 @@ rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ -# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by -# rustdoc-clif cat < Self { - #[track_caller] - pub fn new() -> Self { - let mut cmd = setup_common(); -- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR")); - Self { cmd } - } - diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index e7ae773ffa1d3..04bc2d7787da7 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs -@@ -329,7 +329,6 @@ impl TestCx<'_> { +@@ -117,7 +117,6 @@ impl TestCx<'_> { .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) .arg("--edition=2021") - .arg(&self.testpaths.file.join("rmake.rs")) -- .arg("-Cprefer-dynamic") - // Provide necessary library search paths for rustc. - .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap()); +- .arg(&self.testpaths.file.join("rmake.rs")) +- .arg("-Cprefer-dynamic"); ++ .arg(&self.testpaths.file.join("rmake.rs")); + // In test code we want to be very pedantic about values being silently discarded that are + // annotated with \`#[must_use]\`. diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c..f7895b12961 100644 --- a/tests/run-make/linker-warning/rmake.rs @@ -205,7 +179,7 @@ index 30387af428c..f7895b12961 100644 regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", ) - .run(); + .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"") EOF echo "[TEST] rustc test suite" From aa31d42b39cf9a7c216736392aa522a94794c071 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 12:51:22 +0000 Subject: [PATCH 050/333] Remove no longer necessary disabling of dylib usage for run-make tests Run-make tests are now fully compiled using the bootstrap compiler. --- scripts/test_rustc_tests.sh | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 63f3c8b05036f..005e87c2b2ad7 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -150,22 +150,8 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist -cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ cat < { - .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) - .arg("--edition=2021") -- .arg(&self.testpaths.file.join("rmake.rs")) -- .arg("-Cprefer-dynamic"); -+ .arg(&self.testpaths.file.join("rmake.rs")); - - // In test code we want to be very pedantic about values being silently discarded that are - // annotated with \`#[must_use]\`. diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c..f7895b12961 100644 --- a/tests/run-make/linker-warning/rmake.rs From 4b7bcdbf9fcfa4972a97e7cc47b105d7b3711b19 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:16:09 +0000 Subject: [PATCH 051/333] Use the github cli to publish dev releases This removes a whole bunch of complicated javascript with two lines of bash. Fixes rust-lang/rustc_codegen_cranelift#1562 --- .github/actions/github-release/README.md | 18 - .github/actions/github-release/action.yml | 13 - .github/actions/github-release/main.js | 162 ----- .../actions/github-release/package-lock.json | 571 ------------------ .github/actions/github-release/package.json | 11 - .github/workflows/main.yml | 15 +- 6 files changed, 6 insertions(+), 784 deletions(-) delete mode 100644 .github/actions/github-release/README.md delete mode 100644 .github/actions/github-release/action.yml delete mode 100644 .github/actions/github-release/main.js delete mode 100644 .github/actions/github-release/package-lock.json delete mode 100644 .github/actions/github-release/package.json diff --git a/.github/actions/github-release/README.md b/.github/actions/github-release/README.md deleted file mode 100644 index c70ba8f495387..0000000000000 --- a/.github/actions/github-release/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# github-release - -An action used to publish GitHub releases for `wasmtime`. - -As of the time of this writing there's a few actions floating around which -perform github releases but they all tend to have their set of drawbacks. -Additionally nothing handles deleting releases which we need for our rolling -`dev` release. - -To handle all this this action rolls-its-own implementation using the -actions/toolkit repository and packages published there. These run in a Docker -container and take various inputs to orchestrate the release from the build. - -More comments can be found in `main.js`. - -Testing this is really hard. If you want to try though run `npm install` and -then `node main.js`. You'll have to configure a bunch of env vars though to get -anything reasonably working. diff --git a/.github/actions/github-release/action.yml b/.github/actions/github-release/action.yml deleted file mode 100644 index 36e5209f50c3b..0000000000000 --- a/.github/actions/github-release/action.yml +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -name: 'rustc_codegen_cranelift github releases' -description: 'rustc_codegen_cranelift github releases' -inputs: - token: - description: '' - required: true - files: - description: '' - required: true -runs: - using: 'node16' - main: 'main.js' diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js deleted file mode 100644 index 1eb2b7f23b26c..0000000000000 --- a/.github/actions/github-release/main.js +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -const core = require('@actions/core'); -const path = require("path"); -const fs = require("fs"); -const github = require('@actions/github'); -const glob = require('glob'); - -function sleep(milliseconds) { - return new Promise(resolve => setTimeout(resolve, milliseconds)) -} - -async function runOnce() { - // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` - const files = core.getInput('files'); - const token = core.getInput('token'); - const slug = process.env.GITHUB_REPOSITORY; - const owner = slug.split('/')[0]; - const repo = slug.split('/')[1]; - const sha = process.env.GITHUB_SHA; - let name = 'dev'; - if (process.env.GITHUB_REF.startsWith('refs/tags/v')) { - name = process.env.GITHUB_REF.substring(10); - } - - core.info(`files: ${files}`); - core.info(`name: ${name}`); - core.info(`token: ${token}`); - - const octokit = github.getOctokit(token); - - // For the `dev` release we may need to update the tag to point to the new - // commit on this branch. All other names should already have tags associated - // with them. - if (name == 'dev') { - let tag = null; - try { - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - core.info(`found existing tag`); - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - } catch (e) { - // ignore if this tag doesn't exist - core.info(`no existing tag found`); - } - - if (tag === null || tag.data.object.sha !== sha) { - core.info(`updating existing tag or creating new one`); - - try { - core.info(`updating dev tag`); - await octokit.rest.git.updateRef({ - owner, - repo, - ref: 'tags/dev', - sha, - force: true, - }); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e.response, null, 2)); - core.info(`creating dev tag`); - try { - await octokit.rest.git.createRef({ - owner, - repo, - ref: 'refs/tags/dev', - sha, - }); - } catch (e) { - // we might race with others, so assume someone else has created the - // tag by this point. - console.log("failed to create tag: ", JSON.stringify(e.response, null, 2)); - } - } - - console.log("double-checking tag is correct"); - tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); - if (tag.data.object.sha !== sha) { - console.log("tag: ", JSON.stringify(tag.data, null, 2)); - throw new Error("tag didn't work"); - } - } else { - core.info(`existing tag works`); - } - } - - // Delete a previous release - try { - core.info(`fetching release`); - let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name }); - console.log("found release: ", JSON.stringify(release.data, null, 2)); - await octokit.rest.repos.deleteRelease({ - owner, - repo, - release_id: release.data.id, - }); - console.log("deleted release"); - } catch (e) { - console.log("ERROR: ", JSON.stringify(e, null, 2)); - } - - console.log("creating a release"); - let release = await octokit.rest.repos.createRelease({ - owner, - repo, - tag_name: name, - prerelease: name === 'dev', - }); - - // Delete all assets from a previous run - for (const asset of release.data.assets) { - console.log(`deleting prior asset ${asset.id}`); - await octokit.rest.repos.deleteReleaseAsset({ - owner, - repo, - asset_id: asset.id, - }); - } - - // Upload all the relevant assets for this release as just general blobs. - for (const file of glob.sync(files)) { - const size = fs.statSync(file).size; - const name = path.basename(file); - core.info(`upload ${file}`); - await octokit.rest.repos.uploadReleaseAsset({ - data: fs.createReadStream(file), - headers: { 'content-length': size, 'content-type': 'application/octet-stream' }, - name, - url: release.data.upload_url, - }); - } -} - -async function run() { - const retries = 10; - for (let i = 0; i < retries; i++) { - try { - await runOnce(); - break; - } catch (e) { - if (i === retries - 1) - throw e; - logError(e); - console.log("RETRYING after 10s"); - await sleep(10000) - } - } -} - -function logError(e) { - console.log("ERROR: ", e.message); - try { - console.log(JSON.stringify(e, null, 2)); - } catch (e) { - // ignore json errors for now - } - console.log(e.stack); -} - -run().catch(err => { - logError(err); - core.setFailed(err.message); -}); diff --git a/.github/actions/github-release/package-lock.json b/.github/actions/github-release/package-lock.json deleted file mode 100644 index dd3b2a048f094..0000000000000 --- a/.github/actions/github-release/package-lock.json +++ /dev/null @@ -1,571 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } - }, - "node_modules/@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "node_modules/@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "dependencies": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "node_modules/@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "dependencies": { - "tunnel": "^0.0.6" - } - }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - }, - "dependencies": { - "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", - "requires": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - } - }, - "@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", - "requires": { - "@actions/http-client": "^2.0.1", - "@octokit/core": "^3.6.0", - "@octokit/plugin-paginate-rest": "^2.17.0", - "@octokit/plugin-rest-endpoint-methods": "^5.13.0" - } - }, - "@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "requires": { - "tunnel": "^0.0.6" - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "requires": { - "@octokit/types": "^6.40.0" - } - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/.github/actions/github-release/package.json b/.github/actions/github-release/package.json deleted file mode 100644 index d9c23f8873ece..0000000000000 --- a/.github/actions/github-release/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "rustc_codegen_cranelift-github-release", - "version": "0.0.0", - "license": "Apache-2.0 WITH LLVM-exception", - "main": "main.js", - "dependencies": { - "@actions/core": "^1.9.1", - "@actions/github": "^5.1.0", - "glob": "^7.1.5" - } -} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7d941887100d8..6fd288d195c05 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -261,12 +261,9 @@ jobs: rmdir artifacts/ # verify all artifacts are represented in release/ ls -R release/ - - run: npm install --production - working-directory: .github/actions/github-release - - - name: Publish Release - uses: ./.github/actions/github-release - with: - files: "release/*" - token: ${{ github.token }} - continue-on-error: true + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release delete --cleanup-tag -y dev || true + gh release create --target $GITHUB_SHA --prerelease dev release/* From fd3fb2cf46a155682eee50ef8d6f84cac4ef154d Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 5 Mar 2025 18:14:07 -0800 Subject: [PATCH 052/333] Remove #[cfg(not(test))] gates in core These gates are unnecessary now that unit tests for `core` are in a separate package, `coretests`, instead of in the same files as the source code. They previously prevented the two `core` versions from conflicting with each other. --- ...0027-stdlib-128bit-atomic-operations.patch | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/patches/0027-stdlib-128bit-atomic-operations.patch b/patches/0027-stdlib-128bit-atomic-operations.patch index 3c81b04c0ead2..d7e3b11127c42 100644 --- a/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/patches/0027-stdlib-128bit-atomic-operations.patch @@ -1,4 +1,4 @@ -From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 +From 5d7c709608b01301d4628d2159265936d4440b67 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 18 Feb 2021 18:45:28 +0100 Subject: [PATCH] Disable 128bit atomic operations @@ -7,11 +7,10 @@ Cranelift doesn't support them yet --- library/core/src/panic/unwind_safe.rs | 6 ----- library/core/src/sync/atomic.rs | 38 --------------------------- - library/core/tests/atomic.rs | 4 --- - 4 files changed, 4 insertions(+), 50 deletions(-) + 2 files changed, 44 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs -index 092b7cf..158cf71 100644 +index a60f0799c0e..af056fbf41f 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} @@ -21,7 +20,7 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} - + #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] @@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} @@ -31,14 +30,14 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} - + #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index d9de37e..8293fce 100644 +index bf2b6d59f88..d5ccce03bbf 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -2996,44 +2996,6 @@ atomic_int! { +@@ -3585,44 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { 8, u64 AtomicU64 } @@ -54,7 +53,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"), +- rustc_diagnostic_item = "AtomicI128", - "i128", - "#![feature(integer_atomics)]\n\n", - atomic_min, atomic_max, @@ -73,7 +72,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"), +- rustc_diagnostic_item = "AtomicU128", - "u128", - "#![feature(integer_atomics)]\n\n", - atomic_umin, atomic_umax, @@ -83,7 +82,6 @@ index d9de37e..8293fce 100644 #[cfg(target_has_atomic_load_store = "ptr")] macro_rules! atomic_int_ptr_sized { - ( $($target_pointer_width:literal $align:literal)* ) => { $( --- -2.26.2.7.g19db9cfb68 +-- +2.48.1 From 540565e5b97b4669cd84ecd57f3d7affd00e83a1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:46:33 +0000 Subject: [PATCH 053/333] Fully test the alloc crate through alloctests For the tests that make use of internal implementation details, we include the module to test using #[path] in alloctests now. --- ...9-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index c2027863b00b1..754025ff49db3 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -12,15 +12,15 @@ index 7165c3e48af..968552ad435 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -11,7 +11,7 @@ test = { path = "../test" } - edition = "2021" + bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } - [dev-dependencies] - rand = { version = "0.8.5", default-features = false, features = ["alloc"] } + [features] + compiler-builtins-mem = ['compiler_builtins/mem'] -- 2.34.1 From f86a71dfbf35b36b1ce439f65dfe51f591688393 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Sat, 8 Mar 2025 00:23:46 -0500 Subject: [PATCH 054/333] [AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n)) This PR updates the lint added in 9b40bd7 to ignore repr(C) structs that also have repr(packed) or repr(align(n)). As these representations can be modifiers on repr(C), it is assumed that users that add these should know what they are doing, and thus the the lint should not warn on the respective structs. For example, for the time being, using repr(packed) and manually padding a repr(C) struct can be done to correctly align struct members on AIX. --- compiler/rustc_lint/src/types.rs | 6 ++++++ tests/ui/layout/reprc-power-alignment.rs | 26 +++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fcadbfc3c4a7e..71116d0bfe42b 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1638,6 +1638,9 @@ impl ImproperCTypesDefinitions { return true; } else if let Adt(adt_def, _) = ty.kind() && adt_def.is_struct() + && adt_def.repr().c() + && !adt_def.repr().packed() + && adt_def.repr().align.is_none() { let struct_variant = adt_def.variant(VariantIdx::ZERO); // Within a nested struct, all fields are examined to correctly @@ -1659,8 +1662,11 @@ impl ImproperCTypesDefinitions { item: &'tcx hir::Item<'tcx>, ) { let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id()); + // repr(C) structs also with packed or aligned representation + // should be ignored. if adt_def.repr().c() && !adt_def.repr().packed() + && adt_def.repr().align.is_none() && cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() { diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs index f6c1df55988ba..f144094d43fbc 100644 --- a/tests/ui/layout/reprc-power-alignment.rs +++ b/tests/ui/layout/reprc-power-alignment.rs @@ -148,5 +148,29 @@ pub struct I { d: f32, e: f64, } - +#[repr(C)] +pub struct J { + a: u8, + b: I, +} +// The lint also ignores diagnosing #[repr(align(n))]. +#[repr(C, align(8))] +pub struct K { + a: u8, + b: u8, + c: f64, + d: f32, + e: f64, +} +#[repr(C)] +pub struct L { + a: u8, + b: K, +} +#[repr(C, align(8))] +pub struct M { + a: u8, + b: K, + c: L, +} fn main() { } From d9de94001a25d33d4ba77cfa686c65f49264264c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 26 Jul 2024 10:04:02 +0000 Subject: [PATCH 055/333] Implement `#[define_opaque]` attribute for functions. --- example/issue-72793.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/example/issue-72793.rs b/example/issue-72793.rs index 2e08fbca8ef27..95d58b90e7981 100644 --- a/example/issue-72793.rs +++ b/example/issue-72793.rs @@ -2,23 +2,21 @@ #![feature(type_alias_impl_trait)] -mod helper { - pub trait T { - type Item; - } +pub trait T { + type Item; +} - pub type Alias<'a> = impl T; +pub type Alias<'a> = impl T; - struct S; - impl<'a> T for &'a S { - type Item = &'a (); - } +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} - pub fn filter_positive<'a>() -> Alias<'a> { - &S - } +#[define_opaque(Alias)] +pub fn filter_positive<'a>() -> Alias<'a> { + &S } -use helper::*; fn with_positive(fun: impl Fn(Alias<'_>)) { fun(filter_positive()); From 56715d986483f17af09dc2d73c99d20f7def7ab4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 08:03:54 +0100 Subject: [PATCH 056/333] intrinsics: remove unnecessary leading underscore from argument names --- example/mini_core.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 72c9df59d833f..6e345b2a6fdf0 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -624,25 +624,25 @@ pub mod intrinsics { #[rustc_intrinsic] pub fn size_of() -> usize; #[rustc_intrinsic] - pub unsafe fn size_of_val(_val: *const T) -> usize; + pub unsafe fn size_of_val(val: *const T) -> usize; #[rustc_intrinsic] pub fn min_align_of() -> usize; #[rustc_intrinsic] - pub unsafe fn min_align_of_val(_val: *const T) -> usize; + pub unsafe fn min_align_of_val(val: *const T) -> usize; #[rustc_intrinsic] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); + pub unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic] - pub unsafe fn transmute(_e: T) -> U; + pub unsafe fn transmute(e: T) -> U; #[rustc_intrinsic] - pub unsafe fn ctlz_nonzero(_x: T) -> u32; + pub unsafe fn ctlz_nonzero(x: T) -> u32; #[rustc_intrinsic] pub fn needs_drop() -> bool; #[rustc_intrinsic] - pub fn bitreverse(_x: T) -> T; + pub fn bitreverse(x: T) -> T; #[rustc_intrinsic] - pub fn bswap(_x: T) -> T; + pub fn bswap(x: T) -> T; #[rustc_intrinsic] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); + pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize); #[rustc_intrinsic] pub unsafe fn unreachable() -> !; } From 4ca551cf41d8273a2829f19a8e802fb557f14d6f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:08:42 +0000 Subject: [PATCH 057/333] Rustup to rustc 1.87.0-nightly (665025243 2025-03-11) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4a566552322aa..ec730a4402cf0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-06" +channel = "nightly-2025-03-12" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From d2b328e6b3a4cd42b85a289ce3285ca0ac461e7c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:08:50 +0000 Subject: [PATCH 058/333] Reduce verbosity of ./scripts/rustup.sh pull --- scripts/rustup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rustup.sh b/scripts/rustup.sh index 355282911c255..152c243aa6adc 100755 --- a/scripts/rustup.sh +++ b/scripts/rustup.sh @@ -64,7 +64,7 @@ case $1 in cg_clif=$(pwd) pushd ../rust git fetch origin master - git checkout "$RUST_VERS" + git -c advice.detachedHead=false checkout "$RUST_VERS" "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust popd git merge sync_from_rust -m "Sync from rust $RUST_VERS" From eea0db2590a79b58d1354c86954382e2952f7749 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:18:52 +0000 Subject: [PATCH 059/333] Fix rustc test suite --- scripts/test_rustc_tests.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 005e87c2b2ad7..5e96210d85898 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -166,6 +166,18 @@ index 30387af428c..f7895b12961 100644 "/build-root", ) .normalize(r#""[^"]*\/symbols.o""#, "\\"/symbols.o\\"") +diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs +index 073116933bd..c3e4578204d 100644 +--- a/src/tools/compiletest/src/runtest/run_make.rs ++++ b/src/tools/compiletest/src/runtest/run_make.rs +@@ -109,7 +109,6 @@ pub(super) fn run_rmake_test(&self) { + // library or compiler features. Here, we force the stage 0 rustc to consider itself as + // a stable-channel compiler via \`RUSTC_BOOTSTRAP=-1\` to prevent *any* unstable + // library/compiler usages, even if stage 0 rustc is *actually* a nightly rustc. +- .env("RUSTC_BOOTSTRAP", "-1") + .arg("-o") + .arg(&recipe_bin) + // Specify library search paths for \`run_make_support\`. EOF echo "[TEST] rustc test suite" From 65bd61d2fbef50d28caed626ce601a908d5be77f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 12 Mar 2025 09:47:11 +0100 Subject: [PATCH 060/333] Fix armv7-sony-vita-newlibeabihf LLVM target triple It was previously normalized by LLVM to `thumbv7a-vita-unknown-eabihf`, which is probably wrong, as Vita is the OS. --- .../src/spec/targets/armv7_sony_vita_newlibeabihf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs index 5d292bbf8adf0..6a83835059eee 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { ); Target { - llvm_target: "thumbv7a-vita-eabihf".into(), + llvm_target: "thumbv7a-sony-vita-eabihf".into(), metadata: TargetMetadata { description: Some( "Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(), From eab700a0aa4ad3079ad043a9cb4fb89edab3b4b7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 12 Mar 2025 23:37:35 +0100 Subject: [PATCH 061/333] Fix uclibc LLVM target triples `uclibc` is not an environment understood by LLVM, it is only a concept in Clang that can be selected with `-muclibc` (it affects which dynamic linker is passed to the static linker's `-dynamic-linker` flag). In fact, using `uclibcgnueabi`/`uclibc` is actively harmful, as it prevents LLVM from seeing that the target is gnu-like; we should use `gnueabi`/`gnu` directly instead. --- .../src/spec/targets/armv5te_unknown_linux_uclibceabi.rs | 2 +- .../rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs | 2 +- .../src/spec/targets/mipsel_unknown_linux_uclibc.rs | 2 +- .../rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index dbe1540364ad8..860629b08e19b 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs @@ -2,7 +2,7 @@ use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(), + llvm_target: "armv5te-unknown-linux-gnueabi".into(), metadata: TargetMetadata { description: Some("Armv5TE Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index 0955b3debea00..c14bfbf46d21d 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mips-unknown-linux-uclibc".into(), + llvm_target: "mips-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 08c4347fe0145..f0056799d66f6 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -2,7 +2,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mipsel-unknown-linux-uclibc".into(), + llvm_target: "mipsel-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS (LE) Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index a034a9fb24453..4107249dcf1e3 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -8,7 +8,7 @@ pub(crate) fn target() -> Target { base.panic_strategy = PanicStrategy::Abort; Target { - llvm_target: "x86_64-unknown-l4re-uclibc".into(), + llvm_target: "x86_64-unknown-l4re-gnu".into(), metadata: TargetMetadata { description: None, tier: Some(3), From 025eecc3e7e36bb60bdd4e30ae05b9fa3876d14f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 12:36:40 +0100 Subject: [PATCH 062/333] atomic intrinsics: clarify which types are supported and (if applicable) what happens with provenance --- src/intrinsics/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 6735ae024d1c5..75f3a3c19724f 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1031,7 +1031,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1052,7 +1052,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1073,7 +1073,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Int(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); @@ -1094,7 +1094,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = src.layout(); match layout.ty.kind() { - ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} + ty::Uint(_) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); return Ok(()); From 2d2307e6163816511790c3bb61e07913d9cb66c1 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:01:53 +0100 Subject: [PATCH 063/333] Dedup `&mut *` reborrow suggestion in loops --- .../src/diagnostics/conflict_errors.rs | 13 ------------- tests/ui/borrowck/mut-borrow-in-loop-2.stderr | 4 ---- 2 files changed, 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2694a1eda78d7..a2df4e4e47d5c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -181,7 +181,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; - let mut in_pattern = false; let mut seen_spans = FxIndexSet::default(); for move_site in &move_site_vec { @@ -204,7 +203,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_ref_or_clone( mpi, &mut err, - &mut in_pattern, move_spans, moved_place.as_ref(), &mut has_suggest_reborrow, @@ -256,15 +254,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.body, self.infcx.tcx).ty; - // If we're in pattern, we do nothing in favor of the previous suggestion (#80913). - // Same for if we're in a loop, see #101119. - if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) { - if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { - // We have a `&mut` ref, we need to reborrow on each iteration (#62112). - self.suggest_reborrow(&mut err, span, moved_place); - } - } - if self.infcx.param_env.caller_bounds().iter().any(|c| { c.as_trait_clause().is_some_and(|pred| { pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id()) @@ -330,7 +319,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { &self, mpi: MovePathIndex, err: &mut Diag<'infcx>, - in_pattern: &mut bool, move_spans: UseSpans<'tcx>, moved_place: PlaceRef<'tcx>, has_suggest_reborrow: &mut bool, @@ -545,7 +533,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && !move_span.is_dummy() && !self.infcx.tcx.sess.source_map().is_imported(move_span) { - *in_pattern = true; let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; if let Some(pat) = finder.parent_pat { sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string())); diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr index 4f32df1eb24e2..46e06bc91b91c 100644 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -12,10 +12,6 @@ help: consider creating a fresh reborrow of `value` here | LL | Other::handle(&mut *value); | ++++++ -help: consider creating a fresh reborrow of `value` here - | -LL | Other::handle(&mut *value); - | ++++++ error: aborting due to 1 previous error From f9696dda6e9d88a88c057e93fbc854104996bc33 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 7 Mar 2025 17:52:17 +0000 Subject: [PATCH 064/333] Prefer built-in sized impls for rigid types always --- compiler/rustc_middle/src/traits/select.rs | 5 +++- .../src/traits/select/candidate_assembly.rs | 24 +++++++++++++++---- .../src/traits/select/confirmation.rs | 5 ++++ .../src/traits/select/mod.rs | 13 +++++++++- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 811bd8fb4588a..749f3c31bf8db 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -95,10 +95,13 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), /// parameter environment. #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] pub enum SelectionCandidate<'tcx> { + /// UwU + SizedCandidate, + /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. /// - /// The most notable examples are `sized`, `Copy` and `Clone`. This is also + /// The most notable examples are `Copy` and `Clone`. This is also /// used for the `DiscriminantKind` and `Pointee` trait, both of which have /// an associated type. BuiltinCandidate { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a8d8003ead6ea..9c0efec2e6cf6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -86,10 +86,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `Pointee` is automatically implemented for every type. candidates.vec.push(BuiltinCandidate { has_nested: false }); } else if tcx.is_lang_item(def_id, LangItem::Sized) { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates); + self.assemble_builtin_sized_candidate(obligation, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::Unsize) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else if tcx.is_lang_item(def_id, LangItem::Destruct) { @@ -1059,6 +1056,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Assembles the trait which are built-in to the language itself: /// `Copy`, `Clone` and `Sized`. #[instrument(level = "debug", skip(self, candidates))] + fn assemble_builtin_sized_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + match self.sized_conditions(obligation) { + BuiltinImplConditions::Where(_) => { + candidates.vec.push(SizedCandidate); + } + BuiltinImplConditions::None => {} + BuiltinImplConditions::Ambiguous => { + candidates.ambiguous = true; + } + } + } + + /// Assembles the trait which are built-in to the language itself: + /// e.g. `Copy` and `Clone`. + #[instrument(level = "debug", skip(self, candidates))] fn assemble_builtin_bound_candidates( &mut self, conditions: BuiltinImplConditions<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4cd6781ab8905..349eab2cbe39b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -40,6 +40,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { let mut impl_src = match candidate { + SizedCandidate => { + let data = self.confirm_builtin_candidate(obligation, true); + ImplSource::Builtin(BuiltinImplSource::Misc, data) + } + BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e1adabbeaa662..674ff30786bc3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1801,6 +1801,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { return Some(candidates.pop().unwrap().candidate); } + // We prefer `Sized` candidates over everything. + let mut sized_candidates = + candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); + if let Some(_sized_candidate) = sized_candidates.next() { + // There should only ever be a single sized candidate + // as they would otherwise overlap. + debug_assert_eq!(sized_candidates.next(), None); + return Some(SizedCandidate); + } + // We prefer trivial builtin candidates, i.e. builtin impls without any nested // requirements, over all others. This is a fix for #53123 and prevents winnowing // from accidentally extending the lifetime of a variable. @@ -1940,7 +1950,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Don't use impl candidates which overlap with other candidates. // This should pretty much only ever happen with malformed impls. if candidates.iter().all(|c| match c.candidate { - BuiltinCandidate { has_nested: _ } + SizedCandidate + | BuiltinCandidate { has_nested: _ } | TransmutabilityCandidate | AutoImplCandidate | ClosureCandidate { .. } From aebbd424607b7797f231bc09f44226fcd3040d7e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 10 Mar 2025 16:50:29 +0000 Subject: [PATCH 065/333] Only prefer Sized candidates, and only if they certainly hold --- compiler/rustc_middle/src/traits/select.rs | 7 +++-- .../src/traits/select/candidate_assembly.rs | 6 ++-- .../src/traits/select/confirmation.rs | 4 +-- .../src/traits/select/mod.rs | 28 ++++++++----------- .../dont-incompletely-prefer-built-in.rs | 21 ++++++++++++++ ...incomplete-prefer-sized-builtin-over-wc.rs | 19 +++++++++++++ ...mplete-prefer-sized-builtin-over-wc.stderr | 27 ++++++++++++++++++ 7 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 tests/ui/sized/dont-incompletely-prefer-built-in.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 749f3c31bf8db..aa2ee756bc502 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -95,8 +95,11 @@ pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), /// parameter environment. #[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)] pub enum SelectionCandidate<'tcx> { - /// UwU - SizedCandidate, + /// A built-in implementation for the `Sized` trait. This is preferred + /// over all other candidates. + SizedCandidate { + has_nested: bool, + }, /// A builtin implementation for some specific traits, used in cases /// where we cannot rely an ordinary library implementations. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9c0efec2e6cf6..316198f9e012f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1062,8 +1062,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { match self.sized_conditions(obligation) { - BuiltinImplConditions::Where(_) => { - candidates.vec.push(SizedCandidate); + BuiltinImplConditions::Where(nested) => { + candidates + .vec + .push(SizedCandidate { has_nested: !nested.skip_binder().is_empty() }); } BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 349eab2cbe39b..29e0b833665b7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -40,8 +40,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { let mut impl_src = match candidate { - SizedCandidate => { - let data = self.confirm_builtin_candidate(obligation, true); + SizedCandidate { has_nested } => { + let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 674ff30786bc3..956417b122c6a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1803,25 +1803,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We prefer `Sized` candidates over everything. let mut sized_candidates = - candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate)); - if let Some(_sized_candidate) = sized_candidates.next() { + candidates.iter().filter(|c| matches!(c.candidate, SizedCandidate { has_nested: _ })); + if let Some(sized_candidate) = sized_candidates.next() { // There should only ever be a single sized candidate // as they would otherwise overlap. debug_assert_eq!(sized_candidates.next(), None); - return Some(SizedCandidate); - } - - // We prefer trivial builtin candidates, i.e. builtin impls without any nested - // requirements, over all others. This is a fix for #53123 and prevents winnowing - // from accidentally extending the lifetime of a variable. - let mut trivial_builtin = candidates - .iter() - .filter(|c| matches!(c.candidate, BuiltinCandidate { has_nested: false })); - if let Some(_trivial) = trivial_builtin.next() { - // There should only ever be a single trivial builtin candidate - // as they would otherwise overlap. - debug_assert_eq!(trivial_builtin.next(), None); - return Some(BuiltinCandidate { has_nested: false }); + // Only prefer the built-in `Sized` candidate if its nested goals are certain. + // Otherwise, we may encounter failure later on if inference causes this candidate + // to not hold, but a where clause would've applied instead. + if sized_candidate.evaluation.must_apply_modulo_regions() { + return Some(sized_candidate.candidate.clone()); + } else { + return None; + } } // Before we consider where-bounds, we have to deduplicate them here and also @@ -1950,7 +1944,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Don't use impl candidates which overlap with other candidates. // This should pretty much only ever happen with malformed impls. if candidates.iter().all(|c| match c.candidate { - SizedCandidate + SizedCandidate { has_nested: _ } | BuiltinCandidate { has_nested: _ } | TransmutabilityCandidate | AutoImplCandidate diff --git a/tests/ui/sized/dont-incompletely-prefer-built-in.rs b/tests/ui/sized/dont-incompletely-prefer-built-in.rs new file mode 100644 index 0000000000000..f5bf0c8915e76 --- /dev/null +++ b/tests/ui/sized/dont-incompletely-prefer-built-in.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +struct W(T); + +fn is_sized(x: *const T) {} + +fn dummy() -> *const T { todo!() } + +fn non_param_where_bound() +where + W: Sized, +{ + let x: *const W<_> = dummy(); + is_sized::>(x); + let _: *const W = x; +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs new file mode 100644 index 0000000000000..cc3303dccd570 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs @@ -0,0 +1,19 @@ +struct MyType<'a, T: ?Sized>(&'a (), T); + +fn is_sized() {} + +fn foo<'a, T: ?Sized>() +where + (MyType<'a, T>,): Sized, + //~^ ERROR mismatched types + MyType<'static, T>: Sized, +{ + // Preferring the builtin `Sized` impl of tuples + // requires proving `MyType<'a, T>: Sized` which + // can only be proven by using the where-clause, + // adding an unnecessary `'static` constraint. + is_sized::<(MyType<'a, T>,)>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr new file mode 100644 index 0000000000000..a54574f743f8e --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:7:23 + | +LL | (MyType<'a, T>,): Sized, + | ^^^^^ lifetime mismatch + | + = note: expected trait ` as Sized>` + found trait ` as Sized>` +note: the lifetime `'a` as defined here... + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:5:8 + | +LL | fn foo<'a, T: ?Sized>() + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:15:5 + | +LL | fn foo<'a, T: ?Sized>() + | -- lifetime `'a` defined here +... +LL | is_sized::<(MyType<'a, T>,)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From c0230f4a2904e968f4afd833e44db1f4ebe29b21 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 21:17:46 +0000 Subject: [PATCH 066/333] Flesh out tests --- ...complete-infer-via-sized-wc.current.stderr | 9 ++++++ .../incomplete-infer-via-sized-wc.next.stderr | 9 ++++++ .../traits/incomplete-infer-via-sized-wc.rs | 19 +++++++++++++ ...complete-prefer-sized-builtin-over-wc-2.rs | 28 +++++++++++++++++++ ...efer-sized-builtin-over-wc.current.stderr} | 6 ++-- ...e-prefer-sized-builtin-over-wc.next.stderr | 25 +++++++++++++++++ ...incomplete-prefer-sized-builtin-over-wc.rs | 9 +++++- 7 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr create mode 100644 tests/ui/traits/incomplete-infer-via-sized-wc.rs create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs rename tests/ui/traits/{lifetime-incomplete-prefer-sized-builtin-over-wc.stderr => lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr} (85%) create mode 100644 tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr new file mode 100644 index 0000000000000..f4930bf890c2b --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.current.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-infer-via-sized-wc.rs:15:5 + | +LL | is_sized::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr new file mode 100644 index 0000000000000..f4930bf890c2b --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.next.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-infer-via-sized-wc.rs:15:5 + | +LL | is_sized::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_sized` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/incomplete-infer-via-sized-wc.rs b/tests/ui/traits/incomplete-infer-via-sized-wc.rs new file mode 100644 index 0000000000000..9dcddea3551d1 --- /dev/null +++ b/tests/ui/traits/incomplete-infer-via-sized-wc.rs @@ -0,0 +1,19 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + +struct MaybeSized(T); + +fn is_sized() -> Box { todo!() } + +fn foo() +where + MaybeSized: Sized, +{ + is_sized::>(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs new file mode 100644 index 0000000000000..8a8f7b933b539 --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc-2.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + +trait Trait: Sized {} +impl Trait for T {} + +fn is_sized() {} + +fn normal_ref<'a, 'b, T>() +where + &'a u32: Trait, +{ + is_sized::<&'b u32>(); +} + +struct MyRef<'a, U: ?Sized = ()>(&'a u32, U); +fn my_ref<'a, 'b, T>() +where + MyRef<'a>: Trait, +{ + is_sized::>(); +} + +fn main() {} diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr similarity index 85% rename from tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr rename to tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr index a54574f743f8e..dd9393fae853d 100644 --- a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.stderr +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:7:23 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23 | LL | (MyType<'a, T>,): Sized, | ^^^^^ lifetime mismatch @@ -7,14 +7,14 @@ LL | (MyType<'a, T>,): Sized, = note: expected trait ` as Sized>` found trait ` as Sized>` note: the lifetime `'a` as defined here... - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:5:8 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8 | LL | fn foo<'a, T: ?Sized>() | ^^ = note: ...does not necessarily outlive the static lifetime error: lifetime may not live long enough - --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:15:5 + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5 | LL | fn foo<'a, T: ?Sized>() | -- lifetime `'a` defined here diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr new file mode 100644 index 0000000000000..05861877d413b --- /dev/null +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.next.stderr @@ -0,0 +1,25 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:13:23 + | +LL | (MyType<'a, T>,): Sized, + | ^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:11:8 + | +LL | fn foo<'a, T: ?Sized>() + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/lifetime-incomplete-prefer-sized-builtin-over-wc.rs:22:5 + | +LL | fn foo<'a, T: ?Sized>() + | -- lifetime `'a` defined here +... +LL | is_sized::<(MyType<'a, T>,)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs index cc3303dccd570..ae7a6c9bba335 100644 --- a/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs +++ b/tests/ui/traits/lifetime-incomplete-prefer-sized-builtin-over-wc.rs @@ -1,3 +1,9 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Exercises change in . + struct MyType<'a, T: ?Sized>(&'a (), T); fn is_sized() {} @@ -5,7 +11,8 @@ fn is_sized() {} fn foo<'a, T: ?Sized>() where (MyType<'a, T>,): Sized, - //~^ ERROR mismatched types + //[current]~^ ERROR mismatched types + //[next]~^^ ERROR lifetime bound not satisfied MyType<'static, T>: Sized, { // Preferring the builtin `Sized` impl of tuples From 5bb37b7580aaab8578cb7bb30cf1a62cbfb85a27 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:55:32 +0000 Subject: [PATCH 067/333] Fix usage of vector registers in inline asm on arm64 --- src/inline_asm.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 310b226814d40..59d109341311e 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -652,6 +652,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) .unwrap(), }, + InlineAsmArch::AArch64 => match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit( + &mut generated_asm, + InlineAsmArch::AArch64, + Some(modifier.unwrap_or('q')), + ) + .unwrap() + } + _ => reg + .emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier) + .unwrap(), + }, _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(), } } @@ -809,7 +823,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" str "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { @@ -851,7 +871,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } InlineAsmArch::AArch64 => { generated_asm.push_str(" ldr "); - reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); + match reg { + InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => { + // rustc emits v0 rather than q0 + reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap() + } + _ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(), + } writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } InlineAsmArch::RiscV64 => { From a4b76e31f8f906e31256b2c8f696e39b2ee36c41 Mon Sep 17 00:00:00 2001 From: Yang Lin Date: Sun, 16 Mar 2025 23:27:10 +0800 Subject: [PATCH 068/333] Adapt to rust-lang/rust#136466: Start removing `rustc_middle::hir::map::Map` Following commit f86f7ad from pull request #136466 in the Rust project (https://github.com/rust-lang/rust), some methods in `Map` were moved to `TyCtxt`. This update reimplements `rustc-drive-example.rs`, `rustc-driver-interacting-with-the-ast.rs`, and `rustc-interface-example.rs` using the new versions of these methods, ensuring compatibility with the nightly-2025-03-08 toolchain. --- src/doc/rustc-dev-guide/examples/rustc-driver-example.rs | 7 +++---- .../examples/rustc-driver-interacting-with-the-ast.rs | 8 +++----- .../rustc-dev-guide/examples/rustc-interface-example.rs | 7 +++---- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 984bd3e37ae30..35dd07dd13657 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -71,9 +71,8 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items(){ + let item = &tcx.hir_item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { let name = item.ident; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 3270c722e0772..2a43ba476e1ea 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -70,11 +70,9 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { - // Every compilation contains a single crate. - let hir_krate = tcx.hir(); // Iterate over the top-level items in the crate, looking for the main function. - for id in hir_krate.items() { - let item = hir_krate.item(id); + for id in tcx.hir_free_items(){ + let item = &tcx.hir_item(id); // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn { body, .. } = item.kind { let expr = &tcx.hir_body(body).value; diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 70f27c2a82a9c..11125caec7040 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -64,9 +64,8 @@ fn main() { println!("{krate:?}"); // Analyze the program and inspect the types of definitions. rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - for id in tcx.hir().items() { - let hir = tcx.hir(); - let item = hir.item(id); + for id in tcx.hir_free_items() { + let item = tcx.hir_item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { let name = item.ident; From 9a2d1fdb141ec2db9be1802316c66722f7b678f8 Mon Sep 17 00:00:00 2001 From: Yang Lin Date: Sun, 16 Mar 2025 23:43:17 +0800 Subject: [PATCH 069/333] Following commit 401dd84 in the Rust project (https://github.com/rust-lang/rust), `ErrorGuaranteed` was replaced by fatal errors. As a result, `tcx.analysis()` now aborts directly instead of returning an error guard. To accommodate this change, this update replaces `tcx.analysis()` with `typeck()` to perform type checking in the example. --- .../examples/rustc-interface-getting-diagnostics.rs | 8 +++++--- .../src/rustc-driver/getting-diagnostics.md | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 39b236e1783a6..9bb93ab495878 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-02-13 +// Tested with nightly-2025-03-08 #![feature(rustc_private)] @@ -86,8 +86,10 @@ fn main() { rustc_interface::run_compiler(config, |compiler| { let krate = rustc_interface::passes::parse(&compiler.sess); rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - // Run the analysis phase on the local crate to trigger the type error. - let _ = tcx.analysis(()); + // Iterate all the items defined and perform type checking. + tcx.par_hir_body_owners(|item_def_id| { + tcx.ensure_ok().typeck(item_def_id); + }); }); // If the compiler has encountered errors when this closure returns, it will abort (!) the program. // We avoid this by resetting the error count before returning diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md index 1043df6ecb65c..518cf4e821a72 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md @@ -7,7 +7,7 @@ otherwise be printed to stderr. To get diagnostics from the compiler, configure [`rustc_interface::Config`] to output diagnostic to a buffer, -and run [`TyCtxt.analysis`]. +and run [`rustc_hir_typeck::typeck`] for each item. ```rust {{#include ../../examples/rustc-interface-getting-diagnostics.rs}} @@ -16,3 +16,4 @@ and run [`TyCtxt.analysis`]. [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html [`rustc_interface::Config`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html [`TyCtxt.analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.analysis.html +[`rustc_hir_typeck::typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn.typeck.html From 3270d71cec47bc8bf02352bafef8cc5edec3b7a2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 2 Dec 2023 14:17:33 +0000 Subject: [PATCH 070/333] Remove implicit #[no_mangle] for #[rustc_std_internal_symbol] --- src/allocator.rs | 30 +++++++++++++++++++++++------- src/lib.rs | 1 + 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 5e33b9d606fa5..9cff8a84db3d9 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -7,6 +7,7 @@ use rustc_ast::expand::allocator::{ }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::prelude::*; @@ -14,6 +15,7 @@ use crate::prelude::*; pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; codegen_inner( + tcx, module, kind, tcx.alloc_error_handler_kind(()).unwrap(), @@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { } fn codegen_inner( + tcx: TyCtxt<'_>, module: &mut dyn Module, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, @@ -62,8 +65,8 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - &global_fn_name(method.name), - &default_fn_name(method.name), + &mangle_internal_symbol(tcx, &global_fn_name(method.name)), + &mangle_internal_symbol(tcx, &default_fn_name(method.name)), ); } } @@ -76,19 +79,32 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), ); - let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); let val = oom_strategy.should_panic(); data.define(Box::new([val])); module.define_data(data_id, &data).unwrap(); - let data_id = - module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); data.define(Box::new([0])); diff --git a/src/lib.rs b/src/lib.rs index 06939beb37423..ab3386a9b4ccf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_index; extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; #[macro_use] extern crate tracing; From 93a9102a06d4f1860f3881060e1f4f5c5a37dab6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:01:19 +0000 Subject: [PATCH 071/333] Rustup to rustc 1.87.0-nightly (43a2e9d2c 2025-03-17) --- patches/coretests-lock.toml | 26 ++++++++++++++++++++++++++ rust-toolchain | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/patches/coretests-lock.toml b/patches/coretests-lock.toml index bb7f519f7a7c0..d648923782295 100644 --- a/patches/coretests-lock.toml +++ b/patches/coretests-lock.toml @@ -8,6 +8,7 @@ version = "0.0.0" dependencies = [ "rand", "rand_xorshift", + "regex", ] [[package]] @@ -56,6 +57,31 @@ dependencies = [ "rand_core", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "syn" version = "2.0.98" diff --git a/rust-toolchain b/rust-toolchain index ec730a4402cf0..1b2751c86e3cd 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-12" +channel = "nightly-2025-03-18" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From ebef14a7b6664c9f054f20f6803da17c31387ad5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:40:43 +0000 Subject: [PATCH 072/333] Reuse the Cargo.lock of the library workspace for coretests --- build_system/tests.rs | 27 ++-- config.txt | 2 +- ...root_tests-128bit-atomic-operations.patch} | 12 +- ...ot_tests-Disable-long-running-tests.patch} | 8 +- patches/coretests-lock.toml | 120 ------------------ 5 files changed, 22 insertions(+), 147 deletions(-) rename patches/{0027-coretests-128bit-atomic-operations.patch => 0027-sysroot_tests-128bit-atomic-operations.patch} (84%) rename patches/{0028-coretests-Disable-long-running-tests.patch => 0028-sysroot_tests-Disable-long-running-tests.patch} (87%) delete mode 100644 patches/coretests-lock.toml diff --git a/build_system/tests.rs b/build_system/tests.rs index 9ec0d3850f115..9b4e2857519fa 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -1,5 +1,4 @@ use std::ffi::OsStr; -use std::fs; use std::path::PathBuf; use std::process::Command; @@ -126,9 +125,9 @@ static PORTABLE_SIMD_SRC: RelPath = RelPath::build("portable-simd"); static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target"); -static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests"); +static SYSROOT_TESTS_SRC: RelPath = RelPath::build("sysroot_tests"); -static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target"); +static SYSROOT_TESTS: CargoProject = CargoProject::new(&SYSROOT_TESTS_SRC, "sysroot_tests_target"); const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.rust-random/rand", &|runner| { @@ -147,28 +146,24 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(build_cmd); } }), - TestCase::custom("test.libcore", &|runner| { + TestCase::custom("test.sysroot", &|runner| { apply_patches( &runner.dirs, - "coretests", - &runner.stdlib_source.join("library/coretests"), - &LIBCORE_TESTS_SRC.to_path(&runner.dirs), + "sysroot_tests", + &runner.stdlib_source.join("library"), + &SYSROOT_TESTS_SRC.to_path(&runner.dirs), ); - let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml"); - let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock"); - fs::copy(source_lockfile, target_lockfile).unwrap(); - - LIBCORE_TESTS.clean(&runner.dirs); + SYSROOT_TESTS.clean(&runner.dirs); if runner.is_native { - let mut test_cmd = LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs); - test_cmd.arg("--").arg("-q"); + let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs); + test_cmd.args(["-p", "coretests", "--", "-q"]); spawn_and_wait(test_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = LIBCORE_TESTS.build(&runner.target_compiler, &runner.dirs); - build_cmd.arg("--tests"); + let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs); + build_cmd.args(["-p", "coretests", "--tests"]); spawn_and_wait(build_cmd); } }), diff --git a/config.txt b/config.txt index f578cbef35e68..714414fe8d685 100644 --- a/config.txt +++ b/config.txt @@ -35,6 +35,6 @@ aot.raw-dylib testsuite.extended_sysroot test.rust-random/rand -test.libcore +test.sysroot test.regex test.portable-simd diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-sysroot_tests-128bit-atomic-operations.patch similarity index 84% rename from patches/0027-coretests-128bit-atomic-operations.patch rename to patches/0027-sysroot_tests-128bit-atomic-operations.patch index 4a06dc3f7ef85..16c8488acdb56 100644 --- a/patches/0027-coretests-128bit-atomic-operations.patch +++ b/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -10,20 +10,20 @@ Cranelift doesn't support them yet library/core/tests/atomic.rs | 4 --- 4 files changed, 4 insertions(+), 50 deletions(-) -diff --git a/tests/lib.rs b/tests/lib.rs +diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs index 1e336bf..35e6f54 100644 ---- a/tests/lib.rs -+++ b/tests/lib.rs +--- a/coretests/tests/lib.rs ++++ b/coretests/tests/lib.rs @@ -2,5 +2,4 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] #![feature(array_chunks)] -diff --git a/tests/atomic.rs b/tests/atomic.rs +diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs index b735957..ea728b6 100644 ---- a/tests/atomic.rs -+++ b/tests/atomic.rs +--- a/coretests/tests/atomic.rs ++++ b/coretests/tests/atomic.rs @@ -185,10 +185,6 @@ fn atomic_alignment() { assert_eq!(align_of::(), size_of::()); #[cfg(target_has_atomic = "64")] diff --git a/patches/0028-coretests-Disable-long-running-tests.patch b/patches/0028-sysroot_tests-Disable-long-running-tests.patch similarity index 87% rename from patches/0028-coretests-Disable-long-running-tests.patch rename to patches/0028-sysroot_tests-Disable-long-running-tests.patch index f5ae66c0eb13d..50d93ec99dba5 100644 --- a/patches/0028-coretests-Disable-long-running-tests.patch +++ b/patches/0028-sysroot_tests-Disable-long-running-tests.patch @@ -4,13 +4,13 @@ Date: Fri, 3 Dec 2021 12:16:30 +0100 Subject: [PATCH] Disable long running tests --- - library/core/tests/slice.rs | 2 ++ + library/coretests/tests/slice.rs | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/tests/slice.rs b/tests/slice.rs +diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs index 8402833..84592e0 100644 ---- a/tests/slice.rs -+++ b/tests/slice.rs +--- a/coretests/tests/slice.rs ++++ b/coretests/tests/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { } } diff --git a/patches/coretests-lock.toml b/patches/coretests-lock.toml deleted file mode 100644 index d648923782295..0000000000000 --- a/patches/coretests-lock.toml +++ /dev/null @@ -1,120 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "coretests" -version = "0.0.0" -dependencies = [ - "rand", - "rand_xorshift", - "regex", -] - -[[package]] -name = "proc-macro2" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" -dependencies = [ - "rand_core", - "zerocopy", -] - -[[package]] -name = "rand_core" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "rand_xorshift" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" -dependencies = [ - "rand_core", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "syn" -version = "2.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" - -[[package]] -name = "zerocopy" -version = "0.8.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] From 1adce908c60370fba57f342426ac151823860b02 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:52:12 +0000 Subject: [PATCH 073/333] Run alloctests tests too --- build_system/tests.rs | 4 +- ...oot_tests-Disable-long-running-tests.patch | 57 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 9b4e2857519fa..36e108726121b 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -158,12 +158,12 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ if runner.is_native { let mut test_cmd = SYSROOT_TESTS.test(&runner.target_compiler, &runner.dirs); - test_cmd.args(["-p", "coretests", "--", "-q"]); + test_cmd.args(["-p", "coretests", "-p", "alloctests", "--", "-q"]); spawn_and_wait(test_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); let mut build_cmd = SYSROOT_TESTS.build(&runner.target_compiler, &runner.dirs); - build_cmd.args(["-p", "coretests", "--tests"]); + build_cmd.args(["-p", "coretests", "-p", "alloctests", "--tests"]); spawn_and_wait(build_cmd); } }), diff --git a/patches/0028-sysroot_tests-Disable-long-running-tests.patch b/patches/0028-sysroot_tests-Disable-long-running-tests.patch index 50d93ec99dba5..357b8d306cf6a 100644 --- a/patches/0028-sysroot_tests-Disable-long-running-tests.patch +++ b/patches/0028-sysroot_tests-Disable-long-running-tests.patch @@ -43,6 +43,63 @@ index 8402833..84592e0 100644 #[test] fn test_slice_from_ptr_range() { +diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs +index d321f8d..8b2040a 100644 +--- a/alloctests/tests/sort/tests.rs ++++ b/alloctests/tests/sort/tests.rs +@@ -1,3 +1,5 @@ ++#![cfg(any())] ++ + use std::cell::Cell; + use std::cmp::Ordering; + use std::fmt::Debug; +diff --git a/alloctests/tests/str.rs b/alloctests/tests/str.rs +index 906fa2d..b82fa99 100644 +--- a/alloctests/tests/str.rs ++++ b/alloctests/tests/str.rs +@@ -2234,7 +2234,7 @@ fn const_str_ptr() { + const C: *const u8 = B as *const u8; + + // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) +- #[cfg(not(miri))] ++ #[cfg(any())] + { + let foo = &A as *const u8; + assert_eq!(foo, C); +diff --git a/alloctests/tests/task.rs b/alloctests/tests/task.rs +index 390dec1..87df6e6 100644 +--- a/alloctests/tests/task.rs ++++ b/alloctests/tests/task.rs +@@ -4,7 +4,7 @@ use alloc::task::{LocalWake, Wake}; + use core::task::{LocalWaker, Waker}; + + #[test] +-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail ++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail + fn test_waker_will_wake_clone() { + struct NoopWaker; + +@@ -20,7 +20,7 @@ fn test_waker_will_wake_clone() { + } + + #[test] +-#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail ++#[ignore] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail + fn test_local_waker_will_wake_clone() { + struct NoopWaker; + +diff --git a/alloctests/tests/vec.rs b/alloctests/tests/vec.rs +index f430d97..cfbd3cb 100644 +--- a/alloctests/tests/vec.rs ++++ b/alloctests/tests/vec.rs +@@ -762,6 +762,7 @@ fn test_drain_inclusive_range() { + } + + #[test] ++#[ignore] + fn test_drain_max_vec_size() { + let mut v = Vec::<()>::with_capacity(usize::MAX); + unsafe { -- 2.26.2.7.g19db9cfb68 From 3e448fd4f5e55b24b943dd4d85287ce0b17105ee Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 5 Mar 2025 13:18:17 +0800 Subject: [PATCH 074/333] Add chapter Remarks on perma-unstable features Signed-off-by: xizheyin --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../remarks-on-perma-unstable-features.md | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 106db508ebbc7..71b58f79daf28 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -124,6 +124,7 @@ - [rustc_driver and rustc_interface](./rustc-driver/intro.md) - [Example: Type checking](./rustc-driver/interacting-with-the-ast.md) - [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md) + - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md) - [Errors and Lints](diagnostics.md) - [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md) - [Translation](./diagnostics/translation.md) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md new file mode 100644 index 0000000000000..c307adc00a006 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md @@ -0,0 +1,55 @@ + +# Remarks on perma unstable features + +## `rustc_private` + +### Overview + +The `rustc_private` feature allows external crates to use compiler internals. + +### Using `rustc-private` with Official Toolchains + +When using the `rustc_private` feature with official Rust toolchains distributed via rustup, you need to install two additional components: + +1. **`rustc-dev`**: Provides compiler libraries +2. **`llvm-tools`**: Provides LLVM libraries required for linking + +#### Installation Steps + +Install both components using rustup: + +```bash +rustup component add rustc-dev llvm-tools +``` + +#### Common Error + +Without the `llvm-tools` component, you'll encounter linking errors like: + +``` +error: linking with `cc` failed: exit status: 1 + | + = note: rust-lld: error: unable to find library -lLLVM-{version} +``` + +### Using `rustc-private` with Custom Toolchains + +For custom-built toolchains or environments not using rustup, additional configuration is typically required: + +#### Requirements + +- LLVM libraries must be available in your system's library search paths +- The LLVM version must match the one used to build your Rust toolchain + +#### Troubleshooting Steps + +1. **Check LLVM installation**: Verify LLVM is installed and accessible +2. **Configure library paths**: You may need to set environment variables: + ```bash + export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH + ``` +3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain + +### Additional Resources + +- [GitHub Issue #137421](https://github.com/rust-lang/rust/issues/137421): Explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed From cb4a25ca81e266703a8ffa4fe80a53e954bb992d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 18 Mar 2025 14:39:46 +0000 Subject: [PATCH 075/333] Remove liballoc compiler-builtins f16/f128 disable patch We already build with the compiler-builtins-no-f16-f128 feature enabled. --- ...le-f16-and-f128-in-compiler-builtins.patch | 26 ------------------- scripts/setup_rust_fork.sh | 1 + 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch deleted file mode 100644 index 754025ff49db3..0000000000000 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Fri, 9 Aug 2024 15:44:51 +0000 -Subject: [PATCH] Disable f16 and f128 in compiler-builtins - ---- - library/liballoc/Cargo.toml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml -index 7165c3e48af..968552ad435 100644 ---- a/library/alloc/Cargo.toml -+++ b/library/alloc/Cargo.toml -@@ -11,7 +11,7 @@ test = { path = "../test" } - bench = false - - [dependencies] - core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } - - [features] - compiler-builtins-mem = ['compiler_builtins/mem'] --- -2.34.1 - diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 54f6baff4fecf..c2c8e625f60b5 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -43,6 +43,7 @@ verbose-tests = false # disabled bootstrap will crash trying to copy llvm tools for the bootstrap # compiler. llvm-tools = false +std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"] EOF popd From 74698d7c2cb9cc6722b9ce5c7b32e3da61e38e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:16:28 +0100 Subject: [PATCH 076/333] Add Fuchsia ping group notice --- src/doc/rustc-dev-guide/src/tests/fuchsia.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/fuchsia.md index e96290b921529..926803368f087 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/fuchsia.md @@ -4,6 +4,14 @@ million lines of Rust code.[^loc] It has caught a large number of [regressions] in the past and was subsequently included in CI. +## What to do if the Fuchsia job breaks? + +Please contact the `fuchsia` ping group and ask them for help. + +```text +@rustbot ping fuchsia +``` + ## Building Fuchsia in CI Fuchsia builds as part of the suite of bors tests that run before a pull request From 9ff4936afbc57912aed05f822133af6b5da3f0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:17:59 +0100 Subject: [PATCH 077/333] Reorder RfL tests page to move the "what if it breaks" section to the top --- .../src/tests/rust-for-linux.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md index c674d1575b781..bdf32ffc398db 100644 --- a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md @@ -3,26 +3,7 @@ [Rust for Linux](https://rust-for-linux.com/) (RfL) is an effort for adding support for the Rust programming language into the Linux kernel. -## Building Rust for Linux in CI - -Rust for Linux builds as part of the suite of bors tests that run before a pull -request is merged. - -The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux -kernel, and tries to compile several Rust for Linux drivers and examples using -this sysroot. RfL uses several unstable compiler/language features, therefore -this workflow notifies us if a given compiler change would break it. - -If you are worried that a pull request might break the Rust for Linux builder -and want to test it out before submitting it to the bors queue, simply add this -line to your PR description: - -> try-job: x86_64-rust-for-linux - -Then when you `@bors try` it will pick the job that builds the Rust for Linux -integration. - -## What to do in case of failure +## What to do if the Rust for Linux job breaks? If a PR breaks the Rust for Linux CI job, then: @@ -48,4 +29,23 @@ ping group to ask for help: @rustbot ping rfl ``` +## Building Rust for Linux in CI + +Rust for Linux builds as part of the suite of bors tests that run before a pull +request is merged. + +The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux +kernel, and tries to compile several Rust for Linux drivers and examples using +this sysroot. RfL uses several unstable compiler/language features, therefore +this workflow notifies us if a given compiler change would break it. + +If you are worried that a pull request might break the Rust for Linux builder +and want to test it out before submitting it to the bors queue, simply add this +line to your PR description: + +> try-job: x86_64-rust-for-linux + +Then when you `@bors try` it will pick the job that builds the Rust for Linux +integration. + [rfl-ping]: ../notification-groups/rust-for-linux.md From c987d34a7e14abf5b7065bfd6c27eb52d2863773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 18 Mar 2025 16:19:55 +0100 Subject: [PATCH 078/333] Add Fuchsia ping group page --- src/doc/rustc-dev-guide/src/SUMMARY.md | 3 ++- .../src/notification-groups/fuchsia.md | 12 ++++++++++++ src/doc/rustc-dev-guide/src/tests/fuchsia.md | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index a090f96f3f806..9e2d0774aab0b 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -61,12 +61,13 @@ - [ARM](notification-groups/arm.md) - [Cleanup Crew](notification-groups/cleanup-crew.md) - [Emscripten](notification-groups/emscripten.md) + - [Fuchsia](notification-groups/fuchsia.md) - [LLVM](notification-groups/llvm.md) - [RISC-V](notification-groups/risc-v.md) + - [Rust for Linux](notification-groups/rust-for-linux.md) - [WASI](notification-groups/wasi.md) - [WebAssembly](notification-groups/wasm.md) - [Windows](notification-groups/windows.md) - - [Rust for Linux](notification-groups/rust-for-linux.md) - [Licenses](./licenses.md) - [Editions](guides/editions.md) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md new file mode 100644 index 0000000000000..a4658e0d842f9 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md @@ -0,0 +1,12 @@ +# Fuchsia notification group + +**Github Label:** [O-fuchsia]
+**Ping command:** `@rustbot ping fuchsia` + +[O-fuchsia]: https://github.com/rust-lang/rust/labels/O-fuchsia + +This list will be used to notify [Fuchsia][fuchsia] maintainers +when the compiler or the standard library changes in a way that would +break the Fuchsia integration. + +[fuchsia]: ../tests/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/fuchsia.md index 926803368f087..2766c362cc266 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/fuchsia.md @@ -6,7 +6,7 @@ in the past and was subsequently included in CI. ## What to do if the Fuchsia job breaks? -Please contact the `fuchsia` ping group and ask them for help. +Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. ```text @rustbot ping fuchsia @@ -170,6 +170,7 @@ rustc book][platform-support]. [`public_configs`]: https://gn.googlesource.com/gn/+/main/docs/reference.md#var_public_configs [`//build/config:compiler`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=121;drc=c26c473bef93b33117ae417893118907a026fec7 [build system]: https://fuchsia.dev/fuchsia-src/development/build/build_system +[fuchsia-ping]: ../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust code and a roughly equal amount of third-party code, as counted by tokei From 4f053a9ee9f6816cad66c13b0777b22b0d8854bf Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 12:04:47 -0500 Subject: [PATCH 079/333] add new section on the `rustdoc` test suite --- .../src/rustdoc-internals/htmldocck.md | 101 ++++++++++++++++++ src/doc/rustc-dev-guide/src/rustdoc.md | 14 +-- .../rustc-dev-guide/src/tests/compiletest.md | 2 +- 3 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md new file mode 100644 index 0000000000000..d69627f46cc5c --- /dev/null +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -0,0 +1,101 @@ +# `rustdoc` tests + +This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). + +`htmldocck.py` is a custom checker script that uses [XPath] to verify the HTML output of rustdoc. + +[XPath]: https://en.wikipedia.org/wiki/XPath + +## Directives +Directives to htmldocck are similar to those given to `compiletest` in that they take the form of `//@` comments. + +All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), +so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. +To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. + +All arguments take the form of quoted strings, +with the exception of `COUNT` and the special `-` form of `PATH`. + +Directives are assertions that place constraints on the generated HTML. + +All directives (except `files`) can be negated by putting a `!` in front of their name. + +Similar to shell commands, +directives can extend across multiple lines if their last char is `\`. +In this case, the start of the next line should be `//`, with no `@`. + +For example, `//@ !has 'foo/struct.Bar.html'` checks that crate `foo` does not have a page for a struct named `Bar` in the crate root. + +### `has` + +Usage 1: `//@ has PATH` +Usage 2: `//@ has PATH XPATH PATTERN` + +In the first form, `has` checks that a given file exists. + +In the second form, `has` is an alias for `matches`, +except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `matches` + +Usage: `//@ matches PATH XPATH PATTERN` + +Checks that the text of each element selected by `XPATH` in `PATH` matches the python-flavored regex `PATTERN`. + +### `matchesraw` + +Usage: `//@ matchesraw PATH PATTERN` + +Checks that the contents of the file `PATH` matches the regex `PATTERN`. + +### `hasraw` + +Usage: `//@ hasraw PATH PATTERN` + +Same as `matchesraw`, except `PATTERN` is a whitespace-normalized[^1] string instead of a regex. + +### `count` + +Usage: `//@ count PATH XPATH COUNT` + +Checks that there are exactly `COUNT` matches for `XPATH` within the file `PATH`. + +### `snapshot` + +Usage: `//@ snapshot NAME PATH XPATH` + +Creates a snapshot test named NAME. +A snapshot test captures a subtree of the DOM, at the location +determined by the XPath, and compares it to a pre-recorded value +in a file. The file's name is the test's name with the `.rs` extension +replaced with `.NAME.html`, where NAME is the snapshot's name. + +htmldocck supports the `--bless` option to accept the current subtree +as expected, saving it to the file determined by the snapshot's name. +compiletest's `--bless` flag is forwarded to htmldocck. + +### `has-dir` + +Usage: `//@ has-dir PATH` + +Checks for the existance of directory `PATH`. + +### `files` + +Usage: `//@ files PATH ENTRIES` + +Checks that the directory `PATH` contains exactly `ENTRIES`. +`ENTRIES` is a python list of strings inside a quoted string, +as if it were to be parsed by `eval`. +(note that the list is actually parsed by `shlex.split`, +so it cannot contain arbitrary python expressions). + +Example: `//@ files "foo/bar" '["index.html", "sidebar-items.js"]'` + +[^1]: Whitespace normalization means that all spans of consecutive whitespace are replaced with a single space. The files themselves are also whitespace-normalized. + +## Limitations +All `XPATH` arguments must start with `//` due to a flaw in the implemention. + +Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). + diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 356698148e405..5ac62aa2c3768 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -77,27 +77,27 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) `doctest.rs`. * The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting doctests from a given block of Markdown. -* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, where - they're handled by the test runner of bootstrap and the supplementary script - `src/etc/htmldocck.py`. * Frontend CSS and JavaScript are stored in `html/static/`. ## Tests -* All paths in this section are relative to `tests` in the rust-lang/rust repository. -* Tests on search engine and index are located in `rustdoc-js` and `rustdoc-js-std`. +* Tests on search engine and index are located in `tests/rustdoc-js` and `tests/rustdoc-js-std`. The format is specified [in the search guide](rustdoc-internals/search.md#testing-the-search-engine). * Tests on the "UI" of rustdoc (the terminal output it produces when run) are in - `rustdoc-ui` + `tests/rustdoc-ui` * Tests on the "GUI" of rustdoc (the HTML, JS, and CSS as rendered in a browser) - are in `rustdoc-gui`. These use a [NodeJS tool called + are in `tests/rustdoc-gui`. These use a [NodeJS tool called browser-UI-test](https://github.com/GuillaumeGomez/browser-UI-test/) that uses puppeteer to run tests in a headless browser and check rendering and interactivity. * Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc] comments and an external d.ts file. The code itself is plain, valid JavaScript; we only use tsc as a linter. +* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, + where they're handled by the test runner of bootstrap and + the supplementary script `src/etc/htmldocck.py`. + [These tests have several extra directives available to them](./rustdoc-internals/htmldocck.md). [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 2c35381eadfb5..ee66b787bf1b2 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -78,7 +78,7 @@ The following test suites are available, with links for more information: ### Rustdoc test suites -See [Rustdoc tests](../rustdoc.md#tests) for more details. +See [Rustdoc § Tests](../rustdoc.md#tests) for more details. | Test suite | Purpose | |------------------|--------------------------------------------------------------------------| From 3668c366621043dce7dc9fddca19a60945526fae Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 12:10:43 -0500 Subject: [PATCH 080/333] add htmldocck.md to SUMMARY.md --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9e2d0774aab0b..fb468777409be 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - + - [`rustdoc` tests](./rustdoc-internals/htmldocck.md) # Source Code Representation - [Prologue](./part-3-intro.md) From a172f23df0b108d6d615d1433ae3de51afd292b6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:10:26 -0500 Subject: [PATCH 081/333] htmldocck: expand limitations and mention compiletest directives --- .../src/rustdoc-internals/htmldocck.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md index d69627f46cc5c..b37c1ac3de1b2 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -9,6 +9,10 @@ This page is specifically about the `rustdoc` test suite, for other test suites ## Directives Directives to htmldocck are similar to those given to `compiletest` in that they take the form of `//@` comments. +In addition to the directives listed here, +`rustdoc` tests also support most +[compiletest directives](../tests/directives.html). + All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. @@ -95,7 +99,9 @@ Example: `//@ files "foo/bar" '["index.html", "sidebar-items.js"]'` [^1]: Whitespace normalization means that all spans of consecutive whitespace are replaced with a single space. The files themselves are also whitespace-normalized. ## Limitations -All `XPATH` arguments must start with `//` due to a flaw in the implemention. - -Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). +`htmldocck.py` uses the xpath implementation from the standard library. +This leads to several limitations: +* All `XPATH` arguments must start with `//` due to a flaw in the implemention. +* Many XPath features (functions, axies, etc.) are not supported. +* Only well-formed HTML can be parsed (hopefully rustdoc doesn't output mismatched tags). From 6893f0ac7aaf2c02e48c6434f98febe58def1f95 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:19:33 -0500 Subject: [PATCH 082/333] rustdoc test suite: clean up wording and intro --- .../rustc-dev-guide/src/rustdoc-internals/htmldocck.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md index b37c1ac3de1b2..97c40c8a8202a 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md @@ -1,8 +1,10 @@ -# `rustdoc` tests +# the `rustdoc` test suite This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). -`htmldocck.py` is a custom checker script that uses [XPath] to verify the HTML output of rustdoc. +The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. + +This is achived by means of `htmldocck.py`, a custom checker script that leverages [XPath]. [XPath]: https://en.wikipedia.org/wiki/XPath @@ -14,7 +16,8 @@ In addition to the directives listed here, [compiletest directives](../tests/directives.html). All `PATH`s in directives are relative to the the rustdoc output directory (`build/TARGET/test/rustdoc/TESTNAME`), -so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid writing paths. +so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid +having to write a long crate name multiple times. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. All arguments take the form of quoted strings, From 1081d98cf679560b02f6db4b2d72bb3103b92073 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:21:15 -0500 Subject: [PATCH 083/333] rename htmldocck.md -> rustdoc-test-suite.md --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../rustdoc-internals/{htmldocck.md => rustdoc-test-suite.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/doc/rustc-dev-guide/src/rustdoc-internals/{htmldocck.md => rustdoc-test-suite.md} (100%) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index fb468777409be..8ea5e86cd63a6 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - - [`rustdoc` tests](./rustdoc-internals/htmldocck.md) + - [the `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) # Source Code Representation - [Prologue](./part-3-intro.md) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md similarity index 100% rename from src/doc/rustc-dev-guide/src/rustdoc-internals/htmldocck.md rename to src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md From 40b9be0c456d32cf01441ec1c96fec1523d4737f Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:23:37 -0500 Subject: [PATCH 084/333] clean up wording/grammar and mention double quotes --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../src/rustdoc-internals/rustdoc-test-suite.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 8ea5e86cd63a6..075d5af4c24a5 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -95,7 +95,7 @@ - [Parallel Compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - - [the `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) + - [The `rustdoc` test suite](./rustdoc-internals/rustdoc-test-suite.md) # Source Code Representation - [Prologue](./part-3-intro.md) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index 97c40c8a8202a..fb4be51c278a9 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,6 @@ -# the `rustdoc` test suite +# The `rustdoc` test suite -This page is specifically about the `rustdoc` test suite, for other test suites used for testing rustdoc, see [Rustdoc § Tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc Tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. @@ -20,7 +20,8 @@ so it is conventional to use a `#![crate_name = "foo"]` attribute to avoid having to write a long crate name multiple times. To avoid repetion, `-` can be used in any `PATH` argument to re-use the previous `PATH` argument. -All arguments take the form of quoted strings, +All arguments take the form of quoted strings +(both single and double quotes are supported), with the exception of `COUNT` and the special `-` form of `PATH`. Directives are assertions that place constraints on the generated HTML. From 7f29b47410d62cc1d81c0105add357552a0f1c99 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:25:39 -0500 Subject: [PATCH 085/333] normalize link titles --- .../rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md | 2 +- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index fb4be51c278a9..c2a2e6495f82c 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,6 @@ # The `rustdoc` test suite -This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc Tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index ee66b787bf1b2..2c35381eadfb5 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -78,7 +78,7 @@ The following test suites are available, with links for more information: ### Rustdoc test suites -See [Rustdoc § Tests](../rustdoc.md#tests) for more details. +See [Rustdoc tests](../rustdoc.md#tests) for more details. | Test suite | Purpose | |------------------|--------------------------------------------------------------------------| From eeda54f1102d514a9f73c2d5ed92e75b2edfe94e Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 18 Mar 2025 13:29:14 -0500 Subject: [PATCH 086/333] update filename in link --- src/doc/rustc-dev-guide/src/rustdoc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 5ac62aa2c3768..320dc9d582584 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -97,7 +97,7 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) * The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`, where they're handled by the test runner of bootstrap and the supplementary script `src/etc/htmldocck.py`. - [These tests have several extra directives available to them](./rustdoc-internals/htmldocck.md). + [These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md). [TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html From bf374475c87f23690a0228ec945b48908786ff38 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 19 Mar 2025 14:43:51 +0800 Subject: [PATCH 087/333] Reject `{true,false}` as revision names Because they would imply `--cfg={true,false}` otherwise, and the test writer has to use `cfg(r#true)` and `cfg(r#false)` in the test. --- src/tools/compiletest/src/header.rs | 36 ++++++++++++++++++----- src/tools/compiletest/src/header/tests.rs | 7 +++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 7675e13990d6c..fb2b90d74bdae 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -924,7 +924,14 @@ fn iter_header( impl Config { fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec) { - const FORBIDDEN_REVISION_NAMES: [&str; 9] = + const FORBIDDEN_REVISION_NAMES: [&str; 2] = [ + // `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very + // weird for the test, since if the test writer wants a cfg of the same revision name + // they'd have to use `cfg(r#true)` and `cfg(r#false)`. + "true", "false", + ]; + + const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] = ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"]; if let Some(raw) = self.parse_name_value_directive(line, "revisions") { @@ -933,25 +940,38 @@ impl Config { } let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); - for revision in raw.split_whitespace().map(|r| r.to_string()) { - if !duplicates.insert(revision.clone()) { + for revision in raw.split_whitespace() { + if !duplicates.insert(revision.to_string()) { panic!( "duplicate revision: `{}` in line `{}`: {}", revision, raw, testfile.display() ); - } else if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt) - && FORBIDDEN_REVISION_NAMES.contains(&revision.as_str()) + } + + if FORBIDDEN_REVISION_NAMES.contains(&revision) { + panic!( + "revision name `{revision}` is not permitted: `{}` in line `{}`: {}", + revision, + raw, + testfile.display() + ); + } + + if matches!(self.mode, Mode::Assembly | Mode::Codegen | Mode::MirOpt) + && FILECHECK_FORBIDDEN_REVISION_NAMES.contains(&revision) { panic!( - "revision name `{revision}` is not permitted in a test suite that uses `FileCheck` annotations\n\ - as it is confusing when used as custom `FileCheck` prefix: `{revision}` in line `{}`: {}", + "revision name `{revision}` is not permitted in a test suite that uses \ + `FileCheck` annotations as it is confusing when used as custom `FileCheck` \ + prefix: `{revision}` in line `{}`: {}", raw, testfile.display() ); } - existing.push(revision); + + existing.push(revision.to_string()); } } } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 007318be7cc39..4d90f152ee204 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -567,6 +567,13 @@ fn test_assembly_mode_forbidden_revisions() { parse_rs(&config, "//@ revisions: CHECK"); } +#[test] +#[should_panic(expected = "revision name `true` is not permitted")] +fn test_forbidden_revisions() { + let config = cfg().mode("ui").build(); + parse_rs(&config, "//@ revisions: true"); +} + #[test] #[should_panic( expected = "revision name `CHECK` is not permitted in a test suite that uses `FileCheck` annotations" From 88478aca86706a7b2cc1db4c27add28ee374d376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 19 Mar 2025 09:36:05 +0100 Subject: [PATCH 088/333] Set linkcheck in `ci.yml` --- src/doc/rustc-dev-guide/.github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 22a4fb1901ab8..415d0dc397dc9 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: MDBOOK_LINKCHECK2_VERSION: 0.9.1 MDBOOK_MERMAID_VERSION: 0.12.6 MDBOOK_TOC_VERSION: 0.11.2 + MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} DEPLOY_DIR: book/html BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 2daaf493815e8b4bfa9862559cecf6f0f2383314 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 19 Mar 2025 18:06:50 +0200 Subject: [PATCH 089/333] use correct code block markers This makes this command pass mdbook test --chapter "Remarks on perma-unstable features" --- .../src/rustc-driver/remarks-on-perma-unstable-features.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md index c307adc00a006..b434cfc9cf146 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/remarks-on-perma-unstable-features.md @@ -1,4 +1,3 @@ - # Remarks on perma unstable features ## `rustc_private` @@ -18,7 +17,7 @@ When using the `rustc_private` feature with official Rust toolchains distributed Install both components using rustup: -```bash +```text rustup component add rustc-dev llvm-tools ``` @@ -26,7 +25,7 @@ rustup component add rustc-dev llvm-tools Without the `llvm-tools` component, you'll encounter linking errors like: -``` +```text error: linking with `cc` failed: exit status: 1 | = note: rust-lld: error: unable to find library -lLLVM-{version} @@ -45,7 +44,7 @@ For custom-built toolchains or environments not using rustup, additional configu 1. **Check LLVM installation**: Verify LLVM is installed and accessible 2. **Configure library paths**: You may need to set environment variables: - ```bash + ```text export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH ``` 3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain From 55add8fce38ab100e161d2530a134f645ba78802 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 20 Mar 2025 19:47:57 +0900 Subject: [PATCH 090/333] rustc_target: Add more RISC-V vector-related features --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 ++- compiler/rustc_target/src/target_features.rs | 38 +++++++++++++++++++- tests/ui/check-cfg/target_feature.stderr | 38 +++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 4a166b0872dfd..5bf931965c703 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -274,7 +274,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("fullfp16")), // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single // feature called `fast-unaligned-access`. In LLVM 19, it was split back out. - ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { + ("riscv32" | "riscv64", "unaligned-scalar-mem" | "unaligned-vector-mem") + if get_version().0 == 18 => + { Some(LLVMFeature::new("fast-unaligned-access")) } // Filter out features that are not supported by the current LLVM version diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index a96caf227f747..e1865c624c4d3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -497,7 +497,8 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("m", Stable, &[]), ("relax", Unstable(sym::riscv_target_feature), &[]), ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]), - ("v", Unstable(sym::riscv_target_feature), &[]), + ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]), + ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]), ("za128rs", Unstable(sym::riscv_target_feature), &[]), ("za64rs", Unstable(sym::riscv_target_feature), &[]), ("zaamo", Unstable(sym::riscv_target_feature), &[]), @@ -529,6 +530,41 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("zksed", Stable, &[]), ("zksh", Stable, &[]), ("zkt", Stable, &[]), + ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), + ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]), + ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]), + ("zve32x", Unstable(sym::riscv_target_feature), &["zvl32b"]), + ("zve64d", Unstable(sym::riscv_target_feature), &["zve64f", "d"]), + ("zve64f", Unstable(sym::riscv_target_feature), &["zve32f", "zve64x"]), + ("zve64x", Unstable(sym::riscv_target_feature), &["zve32x", "zvl64b"]), + ("zvfh", Unstable(sym::riscv_target_feature), &["zvfhmin", "zfhmin"]), + ("zvfhmin", Unstable(sym::riscv_target_feature), &["zve32f"]), + ("zvkb", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkg", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkn", Unstable(sym::riscv_target_feature), &["zvkned", "zvknhb", "zvkb", "zvkt"]), + ("zvknc", Unstable(sym::riscv_target_feature), &["zvkn", "zvbc"]), + ("zvkned", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkng", Unstable(sym::riscv_target_feature), &["zvkn", "zvkg"]), + ("zvknha", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvknhb", Unstable(sym::riscv_target_feature), &["zve64x"]), + ("zvks", Unstable(sym::riscv_target_feature), &["zvksed", "zvksh", "zvkb", "zvkt"]), + ("zvksc", Unstable(sym::riscv_target_feature), &["zvks", "zvbc"]), + ("zvksed", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvksg", Unstable(sym::riscv_target_feature), &["zvks", "zvkg"]), + ("zvksh", Unstable(sym::riscv_target_feature), &["zve32x"]), + ("zvkt", Unstable(sym::riscv_target_feature), &[]), + ("zvl1024b", Unstable(sym::riscv_target_feature), &["zvl512b"]), + ("zvl128b", Unstable(sym::riscv_target_feature), &["zvl64b"]), + ("zvl16384b", Unstable(sym::riscv_target_feature), &["zvl8192b"]), + ("zvl2048b", Unstable(sym::riscv_target_feature), &["zvl1024b"]), + ("zvl256b", Unstable(sym::riscv_target_feature), &["zvl128b"]), + ("zvl32768b", Unstable(sym::riscv_target_feature), &["zvl16384b"]), + ("zvl32b", Unstable(sym::riscv_target_feature), &[]), + ("zvl4096b", Unstable(sym::riscv_target_feature), &["zvl2048b"]), + ("zvl512b", Unstable(sym::riscv_target_feature), &["zvl256b"]), + ("zvl64b", Unstable(sym::riscv_target_feature), &["zvl32b"]), + ("zvl65536b", Unstable(sym::riscv_target_feature), &["zvl32768b"]), + ("zvl8192b", Unstable(sym::riscv_target_feature), &["zvl4096b"]), // tidy-alphabetical-end ]; diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index a9d67481ba15b..e23984dc59584 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -245,6 +245,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `trustzone` `ual` `unaligned-scalar-mem` +`unaligned-vector-mem` `v` `v5te` `v6` @@ -325,7 +326,42 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zkr` `zks` `zksed` -`zksh`, and `zkt` +`zksh` +`zkt` +`zvbb` +`zvbc` +`zve32f` +`zve32x` +`zve64d` +`zve64f` +`zve64x` +`zvfh` +`zvfhmin` +`zvkb` +`zvkg` +`zvkn` +`zvknc` +`zvkned` +`zvkng` +`zvknha` +`zvknhb` +`zvks` +`zvksc` +`zvksed` +`zvksg` +`zvksh` +`zvkt` +`zvl1024b` +`zvl128b` +`zvl16384b` +`zvl2048b` +`zvl256b` +`zvl32768b` +`zvl32b` +`zvl4096b` +`zvl512b` +`zvl64b` +`zvl65536b`, and `zvl8192b` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default From 8a6f96a4a08df2bbb73ffbb7afb9b94f137bd24b Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 20 Mar 2025 19:48:02 +0900 Subject: [PATCH 091/333] rustc_target: Use zvl*b target features in vector ABI check --- compiler/rustc_target/src/target_features.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index e1865c624c4d3..0e6523f0880e8 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -740,8 +740,20 @@ const ARM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(1 const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")]; const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")]; const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")]; -const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = - &[/*(64, "zvl64b"), */ (128, "v")]; +const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[ + (32, "zvl32b"), + (64, "zvl64b"), + (128, "zvl128b"), + (256, "zvl256b"), + (512, "zvl512b"), + (1024, "zvl1024b"), + (2048, "zvl2048b"), + (4096, "zvl4096b"), + (8192, "zvl8192b"), + (16384, "zvl16384b"), + (32768, "zvl32768b"), + (65536, "zvl65536b"), +]; // Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment. const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/]; From b9e67a2e286e17d3dd5d88ff9dadb98641a6b21b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:50:13 +0000 Subject: [PATCH 092/333] Enable target features in inline asm on arm64 --- src/inline_asm.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 59d109341311e..fbc33a642853c 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -612,6 +612,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(".att_syntax\n"); } + if self.arch == InlineAsmArch::AArch64 { + for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features { + if feature.name == sym::neon { + continue; + } + writeln!(generated_asm, ".arch_extension {}", feature.name).unwrap(); + } + } + // The actual inline asm for piece in self.template { match piece { @@ -679,6 +688,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { } generated_asm.push('\n'); + if self.arch == InlineAsmArch::AArch64 { + for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features { + if feature.name == sym::neon { + continue; + } + writeln!(generated_asm, ".arch_extension no{}", feature.name).unwrap(); + } + } + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { generated_asm.push_str(".intel_syntax noprefix\n"); } From 8fb99bcb1011a76d07ad124692c6e007034fc855 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:54:08 +0000 Subject: [PATCH 093/333] Fix implementation of vaddlvq_u8 --- src/intrinsics/llvm_aarch64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index b77c99fa2896d..aa5d268e251cf 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -253,7 +253,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } let res = CValue::by_val( fx.bcx.ins().uextend(types::I32, res_val), - fx.layout_of(fx.tcx.types.u32), + fx.layout_of(fx.tcx.types.i32), ); ret.write_cvalue(fx, res); } From ce57133ad170cb069a06f2595d84d3be2e478a86 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:59:01 +0000 Subject: [PATCH 094/333] Update LLVM intrinsic name This got updated in rust-lang/stdarch@13219b5 --- src/intrinsics/llvm_aarch64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index aa5d268e251cf..387c87d123a39 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -21,7 +21,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx.bcx.ins().fence(); } - "llvm.aarch64.neon.ld1x4.v16i8.p0i8" => { + "llvm.aarch64.neon.ld1x4.v16i8.p0" => { intrinsic_args!(fx, args => (ptr); intrinsic); let ptr = ptr.load_scalar(fx); From a8311b4a46f6dcb08a7802397acac548a8ada0ed Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:08:02 +0000 Subject: [PATCH 095/333] Temporarily disable FreeBSD testing --- .cirrus.yml | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 1ec99eb3d17a5..ee5de8b42f465 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,20 +1,21 @@ -task: - name: freebsd - freebsd_instance: - image: freebsd-13-2-release-amd64 - setup_rust_script: - - pkg install -y git-tiny binutils - - curl https://sh.rustup.rs -sSf --output rustup.sh - - sh rustup.sh --default-toolchain none -y --profile=minimal - target_cache: - folder: build/cg_clif - prepare_script: - - . $HOME/.cargo/env - - ./y.sh prepare - test_script: - - . $HOME/.cargo/env - # Disabling incr comp reduces cache size and incr comp doesn't save as much - # on CI anyway. - - export CARGO_BUILD_INCREMENTAL=false - # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 - - ./y.sh test --skip-test test.rust-random/rand +# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed. +# task: +# name: freebsd +# freebsd_instance: +# image: freebsd-13-2-release-amd64 +# setup_rust_script: +# - pkg install -y git-tiny binutils +# - curl https://sh.rustup.rs -sSf --output rustup.sh +# - sh rustup.sh --default-toolchain none -y --profile=minimal +# target_cache: +# folder: build/cg_clif +# prepare_script: +# - . $HOME/.cargo/env +# - ./y.sh prepare +# test_script: +# - . $HOME/.cargo/env +# # Disabling incr comp reduces cache size and incr comp doesn't save as much +# # on CI anyway. +# - export CARGO_BUILD_INCREMENTAL=false +# # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 +# - ./y.sh test --skip-test test.rust-random/rand From 15fff5d2d28c78f6590582f857deaf72e21c1142 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 5 Mar 2025 09:54:13 +0000 Subject: [PATCH 096/333] Update to Cranelift 0.118 --- Cargo.lock | 64 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 24 ++++++++++---------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 011e291cd2032..e5f1896b9230b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,39 +43,39 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-assembler-x64" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b83fcf2fc1c8954561490d02079b496fd0c757da88129981e15bfe3a548229" +checksum = "3e4b56ebe316895d3fa37775d0a87b0c889cc933f5c8b253dbcc7c7bcb7fe7e4" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7496a6e92b5cee48c5d772b0443df58816dee30fed6ba19b2a28e78037ecedf" +checksum = "95cabbc01dfbd7dcd6c329ca44f0212910309c221797ac736a67a5bc8857fe1b" [[package]] name = "cranelift-bforest" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73a9dc0a8d3d49ee772101924968830f1c1937d650c571d3c2dd69dc36a68f41" +checksum = "76ffe46df300a45f1dc6f609dc808ce963f0e3a2e971682c479a2d13e3b9b8ef" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573c641174c40ef31021ae4a5a3ad78974e280633502d0dfc6e362385e0c100f" +checksum = "b265bed7c51e1921fdae6419791d31af77d33662ee56d7b0fa0704dc8d231cab" [[package]] name = "cranelift-codegen" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d7c94d572615156f2db682181cadbd96342892c31e08cc26a757344319a9220" +checksum = "e606230a7e3a6897d603761baee0d19f88d077f17b996bb5089488a29ae96e41" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beecd9fcf2c3e06da436d565de61a42676097ea6eb6b4499346ac6264b6bb9ce" +checksum = "8a63bffafc23bc60969ad528e138788495999d935f0adcfd6543cb151ca8637d" dependencies = [ "cranelift-assembler-x64", "cranelift-codegen-shared", @@ -108,33 +108,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4ff8d2e1235f2d6e7fc3c6738be6954ba972cd295f09079ebffeca2f864e22" +checksum = "af50281b67324b58e843170a6a5943cf6d387c06f7eeacc9f5696e4ab7ae7d7e" [[package]] name = "cranelift-control" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "001312e9fbc7d9ca9517474d6fe71e29d07e52997fd7efe18f19e8836446ceb2" +checksum = "8c20c1b38d1abfbcebb0032e497e71156c0e3b8dcb3f0a92b9863b7bcaec290c" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb0fd6d4aae680275fcbceb08683416b744e65c8b607352043d3f0951d72b3b2" +checksum = "0c2c67d95507c51b4a1ff3f3555fe4bfec36b9e13c1b684ccc602736f5d5f4a2" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd44e7e5dcea20ca104d45894748205c51365ce4cdb18f4418e3ba955971d1b" +checksum = "4e002691cc69c38b54fc7ec93e5be5b744f627d027031d991cc845d1d512d0ce" dependencies = [ "cranelift-codegen", "log", @@ -144,15 +144,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f900e0a3847d51eed0321f0777947fb852ccfce0da7fb070100357f69a2f37fc" +checksum = "e93588ed1796cbcb0e2ad160403509e2c5d330d80dd6e0014ac6774c7ebac496" [[package]] name = "cranelift-jit" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e37088dec72b7819f980558faaba9215d248fec4a2c3b89357b474f9e46f21" +checksum = "17f6682f0b193d6b7873cc8e7ed67e8776a8a26f50eeabf88534e9be618b9a03" dependencies = [ "anyhow", "cranelift-codegen", @@ -170,9 +170,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c3d728819ff644e8613d808378cbfed54fef464790f32e62079e638639eeff" +checksum = "ff19784c6de05116e63e6a34791012bd927b2a4eac56233039c46f1b6a4edac8" dependencies = [ "anyhow", "cranelift-codegen", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7617f13f392ebb63c5126258aca8b8eca739636ca7e4eeee301d3eff68489a6a" +checksum = "e5b09bdd6407bf5d89661b80cf926ce731c9e8cc184bf49102267a2369a8358e" dependencies = [ "cranelift-codegen", "libc", @@ -192,9 +192,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.117.2" +version = "0.118.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60fc9092f7d9bba17c96ce51de5d91461f7905f3e1c43d1ba965df4b884d16ce" +checksum = "685e8661a30d1cb69509f589ac643adeee79c5f63c0da316431b9fad29e6d3b4" dependencies = [ "anyhow", "cranelift-codegen", @@ -436,9 +436,9 @@ checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "wasmtime-jit-icache-coherence" -version = "30.0.2" +version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f180cc0d2745e3a5df5d02231cd3046f49c75512eaa987b8202363b112e125d" +checksum = "a54f6c6c7e9d7eeee32dfcc10db7f29d505ee7dd28d00593ea241d5f70698e64" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index fa3037e77a0cc..08b60de14c1f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.117.2", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.117.2" } -cranelift-module = { version = "0.117.2" } -cranelift-native = { version = "0.117.2" } -cranelift-jit = { version = "0.117.2", optional = true } -cranelift-object = { version = "0.117.2" } +cranelift-codegen = { version = "0.118.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.118.0" } +cranelift-module = { version = "0.118.0" } +cranelift-native = { version = "0.118.0" } +cranelift-jit = { version = "0.118.0", optional = true } +cranelift-object = { version = "0.118.0" } target-lexicon = "0.13" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } @@ -24,12 +24,12 @@ smallvec = "1.8.1" [patch.crates-io] # Uncomment to use an unreleased version of cranelift -#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } -#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } -#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } -#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } -#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } -#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-30.0.0", version = "0.117.0" } +#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } +#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-31.0.0", version = "0.118.0" } # Uncomment to use local checkout of cranelift #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } From 2133fb94b76bdf5b095e8b011a2df4e787afbbcd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:02:29 +0000 Subject: [PATCH 097/333] Disable PIC when jitting This fixes jitting on non-x86_64 targets. --- build_system/tests.rs | 6 ++---- src/driver/aot.rs | 2 +- src/driver/jit.rs | 2 +- src/lib.rs | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 36e108726121b..122b541fa35f8 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -325,10 +325,8 @@ impl<'a> TestRunner<'a> { target_compiler.rustflags.extend(rustflags_from_env("RUSTFLAGS")); target_compiler.rustdocflags.extend(rustflags_from_env("RUSTDOCFLAGS")); - let jit_supported = use_unstable_features - && is_native - && target_compiler.triple.contains("x86_64") - && !target_compiler.triple.contains("windows"); + let jit_supported = + use_unstable_features && is_native && !target_compiler.triple.contains("windows"); Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source } } diff --git a/src/driver/aot.rs b/src/driver/aot.rs index a52b18573b152..57c01f87b86ca 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -329,7 +329,7 @@ fn produce_final_output_artifacts( } fn make_module(sess: &Session, name: String) -> UnwindModule { - let isa = crate::build_isa(sess); + let isa = crate::build_isa(sess, false); let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 4a08937f4aa94..41f8bb9161ca2 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -18,7 +18,7 @@ use crate::unwind_module::UnwindModule; fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); - let isa = crate::build_isa(tcx.sess); + let isa = crate::build_isa(tcx.sess, true); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info)); diff --git a/src/lib.rs b/src/lib.rs index caaa06967ed8a..1e18c53b99c5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,13 +250,13 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple { } } -fn build_isa(sess: &Session) -> Arc { +fn build_isa(sess: &Session, jit: bool) -> Arc { use target_lexicon::BinaryFormat; let target_triple = crate::target_triple(sess); let mut flags_builder = settings::builder(); - flags_builder.enable("is_pic").unwrap(); + flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap(); let enable_verifier = if enable_verifier(sess) { "true" } else { "false" }; flags_builder.set("enable_verifier", enable_verifier).unwrap(); flags_builder.set("regalloc_checker", enable_verifier).unwrap(); From f90f43d62b1ce6d4c3dc49b450a7e30b9172ef42 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Mar 2025 15:46:19 +0000 Subject: [PATCH 098/333] Fix diagnostic struct typo, make sure is_array_like_block checks that it's a block --- compiler/rustc_parse/src/errors.rs | 6 ++--- compiler/rustc_parse/src/parser/expr.rs | 8 ++++--- tests/ui/parser/closure-return-syntax.rs | 16 ++++++++++++- tests/ui/parser/closure-return-syntax.stderr | 24 +++++++++++++++++++- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e090d9cf7600e..eb3bbef350a22 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -810,16 +810,16 @@ pub(crate) enum WrapInParentheses { #[derive(Diagnostic)] #[diag(parse_array_brackets_instead_of_braces)] -pub(crate) struct ArrayBracketsInsteadOfSpaces { +pub(crate) struct ArrayBracketsInsteadOfBraces { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: ArrayBracketsInsteadOfSpacesSugg, + pub sub: ArrayBracketsInsteadOfBracesSugg, } #[derive(Subdiagnostic)] #[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")] -pub(crate) struct ArrayBracketsInsteadOfSpacesSugg { +pub(crate) struct ArrayBracketsInsteadOfBracesSugg { #[suggestion_part(code = "[")] pub left: Span, #[suggestion_part(code = "]")] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd931888fbaa1..1e14446efb513 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2190,7 +2190,9 @@ impl<'a> Parser<'a> { } fn is_array_like_block(&mut self) -> bool { - self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) + matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace)) + && self + .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) && self.look_ahead(2, |t| t == &token::Comma) && self.look_ahead(3, |t| t.can_begin_expr()) } @@ -2202,9 +2204,9 @@ impl<'a> Parser<'a> { let mut snapshot = self.create_snapshot_for_diagnostic(); match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { Ok(arr) => { - let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfSpaces { + let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces { span: arr.span, - sub: errors::ArrayBracketsInsteadOfSpacesSugg { + sub: errors::ArrayBracketsInsteadOfBracesSugg { left: lo, right: snapshot.prev_token.span, }, diff --git a/tests/ui/parser/closure-return-syntax.rs b/tests/ui/parser/closure-return-syntax.rs index c6a08abeff4ba..6865d8c5393d4 100644 --- a/tests/ui/parser/closure-return-syntax.rs +++ b/tests/ui/parser/closure-return-syntax.rs @@ -1,7 +1,21 @@ // Test that we cannot parse a closure with an explicit return type // unless it uses braces. -fn main() { +fn needs_braces_1() { let x = || -> i32 22; //~^ ERROR expected `{`, found `22` } + +// Check other delimiters too. + +fn needs_braces_2() { + let x = || -> (i32, i32) (1, 2); + //~^ ERROR expected `{`, found `(` +} + +fn needs_braces_3() { + let c = || -> [i32; 2] [1, 2]; + //~^ ERROR expected `{`, found `[` +} + +fn main() {} diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr index aacc31ed871d3..6f2106b77adbb 100644 --- a/tests/ui/parser/closure-return-syntax.stderr +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -9,5 +9,27 @@ help: you might have meant to write this as part of a block LL | let x = || -> i32 { 22 }; | + + -error: aborting due to 1 previous error +error: expected `{`, found `(` + --> $DIR/closure-return-syntax.rs:12:34 + | +LL | let x = || -> (i32, i32) (1, 2); + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | let x = || -> (i32, i32) { (1, 2) }; + | + + + +error: expected `{`, found `[` + --> $DIR/closure-return-syntax.rs:17:32 + | +LL | let c = || -> [i32; 2] [1, 2]; + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | let c = || -> [i32; 2] { [1, 2] }; + | + + + +error: aborting due to 3 previous errors From dbda7d44b8c6fcb737f790986a4884f4bbd6b126 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Mar 2025 15:44:44 +0000 Subject: [PATCH 099/333] Make dedicated recovery for missing braces on closure with return --- compiler/rustc_parse/src/parser/expr.rs | 53 +++++++++++++++++--- tests/ui/parser/closure-return-syntax.stderr | 18 ++++--- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1e14446efb513..1efde7fc54b79 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2329,7 +2329,8 @@ impl<'a> Parser<'a> { let capture_clause = self.parse_capture_clause()?; let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?; let decl_hi = self.prev_token.span; - let mut body = match fn_decl.output { + let mut body = match &fn_decl.output { + // No return type. FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET; @@ -2341,11 +2342,8 @@ impl<'a> Parser<'a> { Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?, } } - _ => { - // If an explicit return type is given, require a block to appear (RFC 968). - let body_lo = self.token.span; - self.parse_expr_block(None, body_lo, BlockCheckMode::Default)? - } + // Explicit return type (`->`) needs block `-> T { }`. + FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?, }; match coroutine_kind { @@ -2397,6 +2395,49 @@ impl<'a> Parser<'a> { Ok(closure) } + /// If an explicit return type is given, require a block to appear (RFC 968). + fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P> { + if self.may_recover() + && self.token.can_begin_expr() + && !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace)) + && !self.token.is_whole_block() + { + let snapshot = self.create_snapshot_for_diagnostic(); + let restrictions = + self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET; + let tok = self.token.clone(); + match self.parse_expr_res(restrictions, AttrWrapper::empty()) { + Ok((expr, _)) => { + let descr = super::token_descr(&tok); + let mut diag = self + .dcx() + .struct_span_err(tok.span, format!("expected `{{`, found {descr}")); + diag.span_label( + ret_span, + "explicit return type requires closure body to be enclosed in braces", + ); + diag.multipart_suggestion_verbose( + "wrap the expression in curly braces", + vec![ + (expr.span.shrink_to_lo(), "{ ".to_string()), + (expr.span.shrink_to_hi(), " }".to_string()), + ], + Applicability::MachineApplicable, + ); + diag.emit(); + return Ok(expr); + } + Err(diag) => { + diag.cancel(); + self.restore_snapshot(snapshot); + } + } + } + + let body_lo = self.token.span; + self.parse_expr_block(None, body_lo, BlockCheckMode::Default) + } + /// Parses an optional `move` or `use` prefix to a closure-like construct. fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> { if self.eat_keyword(exp!(Move)) { diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr index 6f2106b77adbb..763f19ccc6454 100644 --- a/tests/ui/parser/closure-return-syntax.stderr +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -2,9 +2,11 @@ error: expected `{`, found `22` --> $DIR/closure-return-syntax.rs:5:23 | LL | let x = || -> i32 22; - | ^^ expected `{` + | --- ^^ + | | + | explicit return type requires closure body to be enclosed in braces | -help: you might have meant to write this as part of a block +help: wrap the expression in curly braces | LL | let x = || -> i32 { 22 }; | + + @@ -13,9 +15,11 @@ error: expected `{`, found `(` --> $DIR/closure-return-syntax.rs:12:34 | LL | let x = || -> (i32, i32) (1, 2); - | ^ expected `{` + | ---------- ^ + | | + | explicit return type requires closure body to be enclosed in braces | -help: you might have meant to write this as part of a block +help: wrap the expression in curly braces | LL | let x = || -> (i32, i32) { (1, 2) }; | + + @@ -24,9 +28,11 @@ error: expected `{`, found `[` --> $DIR/closure-return-syntax.rs:17:32 | LL | let c = || -> [i32; 2] [1, 2]; - | ^ expected `{` + | -------- ^ + | | + | explicit return type requires closure body to be enclosed in braces | -help: you might have meant to write this as part of a block +help: wrap the expression in curly braces | LL | let c = || -> [i32; 2] { [1, 2] }; | + + From 2de68a1bb180923c753e8d53d5ae913b751b860f Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 20 Mar 2025 17:30:18 +0000 Subject: [PATCH 100/333] Update `ParamEnv` section for `TypingEnv` changes --- src/doc/rustc-dev-guide/src/SUMMARY.md | 5 +- .../src/appendix/code-index.md | 2 +- src/doc/rustc-dev-guide/src/const-eval.md | 2 +- .../src/param_env/param_env_acquisition.md | 43 ---- .../param_env_construction_internals.md | 83 ------- .../src/param_env/param_env_summary.md | 18 -- .../src/param_env/param_env_what_is_it.md | 59 ----- src/doc/rustc-dev-guide/src/traits/caching.md | 2 +- .../rustc-dev-guide/src/traits/resolution.md | 2 +- .../src/typing_parameter_envs.md | 206 ++++++++++++++++++ 10 files changed, 211 insertions(+), 211 deletions(-) delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_summary.md delete mode 100644 src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md create mode 100644 src/doc/rustc-dev-guide/src/typing_parameter_envs.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 075d5af4c24a5..c5d046015d884 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -146,10 +146,7 @@ - [ADTs and Generic Arguments](./ty_module/generic_arguments.md) - [Parameter types/consts/regions](./ty_module/param_ty_const_regions.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) -- [Parameter Environments](./param_env/param_env_summary.md) - - [What is it?](./param_env/param_env_what_is_it.md) - - [How are `ParamEnv`'s constructed internally](./param_env/param_env_construction_internals.md) - - [Which `ParamEnv` do I use?](./param_env/param_env_acquisition.md) +- [Typing/Param Envs](./typing_parameter_envs.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index b96ede68eab51..65fbf752d7921 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -40,5 +40,5 @@ Item | Kind | Short description | Chapter | [Emitting Diagnostics]: ../diagnostics.html [Macro expansion]: ../macro-expansion.html [Name resolution]: ../name-resolution.html -[Parameter Environment]: ../param_env/param_env_summary.html +[Parameter Environment]: ../typing_parameter_envs.html [Trait Solving: Goals and Clauses]: ../traits/goals-and-clauses.html#domain-goals diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md index 69329a3e08511..ca6a35a5e97eb 100644 --- a/src/doc/rustc-dev-guide/src/const-eval.md +++ b/src/doc/rustc-dev-guide/src/const-eval.md @@ -35,7 +35,7 @@ They're the wrappers of the `const_eval` query. Statics are special; all other functions do not represent statics correctly and have thus assertions preventing their use on statics. -The `const_eval_*` functions use a [`ParamEnv`](./param_env/param_env_summary.html) of environment +The `const_eval_*` functions use a [`ParamEnv`](./typing_parameter_envs.html) of environment in which the constant is evaluated (e.g. the function within which the constant is used) and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant or static or of an `Instance` of a function and an index into the function's `Promoted` table. diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md b/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md deleted file mode 100644 index f6cff2d6c63cc..0000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_acquisition.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Which `ParamEnv` do I use? - -When needing a [`ParamEnv`][pe] in the compiler there are a few options for obtaining one: -- The correct env is already in scope simply use it (or pass it down the call stack to where you are). -- The [`tcx.param_env(def_id)` query][param_env_query] -- Use [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then call [`traits::normalize_param_env_or_error`][normalize_env_or_error] which will handle normalizing and elaborating all the where clauses in the env for you. -- Creating an empty environment via [`ParamEnv::reveal_all`][env_reveal_all] or [`ParamEnv::empty`][env_empty] - -In the large majority of cases a `ParamEnv` when required already exists somewhere in scope or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: -- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] -- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] -- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] -- The `TypeChecker` used by Mir Typeck has a [`param_env` field][mirtypeck_param_env] -- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in -- When editing an existing [`TypeRelation`][typerelation] if it implements `PredicateEmittingRelation` then a [`param_env` method][typerelation_param_env] will be available. - -Using the `param_env` query to obtain an env is generally done at the start of some kind of analysis and then passed everywhere that a `ParamEnv` is required. For example the type checker will create a `ParamEnv` for the item it is type checking and then pass it around everywhere. - -Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (i.e. [`compare_method_predicate_entailment`][method_pred_entailment] as mentioned earlier). - -Creating an empty environment via `ParamEnv::empty` is almost always wrong. There are very few places where we actually know that the environment should be empty. One of the only places where we do actually know this is after monomorphization, however the `ParamEnv` there should be constructed via `ParamEnv::reveal_all` instead as at this point we should be able to determine the hidden type of opaque types. Codegen/Post-mono is one of the only places that should be using `ParamEnv::reveal_all`. - -An additional piece of complexity here is specifying the `Reveal` (see linked docs for explanation of what reveal does) used for the `ParamEnv`. When constructing a param env using the `param_env` query it will have `Reveal::UserFacing`, if `Reveal::All` is desired then the [`tcx.param_env_reveal_all_normalized`][env_reveal_all_normalized] query can be used instead. - -The `ParamEnv` type has a method [`ParamEnv::with_reveal_all_normalized`][with_reveal_all] which converts an existing `ParamEnv` into one with `Reveal::All` specified. Where possible the previously mentioned query should be preferred as it is more efficient. - -[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html -[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env -[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env -[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env -[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env -[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html -[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env -[env_reveal_all_normalized]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env_reveal_all_normalized -[with_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.with_reveal_all_normalized -[env_reveal_all]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.reveal_all -[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md b/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md deleted file mode 100644 index 69a262a176e09..0000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_construction_internals.md +++ /dev/null @@ -1,83 +0,0 @@ - -# How are `ParamEnv`'s constructed internally? - -Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). - -## Elaborating supertraits - -When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. - -A concrete example would be the following function: -```rust -trait Trait: SuperTrait {} -trait SuperTrait: SuperSuperTrait {} - -// `bar`'s unelaborated `ParamEnv` would be: -// `[T: Sized, T: Copy, T: Trait]` -fn bar(a: T) { - requires_impl(a); -} - -fn requires_impl(a: T) {} -``` - -If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: -`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` -This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. - -The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound). This is because the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates the where clauses to avoid this. - -As a side effect this also means that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: -```rust -trait Trait {} -// The unelaborated `ParamEnv` would be: -// `[T: Sized, T: Trait, T: Trait]` -// but after elaboration it would be: -// `[T: Sized, T: Trait]` -fn foo() {} -``` - -The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. - -[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html -[next-gen-solver]: ../solve/trait-solving.md - -## Normalizing all bounds - -In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized or else the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: -```rust -trait Trait { - type Assoc; -} - -trait Other { - type Bar; -} - -impl Other for T { - type Bar = u32; -} - -// `foo`'s unnormalized `ParamEnv` would be: -// `[T: Sized, U: Sized, U: Trait]` -fn foo(a: U) -where - U: Trait<::Bar>, -{ - requires_impl(a); -} - -fn requires_impl>(_: U) {} -``` - -As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. - -To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. - -This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). - -In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. - -[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md b/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md deleted file mode 100644 index 0ff6d8fc394e2..0000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_summary.md +++ /dev/null @@ -1,18 +0,0 @@ -# The `ParamEnv` type - -## Summary - -The [`ParamEnv`][pe] is used to store information about the environment that we are interacting with the type system from. For example the set of in-scope where-clauses is stored in `ParamEnv` as it differs between each item whereas the list of user written impls is not stored in the `ParamEnv` as this does not change for each item. - -This chapter of the dev guide covers: -- A high level summary of what a `ParamEnv` is and what it is used for -- Technical details about what the process of constructing a `ParamEnv` involves -- Guidance about how to acquire a `ParamEnv` when one is required - -## Bundling - -A useful API on `ParamEnv` is the [`and`][and] method which allows bundling a value with the `ParamEnv`. The `and` method produces a [`ParamEnvAnd`][pea] making it clearer that using the inner value is intended to be done in that specific environment. - -[and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.and -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnvAnd.html \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md b/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md deleted file mode 100644 index 5c2f4d594052e..0000000000000 --- a/src/doc/rustc-dev-guide/src/param_env/param_env_what_is_it.md +++ /dev/null @@ -1,59 +0,0 @@ - -# What is a `ParamEnv`? - -The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system. - -The information represented by `ParamEnv` is a list of in-scope where-clauses, and a `Reveal` (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds. - -A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. - -If we have a function such as: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Trait, ::Assoc: Clone]` -fn foo() -where - ::Assoc: Clone, -{} -``` -If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. - -A more concrete example: -```rust -// `foo` would have a `ParamEnv` of: -// `[T: Sized, T: Clone]` -fn foo(a: T) { - // when typechecking `foo` we require all the where clauses on `bar` - // to hold in order for it to be legal to call. This means we have to - // prove `T: Clone`. As we are type checking `foo` we use `foo`'s - // environment when trying to check that `T: Clone` holds. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` - // will trivially succeed as bound we want to prove is in our environment. - requires_clone(a); -} -``` - -Or alternatively an example that would not compile: -```rust -// `foo2` would have a `ParamEnv` of: -// `[T: Sized]` -fn foo2(a: T) { - // When typechecking `foo2` we attempt to prove `T: Clone`. - // As we are type checking `foo2` we use `foo2`'s environment - // when trying to prove `T: Clone`. - // - // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will - // fail as there is nothing in the environment telling the trait solver - // that `T` implements `Clone` and there exists no user written impl - // that could apply. - requires_clone(a); -} -``` - -It's very important to use the correct `ParamEnv` when interacting with the type system as otherwise it can lead to ICEs or things compiling when they shouldn't (or vice versa). See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that changed rustc to use the correct param env to avoid ICE. Determining how to acquire the correct `ParamEnv` is explained later in this chapter. - -[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html -[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html -[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env diff --git a/src/doc/rustc-dev-guide/src/traits/caching.md b/src/doc/rustc-dev-guide/src/traits/caching.md index a9f20969b5746..c44722a1d9a33 100644 --- a/src/doc/rustc-dev-guide/src/traits/caching.md +++ b/src/doc/rustc-dev-guide/src/traits/caching.md @@ -61,7 +61,7 @@ to be pretty clearly safe and also still retains a very high hit rate **TODO**: it looks like `pick_candidate_cache` no longer exists. In general, is this section still accurate at all? -[`ParamEnv`]: ../param_env/param_env_summary.html +[`ParamEnv`]: ../typing_parameter_envs.html [`tcx`]: ../ty.html [#18290]: https://github.com/rust-lang/rust/issues/18290 [#22019]: https://github.com/rust-lang/rust/issues/22019 diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index 26eb724588600..c62b0593694f1 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -183,7 +183,7 @@ in that list. If so, it is considered satisfied. More precisely, we want to check whether there is a where-clause obligation that is for the same trait (or some subtrait) and which can match against the obligation. -[parameter environment]: ../param_env/param_env_summary.html +[parameter environment]: ../typing_parameter_envs.html Consider this simple example: diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md new file mode 100644 index 0000000000000..757296d1f6529 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/typing_parameter_envs.md @@ -0,0 +1,206 @@ +# Typing/Parameter Environments + + + +## Typing Environments + +When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The the set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively). + +When an environment to perform type system operations in has not yet been created, the [`TypingEnv`][tenv] can be used to bundle all of the external context required into a single type. + +Once a context to perform type system operations in has been created (e.g. an [`ObligationCtxt`][ocx] or [`FnCtxt`][fnctxt]) a `TypingEnv` is typically not stored anywhere as only the `TypingMode` is a property of the whole environment, whereas different `ParamEnv`s can be used on a per-goal basis. + +[ocx]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/struct.ObligationCtxt.html +[fnctxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html + +## Parameter Environemnts + +### What is a `ParamEnv` + +The [`ParamEnv`][penv] is a list of in-scope where-clauses, it typically corresponds to a specific item's where clauses. Some clauses are not explicitly written but are instead are implicitly added in the [`predicates_of`][predicates_of] query, such as `ConstArgHasType` or (some) implied bounds. + +In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. + +--- + +If we have a function such as: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Trait, ::Assoc: Clone]` +fn foo() +where + ::Assoc: Clone, +{} +``` +If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. + +A more concrete example: +```rust +// `foo` would have a `ParamEnv` of: +// `[T: Sized, T: Clone]` +fn foo(a: T) { + // when typechecking `foo` we require all the where clauses on `requires_clone` + // to hold in order for it to be legal to call. This means we have to + // prove `T: Clone`. As we are type checking `foo` we use `foo`'s + // environment when trying to check that `T: Clone` holds. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` + // will trivially succeed as bound we want to prove is in our environment. + requires_clone(a); +} +``` + +Or alternatively an example that would not compile: +```rust +// `foo2` would have a `ParamEnv` of: +// `[T: Sized]` +fn foo2(a: T) { + // When typechecking `foo2` we attempt to prove `T: Clone`. + // As we are type checking `foo2` we use `foo2`'s environment + // when trying to prove `T: Clone`. + // + // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will + // fail as there is nothing in the environment telling the trait solver + // that `T` implements `Clone` and there exists no user written impl + // that could apply. + requires_clone(a); +} +``` + +[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env + +### Acquiring a `ParamEnv` + +Using the wrong [`ParamEnv`][penv] when interacting with the type system can lead to ICEs, illformed programs compiling, or erroing when we shouldn't. See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that modified the compiler to use the correct param env and in the process fixed ICEs. + +In the large majority of cases, when a `ParamEnv` is required it either already exists somewhere in scope, or above in the call stack and should be passed down. A non exhaustive list of places where you might find an existing `ParamEnv`: +- During typeck `FnCtxt` has a [`param_env` field][fnctxt_param_env] +- When writing late lints the `LateContext` has a [`param_env` field][latectxt_param_env] +- During well formedness checking the `WfCheckingCtxt` has a [`param_env` field][wfckctxt_param_env] +- The `TypeChecker` used for MIR Typeck has a [`param_env` field][mirtypeck_param_env] +- In the next-gen trait solver all `Goal`s have a [`param_env` field][goal_param_env] specifying what environment to prove the goal in +- When editing an existing [`TypeRelation`][typerelation] if it implements [`PredicateEmittingRelation`][predicate_emitting_relation] then a [`param_env` method][typerelation_param_env] will be available. + +If you aren't sure if there's a `ParamEnv` in scope somewhere that can be used it can be worth opening a thread in the [`#t-compiler/help`][compiler_help] zulip stream where someone may be able to point out where a `ParamEnv` can be acquired from. + +Manually constructing a `ParamEnv` is typically only needed at the start of some kind of top level analysis (e.g. hir typeck or borrow checking). In such cases there are three ways it can be done: +- Calling the [`tcx.param_env(def_id)` query][param_env_query] which returns the environment associated with a given definition. +- Creating an empty environment with [`ParamEnv::empty`][env_empty]. +- Using [`ParamEnv::new`][param_env_new] to construct an env with an arbitrary set of where clauses. Then calling [`traits::normalize_param_env_or_error`][normalize_env_or_error] to handle normalizing and elaborating all the where clauses in the env. + +Using the `param_env` query is by far the most common way to construct a `ParamEnv` as most of the time the compiler is performing an analysis as part of some specific definition. + +Creating an empty environment with `ParamEnv::empty` is typically only done either in codegen (indirectly via [`TypingEnv::fully_monomorphized`][tenv_mono]), or as part of some analysis that do not expect to ever encounter generic parameters (e.g. various parts of coherence/orphan check). + +Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_predicate_entailment`][method_pred_entailment]). + +[param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html +[fnctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[latectxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html#structfield.param_env +[wfckctxt_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/struct.WfCheckingCtxt.html#structfield.param_env +[goal_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/solve/struct.Goal.html#structfield.param_env +[typerelation_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/trait.PredicateEmittingRelation.html#tymethod.param_env +[typerelation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/trait.TypeRelation.html +[mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env +[env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty +[param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env +[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[predicate_emitting_relation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/combine/trait.PredicateEmittingRelation.html +[tenv_mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html#method.fully_monomorphized +[compiler_help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp + +### How are `ParamEnv`s constructed + +Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). + +#### Elaborating supertraits + +When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. + +A concrete example would be the following function: +```rust +trait Trait: SuperTrait {} +trait SuperTrait: SuperSuperTrait {} + +// `bar`'s unelaborated `ParamEnv` would be: +// `[T: Sized, T: Copy, T: Trait]` +fn bar(a: T) { + requires_impl(a); +} + +fn requires_impl(a: T) {} +``` + +If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: +`[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` +This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. + +The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound) as the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates where clauses. + +A side effect of this is that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: +```rust +trait Trait {} +// The unelaborated `ParamEnv` would be: +// `[T: Sized, T: Trait, T: Trait]` +// but after elaboration it would be: +// `[T: Sized, T: Trait]` +fn foo() {} +``` + +The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. + +[elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html +[next-gen-solver]: ./solve/trait-solving.md + +#### Normalizing all bounds + +In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized as otherwise the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: +```rust +trait Trait { + type Assoc; +} + +trait Other { + type Bar; +} + +impl Other for T { + type Bar = u32; +} + +// `foo`'s unnormalized `ParamEnv` would be: +// `[T: Sized, U: Sized, U: Trait]` +fn foo(a: U) +where + U: Trait<::Bar>, +{ + requires_impl(a); +} + +fn requires_impl>(_: U) {} +``` + +As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. + +To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. + +This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). + +In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. + +[example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c +[pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html + +## Typing Modes + +Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal. + +Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly. + +[penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html +[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html +[tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html From 38cf49dde8a5b0b284bb6dffd423d223c9f8f7a3 Mon Sep 17 00:00:00 2001 From: Sebastian Urban Date: Thu, 20 Mar 2025 19:08:16 +0100 Subject: [PATCH 101/333] wasm: increase default thread stack size to 1 MB The default stack size for the main thread is 1 MB as specified by linker options. However, the default stack size for threads was only 64 kB. This is surprisingly small and thus we increase it to 1 MB to match the main thread. --- library/std/src/sys/pal/wasi/thread.rs | 2 +- library/std/src/sys/pal/wasm/atomics/thread.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index c85b03d4a8918..cc569bb3daf68 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -67,7 +67,7 @@ cfg_if::cfg_if! { } } -pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; +pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index afdb159fe6f8b..dd5aff391fd8b 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -6,7 +6,7 @@ use crate::time::Duration; pub struct Thread(!); -pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; +pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements From d4b8fa9e4c04f3afb7daad03d6719605a8c4bb90 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 14 Mar 2025 12:47:08 +0100 Subject: [PATCH 102/333] remove `feature(inline_const_pat)` --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_feature/src/removed.rs | 3 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_parse/messages.ftl | 2 - compiler/rustc_parse/src/errors.rs | 11 -- compiler/rustc_parse/src/parser/mod.rs | 15 ++- compiler/rustc_parse/src/parser/pat.rs | 9 -- .../src/language-features/inline-const-pat.md | 22 ---- .../src/matches/redundant_guards.rs | 1 - src/tools/tidy/src/issues.txt | 1 - .../invalid-inline-const-in-match-arm.rs | 9 -- .../invalid-inline-const-in-match-arm.stderr | 18 --- .../feature-gate-inline_const_pat.rs | 4 - .../feature-gate-inline_const_pat.stderr | 13 -- .../range_pat_interactions0.rs | 5 +- .../range_pat_interactions1.rs | 2 - .../range_pat_interactions1.stderr | 19 +-- .../range_pat_interactions2.rs | 22 ---- .../range_pat_interactions2.stderr | 43 ------- .../range_pat_interactions3.rs | 19 --- .../range_pat_interactions3.stderr | 13 -- .../ui/inline-const/collect-scopes-in-pat.rs | 16 --- .../inline-const/const-block-pat-liveness.rs | 18 --- .../inline-const/const-match-pat-generic.rs | 28 ----- .../const-match-pat-generic.stderr | 15 --- .../inline-const/const-match-pat-inference.rs | 11 -- .../const-match-pat-lifetime-err.rs | 47 ------- .../const-match-pat-lifetime-err.stderr | 28 ----- .../inline-const/const-match-pat-lifetime.rs | 34 ----- .../ui/inline-const/const-match-pat-range.rs | 38 ------ tests/ui/inline-const/const-match-pat.rs | 20 --- tests/ui/inline-const/in-pat-recovery.rs | 11 ++ tests/ui/inline-const/in-pat-recovery.stderr | 10 ++ tests/ui/inline-const/pat-match-fndef.rs | 12 -- tests/ui/inline-const/pat-match-fndef.stderr | 8 -- tests/ui/inline-const/pat-unsafe-err.rs | 22 ---- tests/ui/inline-const/pat-unsafe-err.stderr | 19 --- tests/ui/inline-const/pat-unsafe.rs | 29 ----- tests/ui/inline-const/pat-unsafe.stderr | 20 --- tests/ui/lint/dead-code/anon-const-in-pat.rs | 44 ------- tests/ui/match/issue-112438.rs | 10 -- tests/ui/match/validate-range-endpoints.rs | 3 - .../ui/match/validate-range-endpoints.stderr | 28 ++--- tests/ui/parser/issues/issue-24375.stderr | 4 - .../parser/recover/recover-pat-exprs.stderr | 116 ------------------ .../parser/recover/recover-pat-issues.stderr | 24 ---- .../ui/parser/recover/recover-pat-lets.stderr | 8 -- .../parser/recover/recover-pat-ranges.stderr | 24 ---- .../recover/recover-pat-wildcards.stderr | 4 - .../ui/pattern/non-structural-match-types.rs | 31 +++-- .../pattern/non-structural-match-types.stderr | 46 +++++-- tests/ui/type/pattern_types/const_block.rs | 10 -- .../unsafe/const_pat_in_layout_restricted.rs | 23 ---- 53 files changed, 109 insertions(+), 886 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/inline-const-pat.md delete mode 100644 tests/ui/consts/invalid-inline-const-in-match-arm.rs delete mode 100644 tests/ui/consts/invalid-inline-const-in-match-arm.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-inline_const_pat.rs delete mode 100644 tests/ui/feature-gates/feature-gate-inline_const_pat.stderr delete mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions2.rs delete mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions2.stderr delete mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions3.rs delete mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions3.stderr delete mode 100644 tests/ui/inline-const/collect-scopes-in-pat.rs delete mode 100644 tests/ui/inline-const/const-block-pat-liveness.rs delete mode 100644 tests/ui/inline-const/const-match-pat-generic.rs delete mode 100644 tests/ui/inline-const/const-match-pat-generic.stderr delete mode 100644 tests/ui/inline-const/const-match-pat-inference.rs delete mode 100644 tests/ui/inline-const/const-match-pat-lifetime-err.rs delete mode 100644 tests/ui/inline-const/const-match-pat-lifetime-err.stderr delete mode 100644 tests/ui/inline-const/const-match-pat-lifetime.rs delete mode 100644 tests/ui/inline-const/const-match-pat-range.rs delete mode 100644 tests/ui/inline-const/const-match-pat.rs create mode 100644 tests/ui/inline-const/in-pat-recovery.rs create mode 100644 tests/ui/inline-const/in-pat-recovery.stderr delete mode 100644 tests/ui/inline-const/pat-match-fndef.rs delete mode 100644 tests/ui/inline-const/pat-match-fndef.stderr delete mode 100644 tests/ui/inline-const/pat-unsafe-err.rs delete mode 100644 tests/ui/inline-const/pat-unsafe-err.stderr delete mode 100644 tests/ui/inline-const/pat-unsafe.rs delete mode 100644 tests/ui/inline-const/pat-unsafe.stderr delete mode 100644 tests/ui/lint/dead-code/anon-const-in-pat.rs delete mode 100644 tests/ui/match/issue-112438.rs delete mode 100644 tests/ui/type/pattern_types/const_block.rs delete mode 100644 tests/ui/unsafe/const_pat_in_layout_restricted.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 31ff102c127a3..cbe5f8e338f6d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -483,7 +483,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { half_open_range_patterns_in_slices, "half-open range patterns in slices are unstable" ); - gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); gate_all!(associated_const_equality, "associated const equality is incomplete"); gate_all!(yeet_expr, "`do yeet` expression is experimental"); gate_all!(dyn_star, "`dyn*` trait objects are experimental"); diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 47e4f9a2fe885..6ba7b22a0dffa 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -142,6 +142,9 @@ declare_features! ( /// Allows inferring `'static` outlives requirements (RFC 2093). (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), Some("removed as it caused some confusion and discussion was inactive for years")), + /// Allow anonymous constants from an inline `const` block in pattern position + (removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001), + Some("removed due to implementation concerns as it requires significant refactorings")), /// Lazily evaluate constants. This allows constants to depend on type parameters. (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")), /// Changes `impl Trait` to capture all lifetimes in scope. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3b75c69132c20..85bf0d319db67 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -531,8 +531,6 @@ declare_features! ( (unstable, import_trait_associated_functions, "1.86.0", Some(134691)), /// Allows associated types in inherent impls. (incomplete, inherent_associated_types, "1.52.0", Some(8995)), - /// Allow anonymous constants from an inline `const` block in pattern position - (unstable, inline_const_pat, "1.58.0", Some(76001)), /// Allows using `pointer` and `reference` in intra-doc links (unstable, intra_doc_pointers, "1.51.0", Some(80896)), // Allows using the `kl` and `widekl` target features and the associated intrinsics diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 6d4308cda1a60..0ef3d6bc37656 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -842,8 +842,6 @@ parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression int parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard -parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`) - parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard parse_unexpected_if_with_if = unexpected `if` in the condition expression diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e090d9cf7600e..7f3208126586d 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2787,17 +2787,6 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { /// The statement's block's indentation. indentation: String, }, - - #[multipart_suggestion( - parse_unexpected_expr_in_pat_inline_const_sugg, - applicability = "maybe-incorrect" - )] - InlineConst { - #[suggestion_part(code = "const {{ ")] - start_span: Span, - #[suggestion_part(code = " }}")] - end_span: Span, - }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index a79b40482883f..d865fd427641d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1370,9 +1370,6 @@ impl<'a> Parser<'a> { /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { - if pat { - self.psess.gated_spans.gate(sym::inline_const_pat, span); - } self.expect_keyword(exp!(Const))?; let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { @@ -1380,7 +1377,17 @@ impl<'a> Parser<'a> { value: self.mk_expr(blk.span, ExprKind::Block(blk, None)), }; let blk_span = anon_const.value.span; - Ok(self.mk_expr_with_attrs(span.to(blk_span), ExprKind::ConstBlock(anon_const), attrs)) + let kind = if pat { + let guar = self + .dcx() + .struct_span_err(blk_span, "`inline_const_pat` has been removed") + .with_help("use a named `const`-item or an `if`-guard instead") + .emit(); + ExprKind::Err(guar) + } else { + ExprKind::ConstBlock(anon_const) + }; + Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs)) } /// Parses mutability (`mut` or nothing). diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index ec14c5718da53..174cc929fa70d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -631,15 +631,6 @@ impl<'a> Parser<'a> { ident, indentation, }); - - // help: wrap the expr in a `const { expr }` - // FIXME(inline_const_pat): once stabilized, remove this check and remove the `(requires #[feature(inline_const_pat)])` note from the message - if self.parser.psess.unstable_features.is_nightly_build() { - err.subdiagnostic(UnexpectedExpressionInPatternSugg::InlineConst { - start_span: expr_span.shrink_to_lo(), - end_span: expr_span.shrink_to_hi(), - }); - } }, ); } diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md deleted file mode 100644 index c6f54d79cfce8..0000000000000 --- a/src/doc/unstable-book/src/language-features/inline-const-pat.md +++ /dev/null @@ -1,22 +0,0 @@ -# `inline_const_pat` - -The tracking issue for this feature is: [#76001] - ------- - -This feature allows you to use inline constant expressions in pattern position: - -```rust -#![feature(inline_const_pat)] - -const fn one() -> i32 { 1 } - -let some_int = 3; -match some_int { - const { 1 + 2 } => println!("Matched 1 + 2"), - const { one() } => println!("Matched const fn returning 1"), - _ => println!("Didn't match anything :("), -} -``` - -[#76001]: https://github.com/rust-lang/rust/issues/76001 diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index ab53ad98572e4..9bbef8da0a466 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -246,7 +246,6 @@ fn emit_redundant_guards<'tcx>( fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { for_each_expr_without_closures(expr, |expr| { if match expr.kind { - ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat(), ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => { // Allow ctors matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..)) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 2b9ae19547856..c20d670510843 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2876,7 +2876,6 @@ ui/macros/rfc-3086-metavar-expr/issue-111904.rs ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs ui/malformed/issue-69341-malformed-derive-inert.rs ui/marker_trait_attr/issue-61651-type-mismatch.rs -ui/match/issue-112438.rs ui/match/issue-113012.rs ui/match/issue-11319.rs ui/match/issue-114691.rs diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs deleted file mode 100644 index 4fe4b0d33c886..0000000000000 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(inline_const_pat)] - -fn main() { - match () { - const { (|| {})() } => {} - //~^ ERROR cannot call non-const closure in constants - //~| ERROR could not evaluate constant pattern - } -} diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr deleted file mode 100644 index b22f99f40d351..0000000000000 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0015]: cannot call non-const closure in constants - --> $DIR/invalid-inline-const-in-match-arm.rs:5:17 - | -LL | const { (|| {})() } => {} - | ^^^^^^^^^ - | - = note: closures need an RFC before allowed to be called in constants - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error: could not evaluate constant pattern - --> $DIR/invalid-inline-const-in-match-arm.rs:5:9 - | -LL | const { (|| {})() } => {} - | ^^^^^^^^^^^^^^^^^^^ could not evaluate constant - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs b/tests/ui/feature-gates/feature-gate-inline_const_pat.rs deleted file mode 100644 index 3d0df289fb74a..0000000000000 --- a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let const { () } = (); - //~^ ERROR inline-const in pattern position is experimental [E0658] -} diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr deleted file mode 100644 index 7d7376fa818bb..0000000000000 --- a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: inline-const in pattern position is experimental - --> $DIR/feature-gate-inline_const_pat.rs:2:9 - | -LL | let const { () } = (); - | ^^^^^ - | - = note: see issue #76001 for more information - = help: add `#![feature(inline_const_pat)]` 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 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs index f943ea0271da2..f79001ff1f171 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -1,7 +1,5 @@ //@ run-pass #![allow(non_contiguous_range_endpoints)] -#![feature(inline_const_pat)] - fn main() { let mut if_lettable = vec![]; let mut first_or = vec![]; @@ -16,7 +14,6 @@ fn main() { match x { 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), - y @ 0..const { 5 + 1 } => assert_eq!(y, 5), y @ -5.. => range_from.push(y), y @ ..-7 => assert_eq!(y, -8), y => bottom.push(y), @@ -25,6 +22,6 @@ fn main() { assert_eq!(if_lettable, [-1, 0, 2, 4]); assert_eq!(first_or, [-3, -2, -1, 1]); assert_eq!(or_two, [0, 2, 3, 4, 6]); - assert_eq!(range_from, [-5, -4, 7]); + assert_eq!(range_from, [-5, -4, 5, 7]); assert_eq!(bottom, [-7, -6]); } diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs index 4d7c9f10261f2..c5705d5db60f8 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -18,8 +18,6 @@ fn main() { //~^ error: expected a pattern range bound, found an expression 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), - y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - //~^ error: inline-const in pattern position is experimental [E0658] y @ -5.. => range_from.push(y), y @ ..-7 => assert_eq!(y, -8), y => bottom.push(y), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index 62be2ef7a4d83..5cd98faa8abb2 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -11,10 +11,6 @@ LL + const VAL: /* Type */ = 5+1; LL ~ match x as i32 { LL ~ 0..VAL => errors_only.push(x), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | 0..const { 5+1 } => errors_only.push(x), - | +++++++ + error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 @@ -24,17 +20,6 @@ LL | if let n @ 2..3|4 = x { | | | variable not in all patterns -error[E0658]: inline-const in pattern position is experimental - --> $DIR/range_pat_interactions1.rs:21:20 - | -LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - | ^^^^^ - | - = note: see issue #76001 for more information - = help: add `#![feature(inline_const_pat)]` 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 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0408, E0658. -For more information about an error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs deleted file mode 100644 index 0dbdb8fe7b6ef..0000000000000 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs +++ /dev/null @@ -1,22 +0,0 @@ -fn main() { - let mut first_or = Vec::::new(); - let mut or_two = Vec::::new(); - let mut range_from = Vec::::new(); - let mut bottom = Vec::::new(); - let mut errors_only = Vec::::new(); - - for x in -9 + 1..=(9 - 2) { - match x as i32 { - 0..=(5+1) => errors_only.push(x), - //~^ error: expected a pattern range bound, found an expression - //~| error: range pattern bounds cannot have parentheses - 1 | -3..0 => first_or.push(x), - y @ (0..5 | 6) => or_two.push(y), - y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - //~^ error: inline-const in pattern position is experimental - y @ -5.. => range_from.push(y), - y @ ..-7 => assert_eq!(y, -8), - y => bottom.push(y), - } - } -} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr deleted file mode 100644 index dbe7f4482eed4..0000000000000 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: range pattern bounds cannot have parentheses - --> $DIR/range_pat_interactions2.rs:10:17 - | -LL | 0..=(5+1) => errors_only.push(x), - | ^ ^ - | -help: remove these parentheses - | -LL - 0..=(5+1) => errors_only.push(x), -LL + 0..=5+1 => errors_only.push(x), - | - -error: expected a pattern range bound, found an expression - --> $DIR/range_pat_interactions2.rs:10:18 - | -LL | 0..=(5+1) => errors_only.push(x), - | ^^^ not a pattern - | - = note: arbitrary expressions are not allowed in patterns: -help: consider extracting the expression into a `const` - | -LL + const VAL: /* Type */ = 5+1; -LL ~ match x as i32 { -LL ~ 0..=(VAL) => errors_only.push(x), - | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | 0..=(const { 5+1 }) => errors_only.push(x), - | +++++++ + - -error[E0658]: inline-const in pattern position is experimental - --> $DIR/range_pat_interactions2.rs:15:20 - | -LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - | ^^^^^ - | - = note: see issue #76001 for more information - = help: add `#![feature(inline_const_pat)]` 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 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs deleted file mode 100644 index 2f2778095cf49..0000000000000 --- a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs +++ /dev/null @@ -1,19 +0,0 @@ -fn main() { - let mut first_or = Vec::::new(); - let mut or_two = Vec::::new(); - let mut range_from = Vec::::new(); - let mut bottom = Vec::::new(); - - for x in -9 + 1..=(9 - 2) { - match x as i32 { - 8.. => bottom.push(x), - 1 | -3..0 => first_or.push(x), - y @ (0..5 | 6) => or_two.push(y), - y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - //~^ inline-const in pattern position is experimental - y @ -5.. => range_from.push(y), - y @ ..-7 => assert_eq!(y, -8), - y => bottom.push(y), - } - } -} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr deleted file mode 100644 index dc7dc0efa7a28..0000000000000 --- a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: inline-const in pattern position is experimental - --> $DIR/range_pat_interactions3.rs:12:20 - | -LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), - | ^^^^^ - | - = note: see issue #76001 for more information - = help: add `#![feature(inline_const_pat)]` 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 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/inline-const/collect-scopes-in-pat.rs b/tests/ui/inline-const/collect-scopes-in-pat.rs deleted file mode 100644 index 16baf920f584e..0000000000000 --- a/tests/ui/inline-const/collect-scopes-in-pat.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ compile-flags: -Zlint-mir -//@ check-pass - -#![feature(inline_const_pat)] - -fn main() { - match 1 { - const { - || match 0 { - x => 0, - }; - 0 - } => (), - _ => (), - } -} diff --git a/tests/ui/inline-const/const-block-pat-liveness.rs b/tests/ui/inline-const/const-block-pat-liveness.rs deleted file mode 100644 index 26393a4f65b84..0000000000000 --- a/tests/ui/inline-const/const-block-pat-liveness.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! This test used to ICE because const blocks didn't have a body -//! anymore, making a lot of logic very fragile around handling the -//! HIR of a const block. -//! https://github.com/rust-lang/rust/issues/125846 - -//@ check-pass - -#![feature(inline_const_pat)] - -fn main() { - match 0 { - const { - let a = 10_usize; - *&a - } - | _ => {} - } -} diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs deleted file mode 100644 index 889c015e9acb3..0000000000000 --- a/tests/ui/inline-const/const-match-pat-generic.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(inline_const_pat)] - -// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter - -fn foo() { - match 0 { - const { V } => {}, - //~^ ERROR constant pattern cannot depend on generic parameters - _ => {}, - } -} - -const fn f(x: usize) -> usize { - x + 1 -} - -fn bar() { - match 0 { - const { f(V) } => {}, - //~^ ERROR constant pattern cannot depend on generic parameters - _ => {}, - } -} - -fn main() { - foo::<1>(); - bar::<1>(); -} diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr deleted file mode 100644 index 7d9e1d9e407e1..0000000000000 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0158]: constant pattern cannot depend on generic parameters - --> $DIR/const-match-pat-generic.rs:7:9 - | -LL | const { V } => {}, - | ^^^^^^^^^^^ `const` depends on a generic parameter - -error[E0158]: constant pattern cannot depend on generic parameters - --> $DIR/const-match-pat-generic.rs:19:9 - | -LL | const { f(V) } => {}, - | ^^^^^^^^^^^^^^ `const` depends on a generic parameter - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs deleted file mode 100644 index 3d3533839bc79..0000000000000 --- a/tests/ui/inline-const/const-match-pat-inference.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ check-pass - -#![feature(inline_const_pat)] - -fn main() { - match 1u64 { - 0 => (), - const { 0 + 1 } => (), - const { 2 - 1 } ..= const { u64::MAX } => (), - } -} diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs deleted file mode 100644 index 7f450ebe6fccf..0000000000000 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![feature(inline_const_pat)] - -use std::marker::PhantomData; - -#[derive(PartialEq, Eq)] -pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); - -#[derive(PartialEq, Eq)] -pub struct CovariantRef<'a, T: ?Sized>(&'a T); - -impl<'a, T: ?Sized> InvariantRef<'a, T> { - pub const fn new(r: &'a T) -> Self { - InvariantRef(r, PhantomData) - } -} - -impl<'a> InvariantRef<'a, ()> { - pub const NEW: Self = InvariantRef::new(&()); -} - -impl<'a> CovariantRef<'a, ()> { - pub const NEW: Self = CovariantRef(&()); -} - -fn match_invariant_ref<'a>() { - let y = (); - match InvariantRef::new(&y) { - //~^ ERROR `y` does not live long enough [E0597] - const { InvariantRef::<'a>::NEW } => (), - } -} - -fn match_covariant_ref<'a>() { - // Unclear if we should error here (should we be able to subtype the type of - // `y.0`), but using the associated const directly in the pattern also - // errors. - let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),); - //~^ ERROR lifetime may not live long enough - match y.0 { - const { CovariantRef::<'a>::NEW } => (), - } -} - -fn main() { - match_invariant_ref(); - match_covariant_ref(); -} diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr deleted file mode 100644 index 7eea1846057af..0000000000000 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0597]: `y` does not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:27:29 - | -LL | fn match_invariant_ref<'a>() { - | -- lifetime `'a` defined here -LL | let y = (); - | - binding `y` declared here -LL | match InvariantRef::new(&y) { - | ^^ borrowed value does not live long enough -LL | -LL | const { InvariantRef::<'a>::NEW } => (), - | ----------------------- using this value as a constant requires that `y` is borrowed for `'a` -LL | } -LL | } - | - `y` dropped here while still borrowed - -error: lifetime may not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:37:12 - | -LL | fn match_covariant_ref<'a>() { - | -- lifetime `'a` defined here -... -LL | let y: (CovariantRef<'static, _>,) = (CovariantRef(&()),); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs deleted file mode 100644 index 7f1011ea2400d..0000000000000 --- a/tests/ui/inline-const/const-match-pat-lifetime.rs +++ /dev/null @@ -1,34 +0,0 @@ -//@ run-pass - -#![feature(inline_const_pat)] - -use std::marker::PhantomData; - -// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" -fn issue_78174() { - match "foo" { - const { concat!("fo", "o") } => (), - _ => unreachable!(), - } -} - -#[derive(PartialEq, Eq)] -pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); - -impl<'a, T: ?Sized> InvariantRef<'a, T> { - pub const fn new(r: &'a T) -> Self { - InvariantRef(r, PhantomData) - } -} - -fn match_invariant_ref<'a>() { - match const { InvariantRef::<'a, _>::new(&()) } { - const { InvariantRef::<'a, ()>::new(&()) } => { - } - } -} - -fn main() { - issue_78174(); - match_invariant_ref(); -} diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs deleted file mode 100644 index 7202c0c04521e..0000000000000 --- a/tests/ui/inline-const/const-match-pat-range.rs +++ /dev/null @@ -1,38 +0,0 @@ -//@ build-pass - -#![feature(inline_const_pat)] - -fn main() { - const N: u32 = 10; - let x: u32 = 3; - - match x { - 1 ..= const { N + 1 } => {}, - _ => {}, - } - - match x { - const { N - 1 } ..= 10 => {}, - _ => {}, - } - - match x { - const { N - 1 } ..= const { N + 1 } => {}, - _ => {}, - } - - match x { - .. const { N + 1 } => {}, - _ => {}, - } - - match x { - const { N - 1 } .. => {}, - _ => {}, - } - - match x { - ..= const { N + 1 } => {}, - _ => {} - } -} diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs deleted file mode 100644 index 1580ef258129e..0000000000000 --- a/tests/ui/inline-const/const-match-pat.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-pass - -#![feature(inline_const_pat)] -const MMIO_BIT1: u8 = 4; -const MMIO_BIT2: u8 = 5; - -fn main() { - let s = match read_mmio() { - 0 => "FOO", - const { 1 << MMIO_BIT1 } => "BAR", - const { 1 << MMIO_BIT2 } => "BAZ", - _ => unreachable!(), - }; - - assert_eq!("BAZ", s); -} - -fn read_mmio() -> i32 { - 1 << 5 -} diff --git a/tests/ui/inline-const/in-pat-recovery.rs b/tests/ui/inline-const/in-pat-recovery.rs new file mode 100644 index 0000000000000..0d912af09811c --- /dev/null +++ b/tests/ui/inline-const/in-pat-recovery.rs @@ -0,0 +1,11 @@ +// While `feature(inline_const_pat)` has been removed from the +// compiler, we should still make sure that the resulting error +// message is acceptable. +fn main() { + match 1 { + const { 1 + 7 } => {} + //~^ `inline_const_pat` has been removed + 2 => {} + _ => {} + } +} diff --git a/tests/ui/inline-const/in-pat-recovery.stderr b/tests/ui/inline-const/in-pat-recovery.stderr new file mode 100644 index 0000000000000..e1f2e681e77f4 --- /dev/null +++ b/tests/ui/inline-const/in-pat-recovery.stderr @@ -0,0 +1,10 @@ +error: `inline_const_pat` has been removed + --> $DIR/in-pat-recovery.rs:6:15 + | +LL | const { 1 + 7 } => {} + | ^^^^^^^^^ + | + = help: use a named `const`-item or an `if`-guard instead + +error: aborting due to 1 previous error + diff --git a/tests/ui/inline-const/pat-match-fndef.rs b/tests/ui/inline-const/pat-match-fndef.rs deleted file mode 100644 index 013a4a6756102..0000000000000 --- a/tests/ui/inline-const/pat-match-fndef.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(inline_const_pat)] - -fn uwu() {} - -fn main() { - let x = []; - match x[123] { - const { uwu } => {} - //~^ ERROR `fn() {uwu}` cannot be used in patterns - _ => {} - } -} diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr deleted file mode 100644 index 220437a0491af..0000000000000 --- a/tests/ui/inline-const/pat-match-fndef.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fn item `fn() {uwu}` cannot be used in patterns - --> $DIR/pat-match-fndef.rs:8:9 - | -LL | const { uwu } => {} - | ^^^^^^^^^^^^^ fn item can't be used in patterns - -error: aborting due to 1 previous error - diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs deleted file mode 100644 index b906def702950..0000000000000 --- a/tests/ui/inline-const/pat-unsafe-err.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![feature(inline_const_pat)] - -const unsafe fn require_unsafe() -> usize { - 1 -} - -fn main() { - match () { - const { - require_unsafe(); - //~^ ERROR [E0133] - } => (), - } - - match 1 { - const { - require_unsafe() - //~^ ERROR [E0133] - }..=4 => (), - _ => (), - } -} diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr deleted file mode 100644 index 786c7f31ccce1..0000000000000 --- a/tests/ui/inline-const/pat-unsafe-err.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/pat-unsafe-err.rs:10:13 - | -LL | require_unsafe(); - | ^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/pat-unsafe-err.rs:17:13 - | -LL | require_unsafe() - | ^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs deleted file mode 100644 index 4b05f3a1cddd8..0000000000000 --- a/tests/ui/inline-const/pat-unsafe.rs +++ /dev/null @@ -1,29 +0,0 @@ -//@ check-pass - -#![warn(unused_unsafe)] -#![feature(inline_const_pat)] - -const unsafe fn require_unsafe() -> usize { - 1 -} - -fn main() { - unsafe { - match () { - const { - require_unsafe(); - unsafe {} - //~^ WARNING unnecessary `unsafe` block - } => (), - } - - match 1 { - const { - unsafe {} - //~^ WARNING unnecessary `unsafe` block - require_unsafe() - }..=4 => (), - _ => (), - } - } -} diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr deleted file mode 100644 index 59460271ac010..0000000000000 --- a/tests/ui/inline-const/pat-unsafe.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:15:17 - | -LL | unsafe {} - | ^^^^^^ unnecessary `unsafe` block - | -note: the lint level is defined here - --> $DIR/pat-unsafe.rs:3:9 - | -LL | #![warn(unused_unsafe)] - | ^^^^^^^^^^^^^ - -warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:22:17 - | -LL | unsafe {} - | ^^^^^^ unnecessary `unsafe` block - -warning: 2 warnings emitted - diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs deleted file mode 100644 index e2d8c90edcca2..0000000000000 --- a/tests/ui/lint/dead-code/anon-const-in-pat.rs +++ /dev/null @@ -1,44 +0,0 @@ -//@ check-pass -#![feature(inline_const_pat)] -#![deny(dead_code)] - -const fn one() -> i32 { - 1 -} - -const fn two() -> i32 { - 2 -} - -const fn three() -> i32 { - 3 -} - -fn inline_const() { - // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern - match 1 { - const { one() } => {} - _ => {} - } -} - -fn inline_const_range() { - match 1 { - 1 ..= const { two() } => {} - _ => {} - } -} - -struct S; - -fn const_generic_arg() { - match S::<3> { - S::<{three()}> => {} - } -} - -fn main() { - inline_const(); - inline_const_range(); - const_generic_arg(); -} diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs deleted file mode 100644 index b2febe2921054..0000000000000 --- a/tests/ui/match/issue-112438.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -#![feature(inline_const_pat)] -#![allow(dead_code)] -fn foo() { - match 0 { - const { 1 << 5 } | _ => {} - } -} - -fn main() {} diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs index 46d4239886d3c..678cedf016b9e 100644 --- a/tests/ui/match/validate-range-endpoints.rs +++ b/tests/ui/match/validate-range-endpoints.rs @@ -1,4 +1,3 @@ -#![feature(inline_const_pat)] #![allow(overlapping_range_endpoints)] fn main() { @@ -17,8 +16,6 @@ fn main() { // There isn't really a way to detect these 1..=TOO_BIG => {} //~^ ERROR lower range bound must be less than or equal to upper - 1..=const { 256 } => {} - //~^ ERROR lower range bound must be less than or equal to upper _ => {} } diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr index 2d0538804a378..6a8a81a1cc645 100644 --- a/tests/ui/match/validate-range-endpoints.stderr +++ b/tests/ui/match/validate-range-endpoints.stderr @@ -1,59 +1,53 @@ error: literal out of range for `u8` - --> $DIR/validate-range-endpoints.rs:7:12 + --> $DIR/validate-range-endpoints.rs:6:12 | LL | 1..257 => {} | ^^^ this value does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` - --> $DIR/validate-range-endpoints.rs:9:13 + --> $DIR/validate-range-endpoints.rs:8:13 | LL | 1..=256 => {} | ^^^ this value does not fit into the type `u8` whose range is `0..=255` error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/validate-range-endpoints.rs:18:9 + --> $DIR/validate-range-endpoints.rs:17:9 | LL | 1..=TOO_BIG => {} | ^^^^^^^^^^^ lower bound larger than upper bound -error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/validate-range-endpoints.rs:20:9 - | -LL | 1..=const { 256 } => {} - | ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound - error: literal out of range for `u64` - --> $DIR/validate-range-endpoints.rs:26:32 + --> $DIR/validate-range-endpoints.rs:23:32 | LL | 10000000000000000000..=99999999999999999999 => {} | ^^^^^^^^^^^^^^^^^^^^ this value does not fit into the type `u64` whose range is `0..=18446744073709551615` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:32:12 + --> $DIR/validate-range-endpoints.rs:29:12 | LL | 0..129 => {} | ^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:34:13 + --> $DIR/validate-range-endpoints.rs:31:13 | LL | 0..=128 => {} | ^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:36:9 + --> $DIR/validate-range-endpoints.rs:33:9 | LL | -129..0 => {} | ^^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:38:9 + --> $DIR/validate-range-endpoints.rs:35:9 | LL | -10000..=-20 => {} | ^^^^^^ this value does not fit into the type `i8` whose range is `-128..=127` error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered - --> $DIR/validate-range-endpoints.rs:49:11 + --> $DIR/validate-range-endpoints.rs:46:11 | LL | match 0i8 { | ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered @@ -66,7 +60,7 @@ LL + i8::MIN..=-17_i8 | 1_i8..=i8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` not covered - --> $DIR/validate-range-endpoints.rs:53:11 + --> $DIR/validate-range-endpoints.rs:50:11 | LL | match 0i8 { | ^^^ pattern `i8::MIN..=-17_i8` not covered @@ -78,7 +72,7 @@ LL ~ -10000.. => {}, LL + i8::MIN..=-17_i8 => todo!() | -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0004, E0030. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index 2af57a52035c3..e96c004fb3516 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -16,10 +16,6 @@ LL + const VAL: /* Type */ = tmp[0]; LL ~ match z { LL ~ VAL => {} | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { tmp[0] } => {} - | +++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index dcc1945d569c0..69bc5107ccafe 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -17,10 +17,6 @@ LL ~ match 0 { LL | x => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.y } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:6:9 @@ -42,10 +38,6 @@ LL | x => (), LL | x.y => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.0 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:7:9 @@ -68,10 +60,6 @@ LL | x.y => (), LL | x.0 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x._0 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:8:9 @@ -94,10 +82,6 @@ LL | x => (), LL | x._0 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.0.1 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:9:9 @@ -120,10 +104,6 @@ LL | x => (), LL | x.0.1 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.4.y.17.__z } => (), - | +++++++ + error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` --> $DIR/recover-pat-exprs.rs:12:12 @@ -173,10 +153,6 @@ LL + const VAL: /* Type */ = x[0]; LL ~ match 0 { LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x[0] } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:24:9 @@ -197,10 +173,6 @@ LL ~ match 0 { LL | x[0] => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x[..] } => (), - | +++++++ + error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` --> $DIR/recover-pat-exprs.rs:27:12 @@ -247,10 +219,6 @@ LL + const VAL: /* Type */ = x.f(); LL ~ match 0 { LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.f() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:38:9 @@ -271,10 +239,6 @@ LL ~ match 0 { LL | x.f() => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x._f() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:39:9 @@ -296,10 +260,6 @@ LL | x.f() => (), LL | x._f() => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x? } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:40:9 @@ -322,10 +282,6 @@ LL | x._f() => (), LL | x? => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { ().f() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:41:9 @@ -348,10 +304,6 @@ LL | x.f() => (), LL | ().f() => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { (0, x)?.f() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:42:9 @@ -374,10 +326,6 @@ LL | x.f() => (), LL | (0, x)?.f() => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.f().g() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:43:9 @@ -400,10 +348,6 @@ LL | x.f() => (), LL | x.f().g() => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { 0.f()?.g()?? } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:50:9 @@ -423,10 +367,6 @@ LL + const VAL: /* Type */ = x as usize; LL ~ match 0 { LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x as usize } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:51:9 @@ -447,10 +387,6 @@ LL ~ match 0 { LL | x as usize => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { 0 as usize } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:52:9 @@ -472,10 +408,6 @@ LL | x as usize => (), LL | 0 as usize => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.f().0.4 as f32 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:59:9 @@ -495,10 +427,6 @@ LL + const VAL: /* Type */ = 1 + 1; LL ~ match 0 { LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { 1 + 1 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:60:9 @@ -519,10 +447,6 @@ LL ~ match 0 { LL | 1 + 1 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { (1 + 2) * 3 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:63:9 @@ -545,10 +469,6 @@ LL | 1 + 1 => (), LL | LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.0 > 2 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:64:9 @@ -571,10 +491,6 @@ LL | 1 + 1 => (), LL | x.0 > 2 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { x.0 == 2 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:69:13 @@ -594,10 +510,6 @@ LL + const VAL: /* Type */ = y.0 > 2; LL ~ match (0, 0) { LL ~ (x, VAL) if x != 0 => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (x, const { y.0 > 2 }) if x != 0 => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:70:13 @@ -618,10 +530,6 @@ LL ~ match (0, 0) { LL | (x, y.0 > 2) if x != 0 => (), LL ~ (x, VAL) if x != 0 || x != 1 => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (x, const { y.0 > 2 }) if x != 0 || x != 1 => (), - | +++++++ + error: left-hand side of `@` must be a binding --> $DIR/recover-pat-exprs.rs:83:9 @@ -658,10 +566,6 @@ LL + const VAL: /* Type */ = u8::MAX.abs(); LL ~ match u8::MAX { LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { u8::MAX.abs() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:86:17 @@ -684,10 +588,6 @@ LL | u8::MAX.abs() => (), LL | LL ~ z @ w @ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | z @ w @ const { v.u() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:88:9 @@ -710,10 +610,6 @@ LL | u8::MAX.abs() => (), LL | LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { y.ilog(3) } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:90:9 @@ -736,10 +632,6 @@ LL | u8::MAX.abs() => (), LL | LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { n + 1 } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:92:10 @@ -762,10 +654,6 @@ LL | u8::MAX.abs() => (), LL | LL ~ (VAL) => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (const { "".f() + 14 * 8 }) => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:95:9 @@ -788,10 +676,6 @@ LL | u8::MAX.abs() => (), LL | 0 | ((1) | 2) | 3 => (), LL ~ VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { f?() } => (), - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:101:9 diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr index 0c65b16dd951f..ec7fcda3497f4 100644 --- a/tests/ui/parser/recover/recover-pat-issues.stderr +++ b/tests/ui/parser/recover/recover-pat-issues.stderr @@ -16,10 +16,6 @@ LL + const VAL: /* Type */ = "hi".to_owned(); LL ~ match foo { LL ~ Foo(VAL) => true, | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | Foo(const { "hi".to_owned() }) => true, - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:14:20 @@ -39,10 +35,6 @@ LL + const BAZ: /* Type */ = "hi".to_owned(); LL ~ match bar { LL ~ Bar { baz: BAZ } => true, | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | Bar { baz: const { "hi".to_owned() } } => true, - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:25:11 @@ -62,10 +54,6 @@ LL + const VAL: /* Type */ = "foo".to_string(); LL ~ match foo.as_slice() { LL ~ &[VAL] => {} | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | &[const { "foo".to_string() }] => {} - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:36:17 @@ -79,10 +67,6 @@ help: consider extracting the expression into a `const` LL + const VAL: /* Type */ = MAGIC.0 as usize; LL ~ if let Some(VAL) = None:: {} | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | if let Some(const { MAGIC.0 as usize }) = None:: {} - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:41:13 @@ -96,10 +80,6 @@ help: consider extracting the expression into a `const` LL + const VAL: /* Type */ = -1.some(4); LL ~ if let (VAL) = (0, Some(4)) {} | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | if let (const { -1.some(4) }) = (0, Some(4)) {} - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:44:13 @@ -113,10 +93,6 @@ help: consider extracting the expression into a `const` LL + const VAL: /* Type */ = -1.Some(4); LL ~ if let (VAL) = (0, Some(4)) {} | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | if let (const { -1.Some(4) }) = (0, Some(4)) {} - | +++++++ + error: aborting due to 6 previous errors diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr index 55252729d7baa..ab79e4ebcaebe 100644 --- a/tests/ui/parser/recover/recover-pat-lets.stderr +++ b/tests/ui/parser/recover/recover-pat-lets.stderr @@ -34,10 +34,6 @@ help: consider extracting the expression into a `const` LL + const VAL: /* Type */ = 1 + 1; LL ~ let Some(VAL) = x else { | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | let Some(const { 1 + 1 }) = x else { - | +++++++ + error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:17:17 @@ -51,10 +47,6 @@ help: consider extracting the expression into a `const` LL + const VAL: /* Type */ = 1 + 1; LL ~ if let Some(VAL) = x { | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | if let Some(const { 1 + 1 }) = x { - | +++++++ + error: aborting due to 5 previous errors diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr index e8f323596d0fa..6c17182618b5e 100644 --- a/tests/ui/parser/recover/recover-pat-ranges.stderr +++ b/tests/ui/parser/recover/recover-pat-ranges.stderr @@ -98,10 +98,6 @@ LL | 0..=1 => (), LL | LL ~ ..=VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | ..=const { 1 + 2 } => (), - | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:15:10 @@ -119,10 +115,6 @@ LL | 0..=1 => (), LL | LL ~ (VAL).. => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (const { -4 + 0 }).. => (), - | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:18:10 @@ -140,10 +132,6 @@ LL | 0..=1 => (), LL | LL ~ (VAL)...1 * 2 => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (const { 1 + 4 })...1 * 2 => (), - | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:18:19 @@ -161,10 +149,6 @@ LL | 0..=1 => (), LL | LL ~ (1 + 4)...VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | (1 + 4)...const { 1 * 2 } => (), - | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:9 @@ -182,10 +166,6 @@ LL | 0..=1 => (), LL | LL ~ VAL..="y".z() => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | const { 0.x() }..="y".z() => (), - | +++++++ + error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:17 @@ -203,10 +183,6 @@ LL | 0..=1 => (), LL | LL ~ 0.x()..=VAL => (), | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | 0.x()..=const { "y".z() } => (), - | +++++++ + warning: `...` range patterns are deprecated --> $DIR/recover-pat-ranges.rs:18:16 diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr index f939e5133700f..ebc1cbf7d591e 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -84,10 +84,6 @@ LL + const VAL: /* Type */ = 2 + _; LL ~ match 9 { LL ~ 4..=(VAL) => () | -help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`) - | -LL | 4..=(const { 2 + _ }) => () - | +++++++ + error: aborting due to 11 previous errors diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index dde44dfee9c3d..5869767c936ba 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -1,14 +1,29 @@ //@ edition:2021 - -#![allow(unreachable_code)] #![feature(const_async_blocks)] -#![feature(inline_const_pat)] -fn main() { - match loop {} { - const { || {} } => {} //~ ERROR cannot be used in patterns +struct AnyOption(T); +impl AnyOption { + const NONE: Option = None; +} + +fn uwu() {} +fn defines() { + match Some(uwu) { + AnyOption::<_>::NONE => {} + //~^ ERROR constant of non-structural type + _ => {} } - match loop {} { - const { async {} } => {} //~ ERROR cannot be used in patterns + + match Some(|| {}) { + AnyOption::<_>::NONE => {} + //~^ ERROR constant of non-structural type + _ => {} + } + + match Some(async {}) { + AnyOption::<_>::NONE => {} + //~^ ERROR constant of non-structural type + _ => {} } } +fn main() {} diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index 3588751bf6687..da675a9f3ff5a 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,14 +1,42 @@ -error: closure `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:9:9 +error: constant of non-structural type `Option` in a pattern + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | impl AnyOption { + | -------------------- +LL | const NONE: Option = None; + | --------------------- constant defined here +... +LL | AnyOption::<_>::NONE => {} + | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type | -LL | const { || {} } => {} - | ^^^^^^^^^^^^^^^ closure can't be used in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -error: `async` block `{async block@$DIR/non-structural-match-types.rs:12:17: 12:22}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:12:9 +error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:17:16: 17:18}>` in a pattern + --> $DIR/non-structural-match-types.rs:18:9 + | +LL | impl AnyOption { + | -------------------- +LL | const NONE: Option = None; + | --------------------- constant defined here +... +LL | AnyOption::<_>::NONE => {} + | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type + | + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + +error: constant of non-structural type `Option<{async block@$DIR/non-structural-match-types.rs:23:16: 23:21}>` in a pattern + --> $DIR/non-structural-match-types.rs:24:9 + | +LL | impl AnyOption { + | -------------------- +LL | const NONE: Option = None; + | --------------------- constant defined here +... +LL | AnyOption::<_>::NONE => {} + | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type | -LL | const { async {} } => {} - | ^^^^^^^^^^^^^^^^^^ `async` block can't be used in patterns + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + = note: `ResumeTy` must be annotated with `#[derive(PartialEq)]` to be usable in patterns -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs deleted file mode 100644 index ed19b10671af0..0000000000000 --- a/tests/ui/type/pattern_types/const_block.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(pattern_types)] -#![feature(pattern_type_macro)] -#![feature(inline_const_pat)] -//@ check-pass - -use std::pat::pattern_type; - -fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - -fn main() {} diff --git a/tests/ui/unsafe/const_pat_in_layout_restricted.rs b/tests/ui/unsafe/const_pat_in_layout_restricted.rs deleted file mode 100644 index 2ba173ee49962..0000000000000 --- a/tests/ui/unsafe/const_pat_in_layout_restricted.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Check that ref mut patterns within a const pattern don't get considered -// unsafe because they're within a pattern for a layout constrained stuct. -//@ check-pass - -#![feature(rustc_attrs)] -#![feature(inline_const_pat)] - -#[rustc_layout_scalar_valid_range_start(3)] -struct Gt2(i32); - -fn main() { - match unsafe { Gt2(5) } { - Gt2( - const { - || match () { - ref mut y => (), - }; - 4 - }, - ) => (), - _ => (), - } -} From 75935624b383f142f952fa94790a7a88f6ce80b0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 14 Mar 2025 15:37:14 +0100 Subject: [PATCH 103/333] fix pretty test --- tests/pretty/stmt_expr_attributes.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs index 01a503ce7eeaf..90d2b2f5e1e6b 100644 --- a/tests/pretty/stmt_expr_attributes.rs +++ b/tests/pretty/stmt_expr_attributes.rs @@ -1,6 +1,5 @@ //@ pp-exact -#![feature(inline_const_pat)] #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] @@ -206,9 +205,7 @@ fn _11() { let _ = (); () }; - let const { - #![rustc_dummy] - } = + let _ = #[rustc_dummy] const { #![rustc_dummy] }; From 8b2daac8d371c341b92fbdc00876706355b2f69d Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 20 Mar 2025 15:10:42 +0100 Subject: [PATCH 104/333] coretests stop relying on `inline_const_pat` --- library/coretests/tests/lib.rs | 10 +- library/coretests/tests/num/int_macros.rs | 697 +++++++++++---------- library/coretests/tests/num/uint_macros.rs | 503 +++++++-------- 3 files changed, 609 insertions(+), 601 deletions(-) diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 79022fec8a20c..7ad154796f649 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -39,7 +39,6 @@ #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] -#![feature(inline_const_pat)] #![feature(int_roundings)] #![feature(ip)] #![feature(ip_from)] @@ -95,16 +94,17 @@ /// Version of `assert_matches` that ignores fancy runtime printing in const context and uses structural equality. macro_rules! assert_eq_const_safe { - ($left:expr, $right:expr) => { - assert_eq_const_safe!($left, $right, concat!(stringify!($left), " == ", stringify!($right))); + ($t:ty: $left:expr, $right:expr) => { + assert_eq_const_safe!($t: $left, $right, concat!(stringify!($left), " == ", stringify!($right))); }; - ($left:expr, $right:expr$(, $($arg:tt)+)?) => { + ($t:ty: $left:expr, $right:expr$(, $($arg:tt)+)?) => { { fn runtime() { assert_eq!($left, $right, $($($arg)*),*); } const fn compiletime() { - assert!(matches!($left, const { $right })); + const PAT: $t = $right; + assert!(matches!($left, PAT), $($($arg)*),*); } core::intrinsics::const_eval_select((), compiletime, runtime) } diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs index bbf19d2b444f9..0d9fb9e797e1f 100644 --- a/library/coretests/tests/num/int_macros.rs +++ b/library/coretests/tests/num/int_macros.rs @@ -1,5 +1,6 @@ macro_rules! int_module { ($T:ident, $U:ident) => { + use core::num::ParseIntError; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use core::$T::*; @@ -32,20 +33,20 @@ macro_rules! int_module { test_runtime_and_compiletime! { fn test_rem_euclid() { - assert_eq_const_safe!((-1 as $T).rem_euclid(MIN), MAX); + assert_eq_const_safe!($T: (-1 as $T).rem_euclid(MIN), MAX); } fn test_abs() { - assert_eq_const_safe!((1 as $T).abs(), 1 as $T); - assert_eq_const_safe!((0 as $T).abs(), 0 as $T); - assert_eq_const_safe!((-1 as $T).abs(), 1 as $T); + assert_eq_const_safe!($T: (1 as $T).abs(), 1 as $T); + assert_eq_const_safe!($T: (0 as $T).abs(), 0 as $T); + assert_eq_const_safe!($T: (-1 as $T).abs(), 1 as $T); } fn test_signum() { - assert_eq_const_safe!((1 as $T).signum(), 1 as $T); - assert_eq_const_safe!((0 as $T).signum(), 0 as $T); - assert_eq_const_safe!((-0 as $T).signum(), 0 as $T); - assert_eq_const_safe!((-1 as $T).signum(), -1 as $T); + assert_eq_const_safe!($T: (1 as $T).signum(), 1 as $T); + assert_eq_const_safe!($T: (0 as $T).signum(), 0 as $T); + assert_eq_const_safe!($T: (-0 as $T).signum(), 0 as $T); + assert_eq_const_safe!($T: (-1 as $T).signum(), -1 as $T); } fn test_is_positive() { @@ -72,123 +73,123 @@ macro_rules! int_module { test_runtime_and_compiletime! { fn test_count_ones() { - assert_eq_const_safe!(A.count_ones(), 3); - assert_eq_const_safe!(B.count_ones(), 2); - assert_eq_const_safe!(C.count_ones(), 5); + assert_eq_const_safe!(u32: A.count_ones(), 3); + assert_eq_const_safe!(u32: B.count_ones(), 2); + assert_eq_const_safe!(u32: C.count_ones(), 5); } fn test_count_zeros() { - assert_eq_const_safe!(A.count_zeros(), $T::BITS - 3); - assert_eq_const_safe!(B.count_zeros(), $T::BITS - 2); - assert_eq_const_safe!(C.count_zeros(), $T::BITS - 5); + assert_eq_const_safe!(u32: A.count_zeros(), $T::BITS - 3); + assert_eq_const_safe!(u32: B.count_zeros(), $T::BITS - 2); + assert_eq_const_safe!(u32: C.count_zeros(), $T::BITS - 5); } fn test_leading_trailing_ones() { const A: $T = 0b0101_1111; - assert_eq_const_safe!(A.trailing_ones(), 5); - assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7); + assert_eq_const_safe!(u32: A.trailing_ones(), 5); + assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7); - assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5); + assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5); - assert_eq_const_safe!(_1.leading_ones(), $T::BITS); - assert_eq_const_safe!(_1.trailing_ones(), $T::BITS); + assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS); + assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS); - assert_eq_const_safe!((_1 << 1).trailing_ones(), 0); - assert_eq_const_safe!(MAX.leading_ones(), 0); + assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0); + assert_eq_const_safe!(u32: MAX.leading_ones(), 0); - assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq_const_safe!(MAX.trailing_ones(), $T::BITS - 1); + assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq_const_safe!(u32: MAX.trailing_ones(), $T::BITS - 1); - assert_eq_const_safe!(_0.leading_ones(), 0); - assert_eq_const_safe!(_0.trailing_ones(), 0); + assert_eq_const_safe!(u32: _0.leading_ones(), 0); + assert_eq_const_safe!(u32: _0.trailing_ones(), 0); const X: $T = 0b0010_1100; - assert_eq_const_safe!(X.leading_ones(), 0); - assert_eq_const_safe!(X.trailing_ones(), 0); + assert_eq_const_safe!(u32: X.leading_ones(), 0); + assert_eq_const_safe!(u32: X.trailing_ones(), 0); } fn test_rotate() { - assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behavior. See #10183. - assert_eq_const_safe!(_0.rotate_left(124), _0); - assert_eq_const_safe!(_1.rotate_left(124), _1); - assert_eq_const_safe!(_0.rotate_right(124), _0); - assert_eq_const_safe!(_1.rotate_right(124), _1); + assert_eq_const_safe!($T: _0.rotate_left(124), _0); + assert_eq_const_safe!($T: _1.rotate_left(124), _1); + assert_eq_const_safe!($T: _0.rotate_right(124), _0); + assert_eq_const_safe!($T: _1.rotate_right(124), _1); // Rotating by 0 should have no effect - assert_eq_const_safe!(A.rotate_left(0), A); - assert_eq_const_safe!(B.rotate_left(0), B); - assert_eq_const_safe!(C.rotate_left(0), C); + assert_eq_const_safe!($T: A.rotate_left(0), A); + assert_eq_const_safe!($T: B.rotate_left(0), B); + assert_eq_const_safe!($T: C.rotate_left(0), C); // Rotating by a multiple of word size should also have no effect - assert_eq_const_safe!(A.rotate_left(128), A); - assert_eq_const_safe!(B.rotate_left(128), B); - assert_eq_const_safe!(C.rotate_left(128), C); + assert_eq_const_safe!($T: A.rotate_left(128), A); + assert_eq_const_safe!($T: B.rotate_left(128), B); + assert_eq_const_safe!($T: C.rotate_left(128), C); } fn test_swap_bytes() { - assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A); - assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B); - assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C); + assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A); + assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B); + assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C); // Swapping these should make no difference - assert_eq_const_safe!(_0.swap_bytes(), _0); - assert_eq_const_safe!(_1.swap_bytes(), _1); + assert_eq_const_safe!($T: _0.swap_bytes(), _0); + assert_eq_const_safe!($T: _1.swap_bytes(), _1); } fn test_le() { - assert_eq_const_safe!($T::from_le(A.to_le()), A); - assert_eq_const_safe!($T::from_le(B.to_le()), B); - assert_eq_const_safe!($T::from_le(C.to_le()), C); - assert_eq_const_safe!($T::from_le(_0), _0); - assert_eq_const_safe!($T::from_le(_1), _1); - assert_eq_const_safe!(_0.to_le(), _0); - assert_eq_const_safe!(_1.to_le(), _1); + assert_eq_const_safe!($T: $T::from_le(A.to_le()), A); + assert_eq_const_safe!($T: $T::from_le(B.to_le()), B); + assert_eq_const_safe!($T: $T::from_le(C.to_le()), C); + assert_eq_const_safe!($T: $T::from_le(_0), _0); + assert_eq_const_safe!($T: $T::from_le(_1), _1); + assert_eq_const_safe!($T: _0.to_le(), _0); + assert_eq_const_safe!($T: _1.to_le(), _1); } fn test_be() { - assert_eq_const_safe!($T::from_be(A.to_be()), A); - assert_eq_const_safe!($T::from_be(B.to_be()), B); - assert_eq_const_safe!($T::from_be(C.to_be()), C); - assert_eq_const_safe!($T::from_be(_0), _0); - assert_eq_const_safe!($T::from_be(_1), _1); - assert_eq_const_safe!(_0.to_be(), _0); - assert_eq_const_safe!(_1.to_be(), _1); + assert_eq_const_safe!($T: $T::from_be(A.to_be()), A); + assert_eq_const_safe!($T: $T::from_be(B.to_be()), B); + assert_eq_const_safe!($T: $T::from_be(C.to_be()), C); + assert_eq_const_safe!($T: $T::from_be(_0), _0); + assert_eq_const_safe!($T: $T::from_be(_1), _1); + assert_eq_const_safe!($T: _0.to_be(), _0); + assert_eq_const_safe!($T: _1.to_be(), _1); } fn test_signed_checked_div() { - assert_eq_const_safe!((10 as $T).checked_div(2), Some(5)); - assert_eq_const_safe!((5 as $T).checked_div(0), None); - assert_eq_const_safe!(isize::MIN.checked_div(-1), None); + assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5)); + assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None); + assert_eq_const_safe!(Option<$T>: $T::MIN.checked_div(-1), None); } fn test_saturating_abs() { - assert_eq_const_safe!((0 as $T).saturating_abs(), 0); - assert_eq_const_safe!((123 as $T).saturating_abs(), 123); - assert_eq_const_safe!((-123 as $T).saturating_abs(), 123); - assert_eq_const_safe!((MAX - 2).saturating_abs(), MAX - 2); - assert_eq_const_safe!((MAX - 1).saturating_abs(), MAX - 1); - assert_eq_const_safe!(MAX.saturating_abs(), MAX); - assert_eq_const_safe!((MIN + 2).saturating_abs(), MAX - 1); - assert_eq_const_safe!((MIN + 1).saturating_abs(), MAX); - assert_eq_const_safe!(MIN.saturating_abs(), MAX); + assert_eq_const_safe!($T: (0 as $T).saturating_abs(), 0); + assert_eq_const_safe!($T: (123 as $T).saturating_abs(), 123); + assert_eq_const_safe!($T: (-123 as $T).saturating_abs(), 123); + assert_eq_const_safe!($T: (MAX - 2).saturating_abs(), MAX - 2); + assert_eq_const_safe!($T: (MAX - 1).saturating_abs(), MAX - 1); + assert_eq_const_safe!($T: MAX.saturating_abs(), MAX); + assert_eq_const_safe!($T: (MIN + 2).saturating_abs(), MAX - 1); + assert_eq_const_safe!($T: (MIN + 1).saturating_abs(), MAX); + assert_eq_const_safe!($T: MIN.saturating_abs(), MAX); } fn test_saturating_neg() { - assert_eq_const_safe!((0 as $T).saturating_neg(), 0); - assert_eq_const_safe!((123 as $T).saturating_neg(), -123); - assert_eq_const_safe!((-123 as $T).saturating_neg(), 123); - assert_eq_const_safe!((MAX - 2).saturating_neg(), MIN + 3); - assert_eq_const_safe!((MAX - 1).saturating_neg(), MIN + 2); - assert_eq_const_safe!(MAX.saturating_neg(), MIN + 1); - assert_eq_const_safe!((MIN + 2).saturating_neg(), MAX - 1); - assert_eq_const_safe!((MIN + 1).saturating_neg(), MAX); - assert_eq_const_safe!(MIN.saturating_neg(), MAX); + assert_eq_const_safe!($T: (0 as $T).saturating_neg(), 0); + assert_eq_const_safe!($T: (123 as $T).saturating_neg(), -123); + assert_eq_const_safe!($T: (-123 as $T).saturating_neg(), 123); + assert_eq_const_safe!($T: (MAX - 2).saturating_neg(), MIN + 3); + assert_eq_const_safe!($T: (MAX - 1).saturating_neg(), MIN + 2); + assert_eq_const_safe!($T: MAX.saturating_neg(), MIN + 1); + assert_eq_const_safe!($T: (MIN + 2).saturating_neg(), MAX - 1); + assert_eq_const_safe!($T: (MIN + 1).saturating_neg(), MAX); + assert_eq_const_safe!($T: MIN.saturating_neg(), MAX); } } @@ -250,23 +251,23 @@ macro_rules! int_module { test_runtime_and_compiletime! { fn test_from_str_radix() { - assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq_const_safe!(i32::from_str_radix("123", 16), Ok(291 as i32)); - assert_eq_const_safe!(i32::from_str_radix("ffff", 16), Ok(65535 as i32)); - assert_eq_const_safe!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); - assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T)); - assert_eq_const_safe!($T::from_str_radix("Z", 36), Ok(35 as $T)); - - assert_eq_const_safe!($T::from_str_radix("-123", 10), Ok(-123 as $T)); - assert_eq_const_safe!($T::from_str_radix("-1001", 2), Ok(-9 as $T)); - assert_eq_const_safe!($T::from_str_radix("-123", 8), Ok(-83 as $T)); - assert_eq_const_safe!(i32::from_str_radix("-123", 16), Ok(-291 as i32)); - assert_eq_const_safe!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); - assert_eq_const_safe!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); - assert_eq_const_safe!($T::from_str_radix("-z", 36), Ok(-35 as $T)); - assert_eq_const_safe!($T::from_str_radix("-Z", 36), Ok(-35 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq_const_safe!(Result: i32::from_str_radix("123", 16), Ok(291 as i32)); + assert_eq_const_safe!(Result: i32::from_str_radix("ffff", 16), Ok(65535 as i32)); + assert_eq_const_safe!(Result: i32::from_str_radix("FFFF", 16), Ok(65535 as i32)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("Z", 36), Ok(35 as $T)); + + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 10), Ok(-123 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-1001", 2), Ok(-9 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-123", 8), Ok(-83 as $T)); + assert_eq_const_safe!(Result: i32::from_str_radix("-123", 16), Ok(-291 as i32)); + assert_eq_const_safe!(Result: i32::from_str_radix("-ffff", 16), Ok(-65535 as i32)); + assert_eq_const_safe!(Result: i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-z", 36), Ok(-35 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("-Z", 36), Ok(-35 as $T)); assert!($T::from_str_radix("Z", 35).is_err()); assert!($T::from_str_radix("-9", 2).is_err()); @@ -277,16 +278,16 @@ macro_rules! int_module { fn test_pow() { { const R: $T = 2; - assert_eq_const_safe!(R.pow(2), 4 as $T); - assert_eq_const_safe!(R.pow(0), 1 as $T); - assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T); - assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T); - assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T)); - assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T)); - assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false)); - assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false)); - assert_eq_const_safe!(R.saturating_pow(2), 4 as $T); - assert_eq_const_safe!(R.saturating_pow(0), 1 as $T); + assert_eq_const_safe!($T: R.pow(2), 4 as $T); + assert_eq_const_safe!($T: R.pow(0), 1 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T); + assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T)); + assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false)); + assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T); } { @@ -295,221 +296,227 @@ macro_rules! int_module { // if itest::MAX == 2^j-1, then itest is a `j` bit int, // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, // thussaturating_pow the overflowing result is exactly 1. - assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T); - assert_eq_const_safe!(R.checked_pow(2), None); - assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true)); - assert_eq_const_safe!(R.saturating_pow(2), MAX); + assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T); + assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true)); + assert_eq_const_safe!($T: R.saturating_pow(2), MAX); } { // test for negative exponent. const R: $T = -2; - assert_eq_const_safe!(R.pow(2), 4 as $T); - assert_eq_const_safe!(R.pow(3), -8 as $T); - assert_eq_const_safe!(R.pow(0), 1 as $T); - assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T); - assert_eq_const_safe!(R.wrapping_pow(3), -8 as $T); - assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T); - assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T)); - assert_eq_const_safe!(R.checked_pow(3), Some(-8 as $T)); - assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T)); - assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false)); - assert_eq_const_safe!(R.overflowing_pow(3), (-8 as $T, false)); - assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false)); - assert_eq_const_safe!(R.saturating_pow(2), 4 as $T); - assert_eq_const_safe!(R.saturating_pow(3), -8 as $T); - assert_eq_const_safe!(R.saturating_pow(0), 1 as $T); + assert_eq_const_safe!($T: R.pow(2), 4 as $T); + assert_eq_const_safe!($T: R.pow(3), -8 as $T); + assert_eq_const_safe!($T: R.pow(0), 1 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(3), -8 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T); + assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T)); + assert_eq_const_safe!(Option<$T>: R.checked_pow(3), Some(-8 as $T)); + assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(3), (-8 as $T, false)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false)); + assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.saturating_pow(3), -8 as $T); + assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T); } } fn test_div_floor() { const A: $T = 8; const B: $T = 3; - assert_eq_const_safe!(A.div_floor(B), 2); - assert_eq_const_safe!(A.div_floor(-B), -3); - assert_eq_const_safe!((-A).div_floor(B), -3); - assert_eq_const_safe!((-A).div_floor(-B), 2); + assert_eq_const_safe!($T: A.div_floor(B), 2); + assert_eq_const_safe!($T: A.div_floor(-B), -3); + assert_eq_const_safe!($T: (-A).div_floor(B), -3); + assert_eq_const_safe!($T: (-A).div_floor(-B), 2); } fn test_div_ceil() { const A: $T = 8; const B: $T = 3; - assert_eq_const_safe!(A.div_ceil(B), 3); - assert_eq_const_safe!(A.div_ceil(-B), -2); - assert_eq_const_safe!((-A).div_ceil(B), -2); - assert_eq_const_safe!((-A).div_ceil(-B), 3); + assert_eq_const_safe!($T: A.div_ceil(B), 3); + assert_eq_const_safe!($T: A.div_ceil(-B), -2); + assert_eq_const_safe!($T: (-A).div_ceil(B), -2); + assert_eq_const_safe!($T: (-A).div_ceil(-B), 3); } fn test_next_multiple_of() { - assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16); - assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24); - assert_eq_const_safe!((16 as $T).next_multiple_of(-8), 16); - assert_eq_const_safe!((23 as $T).next_multiple_of(-8), 16); - assert_eq_const_safe!((-16 as $T).next_multiple_of(8), -16); - assert_eq_const_safe!((-23 as $T).next_multiple_of(8), -16); - assert_eq_const_safe!((-16 as $T).next_multiple_of(-8), -16); - assert_eq_const_safe!((-23 as $T).next_multiple_of(-8), -24); - assert_eq_const_safe!(MIN.next_multiple_of(-1), MIN); + assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16); + assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24); + assert_eq_const_safe!($T: (16 as $T).next_multiple_of(-8), 16); + assert_eq_const_safe!($T: (23 as $T).next_multiple_of(-8), 16); + assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(8), -16); + assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(8), -16); + assert_eq_const_safe!($T: (-16 as $T).next_multiple_of(-8), -16); + assert_eq_const_safe!($T: (-23 as $T).next_multiple_of(-8), -24); + assert_eq_const_safe!($T: MIN.next_multiple_of(-1), MIN); } fn test_checked_next_multiple_of() { - assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq_const_safe!((16 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq_const_safe!((23 as $T).checked_next_multiple_of(-8), Some(16)); - assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(8), Some(-16)); - assert_eq_const_safe!((-16 as $T).checked_next_multiple_of(-8), Some(-16)); - assert_eq_const_safe!((-23 as $T).checked_next_multiple_of(-8), Some(-24)); - assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None); - assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None); - assert_eq_const_safe!(MIN.checked_next_multiple_of(-3), None); - assert_eq_const_safe!(MIN.checked_next_multiple_of(-1), Some(MIN)); + assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(-8), Some(16)); + assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(8), Some(-16)); + assert_eq_const_safe!(Option<$T>: (-16 as $T).checked_next_multiple_of(-8), Some(-16)); + assert_eq_const_safe!(Option<$T>: (-23 as $T).checked_next_multiple_of(-8), Some(-24)); + assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None); + assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None); + assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-3), None); + assert_eq_const_safe!(Option<$T>: MIN.checked_next_multiple_of(-1), Some(MIN)); } fn test_carrying_add() { - assert_eq_const_safe!(MAX.carrying_add(1, false), (MIN, true)); - assert_eq_const_safe!(MAX.carrying_add(0, true), (MIN, true)); - assert_eq_const_safe!(MAX.carrying_add(1, true), (MIN + 1, true)); - assert_eq_const_safe!(MAX.carrying_add(-1, false), (MAX - 1, false)); - assert_eq_const_safe!(MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow - assert_eq_const_safe!(MIN.carrying_add(-1, false), (MAX, true)); - assert_eq_const_safe!(MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow - assert_eq_const_safe!((0 as $T).carrying_add(MAX, true), (MIN, true)); - assert_eq_const_safe!((0 as $T).carrying_add(MIN, true), (MIN + 1, false)); + assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, false), (MIN, true)); + assert_eq_const_safe!(($T, bool): MAX.carrying_add(0, true), (MIN, true)); + assert_eq_const_safe!(($T, bool): MAX.carrying_add(1, true), (MIN + 1, true)); + assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, false), (MAX - 1, false)); + assert_eq_const_safe!(($T, bool): MAX.carrying_add(-1, true), (MAX, false)); // no intermediate overflow + assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, false), (MAX, true)); + assert_eq_const_safe!(($T, bool): MIN.carrying_add(-1, true), (MIN, false)); // no intermediate overflow + assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MAX, true), (MIN, true)); + assert_eq_const_safe!(($T, bool): (0 as $T).carrying_add(MIN, true), (MIN + 1, false)); } fn test_borrowing_sub() { - assert_eq_const_safe!(MIN.borrowing_sub(1, false), (MAX, true)); - assert_eq_const_safe!(MIN.borrowing_sub(0, true), (MAX, true)); - assert_eq_const_safe!(MIN.borrowing_sub(1, true), (MAX - 1, true)); - assert_eq_const_safe!(MIN.borrowing_sub(-1, false), (MIN + 1, false)); - assert_eq_const_safe!(MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow - assert_eq_const_safe!(MAX.borrowing_sub(-1, false), (MIN, true)); - assert_eq_const_safe!(MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow - assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, false), (MIN, true)); - assert_eq_const_safe!((0 as $T).borrowing_sub(MIN, true), (MAX, false)); + assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, false), (MAX, true)); + assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(0, true), (MAX, true)); + assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(1, true), (MAX - 1, true)); + assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, false), (MIN + 1, false)); + assert_eq_const_safe!(($T, bool): MIN.borrowing_sub(-1, true), (MIN, false)); // no intermediate overflow + assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, false), (MIN, true)); + assert_eq_const_safe!(($T, bool): MAX.borrowing_sub(-1, true), (MAX, false)); // no intermediate overflow + assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, false), (MIN, true)); + assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, true), (MAX, false)); } fn test_widening_mul() { - assert_eq_const_safe!(MAX.widening_mul(MAX), (1, MAX / 2)); - assert_eq_const_safe!(MIN.widening_mul(MAX), (MIN as $U, MIN / 2)); - assert_eq_const_safe!(MIN.widening_mul(MIN), (0, MAX / 2 + 1)); + assert_eq_const_safe!(($U, $T): MAX.widening_mul(MAX), (1, MAX / 2)); + assert_eq_const_safe!(($U, $T): MIN.widening_mul(MAX), (MIN as $U, MIN / 2)); + assert_eq_const_safe!(($U, $T): MIN.widening_mul(MIN), (0, MAX / 2 + 1)); } fn test_carrying_mul() { - assert_eq_const_safe!(MAX.carrying_mul(MAX, 0), (1, MAX / 2)); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, 0), (1, MAX / 2)); + assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, MAX), (UMAX / 2 + 1, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, MIN), (UMAX / 2 + 2, MAX / 2 - 1) ); - assert_eq_const_safe!(MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2)); - assert_eq_const_safe!(MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2)); - assert_eq_const_safe!(MIN.carrying_mul(MAX, MIN), (0, MIN / 2)); - assert_eq_const_safe!(MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1)); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, 0), (MIN as $U, MIN / 2)); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MAX), (UMAX, MIN / 2)); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MAX, MIN), (0, MIN / 2)); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MIN, 0), (0, MAX / 2 + 1)); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MIN, MAX), (UMAX / 2, MAX / 2 + 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul(MIN, MIN), (UMAX / 2 + 1, MAX / 2) ); } fn test_carrying_mul_add() { - assert_eq_const_safe!(MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2)); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, 0, 0), (1, MAX / 2)); + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, MAX, 0), (UMAX / 2 + 1, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, MIN, 0), (UMAX / 2 + 2, MAX / 2 - 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, MAX, MAX), (UMAX, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, MAX, MIN), (0, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MAX.carrying_mul_add(MAX, MIN, MIN), (1, MAX / 2 - 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MAX, 0, 0), (MIN as $U, MIN / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MAX, MAX, 0), (UMAX, MIN / 2) ); - assert_eq_const_safe!(MIN.carrying_mul_add(MAX, MIN, 0), (0, MIN / 2)); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): + MIN.carrying_mul_add(MAX, MIN, 0), + (0, MIN / 2) + ); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MAX, MAX, MAX), (UMAX / 2 - 1, MIN / 2 + 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MAX, MAX, MIN), (UMAX / 2, MIN / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MAX, MIN, MIN), (UMAX / 2 + 1, MIN / 2 - 1) ); - assert_eq_const_safe!(MIN.carrying_mul_add(MIN, 0, 0), (0, MAX / 2 + 1)); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): + MIN.carrying_mul_add(MIN, 0, 0), + (0, MAX / 2 + 1) + ); + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MIN, MAX, 0), (UMAX / 2, MAX / 2 + 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MIN, MIN, 0), (UMAX / 2 + 1, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MIN, MAX, MAX), (UMAX - 1, MAX / 2 + 1) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MIN, MAX, MIN), (UMAX, MAX / 2) ); - assert_eq_const_safe!( + assert_eq_const_safe!(($U, $T): MIN.carrying_mul_add(MIN, MIN, MIN), (0, MAX / 2) ); } fn test_midpoint() { - assert_eq_const_safe!(<$T>::midpoint(1, 3), 2); - assert_eq_const_safe!(<$T>::midpoint(3, 1), 2); + assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2); + assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2); - assert_eq_const_safe!(<$T>::midpoint(0, 0), 0); - assert_eq_const_safe!(<$T>::midpoint(0, 2), 1); - assert_eq_const_safe!(<$T>::midpoint(2, 0), 1); - assert_eq_const_safe!(<$T>::midpoint(2, 2), 2); + assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0); + assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1); + assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1); + assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2); - assert_eq_const_safe!(<$T>::midpoint(1, 4), 2); - assert_eq_const_safe!(<$T>::midpoint(4, 1), 2); - assert_eq_const_safe!(<$T>::midpoint(3, 4), 3); - assert_eq_const_safe!(<$T>::midpoint(4, 3), 3); + assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2); + assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2); + assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3); + assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), 0); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), 0); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), 0); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), 0); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), <$T>::MAX / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), <$T>::MAX / 2 + 3); } } @@ -526,154 +533,154 @@ macro_rules! int_module { test_runtime_and_compiletime! { fn test_unbounded_shl() { // <$T>::MIN - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); // <$T>::MAX - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); // 1 - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0); // -1 - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, 1), (-1 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, 3), (-1 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, 5), (-1 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_ONE), (-1 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_TWO), (-1 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_THREE), (-1 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 1), (-1 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 3), (-1 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, 5), (-1 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(-1, SHIFT_AMOUNT_OVERFLOW3), 0); // 8 - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0); // 17 - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0); } fn test_unbounded_shr() { // <$T>::MIN - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), -1); // <$T>::MAX - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); // 1 - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0); // -1 - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, 1), (-1 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, 3), (-1 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, 5), (-1 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1); - assert_eq_const_safe!(<$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_ONE), (-1 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_TWO), (-1 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_THREE), (-1 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_TEST_FOUR), (-1 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 1), (-1 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 3), (-1 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, 5), (-1 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW2), -1); + assert_eq_const_safe!($T: <$T>::unbounded_shr(-1, SHIFT_AMOUNT_OVERFLOW3), -1); // 8 - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0); // 17 - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0); } } }; diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index d09eb97b17e06..2e35e8bf5342a 100644 --- a/library/coretests/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs @@ -1,5 +1,6 @@ macro_rules! uint_module { ($T:ident) => { + use core::num::ParseIntError; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use core::$T::*; @@ -49,95 +50,95 @@ macro_rules! uint_module { fn test_leading_trailing_ones() { const A: $T = 0b0101_1111; - assert_eq_const_safe!(A.trailing_ones(), 5); - assert_eq_const_safe!((!A).leading_ones(), $T::BITS - 7); + assert_eq_const_safe!(u32: A.trailing_ones(), 5); + assert_eq_const_safe!(u32: (!A).leading_ones(), $T::BITS - 7); - assert_eq_const_safe!(A.reverse_bits().leading_ones(), 5); + assert_eq_const_safe!(u32: A.reverse_bits().leading_ones(), 5); - assert_eq_const_safe!(_1.leading_ones(), $T::BITS); - assert_eq_const_safe!(_1.trailing_ones(), $T::BITS); + assert_eq_const_safe!(u32: _1.leading_ones(), $T::BITS); + assert_eq_const_safe!(u32: _1.trailing_ones(), $T::BITS); - assert_eq_const_safe!((_1 << 1).trailing_ones(), 0); - assert_eq_const_safe!((_1 >> 1).leading_ones(), 0); + assert_eq_const_safe!(u32: (_1 << 1).trailing_ones(), 0); + assert_eq_const_safe!(u32: (_1 >> 1).leading_ones(), 0); - assert_eq_const_safe!((_1 << 1).leading_ones(), $T::BITS - 1); - assert_eq_const_safe!((_1 >> 1).trailing_ones(), $T::BITS - 1); + assert_eq_const_safe!(u32: (_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq_const_safe!(u32: (_1 >> 1).trailing_ones(), $T::BITS - 1); - assert_eq_const_safe!(_0.leading_ones(), 0); - assert_eq_const_safe!(_0.trailing_ones(), 0); + assert_eq_const_safe!(u32: _0.leading_ones(), 0); + assert_eq_const_safe!(u32: _0.trailing_ones(), 0); const X: $T = 0b0010_1100; - assert_eq_const_safe!(X.leading_ones(), 0); - assert_eq_const_safe!(X.trailing_ones(), 0); + assert_eq_const_safe!(u32: X.leading_ones(), 0); + assert_eq_const_safe!(u32: X.trailing_ones(), 0); } fn test_rotate() { - assert_eq_const_safe!(A.rotate_left(6).rotate_right(2).rotate_right(4), A); - assert_eq_const_safe!(B.rotate_left(3).rotate_left(2).rotate_right(5), B); - assert_eq_const_safe!(C.rotate_left(6).rotate_right(2).rotate_right(4), C); + assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A); + assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B); + assert_eq_const_safe!($T: C.rotate_left(6).rotate_right(2).rotate_right(4), C); // Rotating these should make no difference // // We test using 124 bits because to ensure that overlong bit shifts do // not cause undefined behavior. See #10183. - assert_eq_const_safe!(_0.rotate_left(124), _0); - assert_eq_const_safe!(_1.rotate_left(124), _1); - assert_eq_const_safe!(_0.rotate_right(124), _0); - assert_eq_const_safe!(_1.rotate_right(124), _1); + assert_eq_const_safe!($T: _0.rotate_left(124), _0); + assert_eq_const_safe!($T: _1.rotate_left(124), _1); + assert_eq_const_safe!($T: _0.rotate_right(124), _0); + assert_eq_const_safe!($T: _1.rotate_right(124), _1); // Rotating by 0 should have no effect - assert_eq_const_safe!(A.rotate_left(0), A); - assert_eq_const_safe!(B.rotate_left(0), B); - assert_eq_const_safe!(C.rotate_left(0), C); + assert_eq_const_safe!($T: A.rotate_left(0), A); + assert_eq_const_safe!($T: B.rotate_left(0), B); + assert_eq_const_safe!($T: C.rotate_left(0), C); // Rotating by a multiple of word size should also have no effect - assert_eq_const_safe!(A.rotate_left(128), A); - assert_eq_const_safe!(B.rotate_left(128), B); - assert_eq_const_safe!(C.rotate_left(128), C); + assert_eq_const_safe!($T: A.rotate_left(128), A); + assert_eq_const_safe!($T: B.rotate_left(128), B); + assert_eq_const_safe!($T: C.rotate_left(128), C); } fn test_swap_bytes() { - assert_eq_const_safe!(A.swap_bytes().swap_bytes(), A); - assert_eq_const_safe!(B.swap_bytes().swap_bytes(), B); - assert_eq_const_safe!(C.swap_bytes().swap_bytes(), C); + assert_eq_const_safe!($T: A.swap_bytes().swap_bytes(), A); + assert_eq_const_safe!($T: B.swap_bytes().swap_bytes(), B); + assert_eq_const_safe!($T: C.swap_bytes().swap_bytes(), C); // Swapping these should make no difference - assert_eq_const_safe!(_0.swap_bytes(), _0); - assert_eq_const_safe!(_1.swap_bytes(), _1); + assert_eq_const_safe!($T: _0.swap_bytes(), _0); + assert_eq_const_safe!($T: _1.swap_bytes(), _1); } fn test_reverse_bits() { - assert_eq_const_safe!(A.reverse_bits().reverse_bits(), A); - assert_eq_const_safe!(B.reverse_bits().reverse_bits(), B); - assert_eq_const_safe!(C.reverse_bits().reverse_bits(), C); + assert_eq_const_safe!($T: A.reverse_bits().reverse_bits(), A); + assert_eq_const_safe!($T: B.reverse_bits().reverse_bits(), B); + assert_eq_const_safe!($T: C.reverse_bits().reverse_bits(), C); // Swapping these should make no difference - assert_eq_const_safe!(_0.reverse_bits(), _0); - assert_eq_const_safe!(_1.reverse_bits(), _1); + assert_eq_const_safe!($T: _0.reverse_bits(), _0); + assert_eq_const_safe!($T: _1.reverse_bits(), _1); } fn test_le() { - assert_eq_const_safe!($T::from_le(A.to_le()), A); - assert_eq_const_safe!($T::from_le(B.to_le()), B); - assert_eq_const_safe!($T::from_le(C.to_le()), C); - assert_eq_const_safe!($T::from_le(_0), _0); - assert_eq_const_safe!($T::from_le(_1), _1); - assert_eq_const_safe!(_0.to_le(), _0); - assert_eq_const_safe!(_1.to_le(), _1); + assert_eq_const_safe!($T: $T::from_le(A.to_le()), A); + assert_eq_const_safe!($T: $T::from_le(B.to_le()), B); + assert_eq_const_safe!($T: $T::from_le(C.to_le()), C); + assert_eq_const_safe!($T: $T::from_le(_0), _0); + assert_eq_const_safe!($T: $T::from_le(_1), _1); + assert_eq_const_safe!($T: _0.to_le(), _0); + assert_eq_const_safe!($T: _1.to_le(), _1); } fn test_be() { - assert_eq_const_safe!($T::from_be(A.to_be()), A); - assert_eq_const_safe!($T::from_be(B.to_be()), B); - assert_eq_const_safe!($T::from_be(C.to_be()), C); - assert_eq_const_safe!($T::from_be(_0), _0); - assert_eq_const_safe!($T::from_be(_1), _1); - assert_eq_const_safe!(_0.to_be(), _0); - assert_eq_const_safe!(_1.to_be(), _1); + assert_eq_const_safe!($T: $T::from_be(A.to_be()), A); + assert_eq_const_safe!($T: $T::from_be(B.to_be()), B); + assert_eq_const_safe!($T: $T::from_be(C.to_be()), C); + assert_eq_const_safe!($T: $T::from_be(_0), _0); + assert_eq_const_safe!($T: $T::from_be(_1), _1); + assert_eq_const_safe!($T: _0.to_be(), _0); + assert_eq_const_safe!($T: _1.to_be(), _1); } fn test_unsigned_checked_div() { - assert_eq_const_safe!((10 as $T).checked_div(2), Some(5)); - assert_eq_const_safe!((5 as $T).checked_div(0), None); + assert_eq_const_safe!(Option<$T>: (10 as $T).checked_div(2), Some(5)); + assert_eq_const_safe!(Option<$T>: (5 as $T).checked_div(0), None); } } @@ -194,12 +195,12 @@ macro_rules! uint_module { test_runtime_and_compiletime! { fn test_parse_bytes() { - assert_eq_const_safe!($T::from_str_radix("123", 10), Ok(123 as $T)); - assert_eq_const_safe!($T::from_str_radix("1001", 2), Ok(9 as $T)); - assert_eq_const_safe!($T::from_str_radix("123", 8), Ok(83 as $T)); - assert_eq_const_safe!(u16::from_str_radix("123", 16), Ok(291 as u16)); - assert_eq_const_safe!(u16::from_str_radix("ffff", 16), Ok(65535 as u16)); - assert_eq_const_safe!($T::from_str_radix("z", 36), Ok(35 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 10), Ok(123 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("1001", 2), Ok(9 as $T)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("123", 8), Ok(83 as $T)); + assert_eq_const_safe!(Result: u16::from_str_radix("123", 16), Ok(291 as u16)); + assert_eq_const_safe!(Result: u16::from_str_radix("ffff", 16), Ok(65535 as u16)); + assert_eq_const_safe!(Result<$T, ParseIntError>: $T::from_str_radix("z", 36), Ok(35 as $T)); assert!($T::from_str_radix("Z", 10).is_err()); assert!($T::from_str_radix("_", 2).is_err()); @@ -208,16 +209,16 @@ macro_rules! uint_module { fn test_pow() { { const R: $T = 2; - assert_eq_const_safe!(R.pow(2), 4 as $T); - assert_eq_const_safe!(R.pow(0), 1 as $T); - assert_eq_const_safe!(R.wrapping_pow(2), 4 as $T); - assert_eq_const_safe!(R.wrapping_pow(0), 1 as $T); - assert_eq_const_safe!(R.checked_pow(2), Some(4 as $T)); - assert_eq_const_safe!(R.checked_pow(0), Some(1 as $T)); - assert_eq_const_safe!(R.overflowing_pow(2), (4 as $T, false)); - assert_eq_const_safe!(R.overflowing_pow(0), (1 as $T, false)); - assert_eq_const_safe!(R.saturating_pow(2), 4 as $T); - assert_eq_const_safe!(R.saturating_pow(0), 1 as $T); + assert_eq_const_safe!($T: R.pow(2), 4 as $T); + assert_eq_const_safe!($T: R.pow(0), 1 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.wrapping_pow(0), 1 as $T); + assert_eq_const_safe!(Option<$T>: R.checked_pow(2), Some(4 as $T)); + assert_eq_const_safe!(Option<$T>: R.checked_pow(0), Some(1 as $T)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (4 as $T, false)); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(0), (1 as $T, false)); + assert_eq_const_safe!($T: R.saturating_pow(2), 4 as $T); + assert_eq_const_safe!($T: R.saturating_pow(0), 1 as $T); } { @@ -226,20 +227,20 @@ macro_rules! uint_module { // if itest::MAX == 2^j-1, then itest is a `j` bit int, // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`, // thussaturating_pow the overflowing result is exactly 1. - assert_eq_const_safe!(R.wrapping_pow(2), 1 as $T); - assert_eq_const_safe!(R.checked_pow(2), None); - assert_eq_const_safe!(R.overflowing_pow(2), (1 as $T, true)); - assert_eq_const_safe!(R.saturating_pow(2), MAX); + assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T); + assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None); + assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true)); + assert_eq_const_safe!($T: R.saturating_pow(2), MAX); } } fn test_isqrt() { - assert_eq_const_safe!((0 as $T).isqrt(), 0 as $T); - assert_eq_const_safe!((1 as $T).isqrt(), 1 as $T); - assert_eq_const_safe!((2 as $T).isqrt(), 1 as $T); - assert_eq_const_safe!((99 as $T).isqrt(), 9 as $T); - assert_eq_const_safe!((100 as $T).isqrt(), 10 as $T); - assert_eq_const_safe!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); + assert_eq_const_safe!($T: (0 as $T).isqrt(), 0 as $T); + assert_eq_const_safe!($T: (1 as $T).isqrt(), 1 as $T); + assert_eq_const_safe!($T: (2 as $T).isqrt(), 1 as $T); + assert_eq_const_safe!($T: (99 as $T).isqrt(), 9 as $T); + assert_eq_const_safe!($T: (100 as $T).isqrt(), 10 as $T); + assert_eq_const_safe!($T: $T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1); } } @@ -264,24 +265,24 @@ macro_rules! uint_module { test_runtime_and_compiletime! { fn test_div_floor() { - assert_eq_const_safe!((8 as $T).div_floor(3), 2); + assert_eq_const_safe!($T: (8 as $T).div_floor(3), 2); } fn test_div_ceil() { - assert_eq_const_safe!((8 as $T).div_ceil(3), 3); + assert_eq_const_safe!($T: (8 as $T).div_ceil(3), 3); } fn test_next_multiple_of() { - assert_eq_const_safe!((16 as $T).next_multiple_of(8), 16); - assert_eq_const_safe!((23 as $T).next_multiple_of(8), 24); - assert_eq_const_safe!(MAX.next_multiple_of(1), MAX); + assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16); + assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24); + assert_eq_const_safe!($T: MAX.next_multiple_of(1), MAX); } fn test_checked_next_multiple_of() { - assert_eq_const_safe!((16 as $T).checked_next_multiple_of(8), Some(16)); - assert_eq_const_safe!((23 as $T).checked_next_multiple_of(8), Some(24)); - assert_eq_const_safe!((1 as $T).checked_next_multiple_of(0), None); - assert_eq_const_safe!(MAX.checked_next_multiple_of(2), None); + assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16)); + assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24)); + assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None); + assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None); } fn test_is_next_multiple_of() { @@ -292,63 +293,63 @@ macro_rules! uint_module { } fn test_carrying_add() { - assert_eq_const_safe!($T::MAX.carrying_add(1, false), (0, true)); - assert_eq_const_safe!($T::MAX.carrying_add(0, true), (0, true)); - assert_eq_const_safe!($T::MAX.carrying_add(1, true), (1, true)); + assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, false), (0, true)); + assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(0, true), (0, true)); + assert_eq_const_safe!(($T, bool): $T::MAX.carrying_add(1, true), (1, true)); - assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); - assert_eq_const_safe!($T::MIN.carrying_add(0, true), (1, false)); - assert_eq_const_safe!($T::MIN.carrying_add($T::MAX, true), (0, true)); + assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, false), ($T::MAX, false)); + assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add(0, true), (1, false)); + assert_eq_const_safe!(($T, bool): $T::MIN.carrying_add($T::MAX, true), (0, true)); } fn test_borrowing_sub() { - assert_eq_const_safe!($T::MIN.borrowing_sub(1, false), ($T::MAX, true)); - assert_eq_const_safe!($T::MIN.borrowing_sub(0, true), ($T::MAX, true)); - assert_eq_const_safe!($T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); + assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, false), ($T::MAX, true)); + assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(0, true), ($T::MAX, true)); + assert_eq_const_safe!(($T, bool): $T::MIN.borrowing_sub(1, true), ($T::MAX - 1, true)); - assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, false), (0, false)); - assert_eq_const_safe!($T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); - assert_eq_const_safe!($T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); + assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, false), (0, false)); + assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub(0, true), ($T::MAX - 1, false)); + assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true)); } fn test_widening_mul() { - assert_eq_const_safe!($T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1)); + assert_eq_const_safe!(($T, $T): $T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1)); } fn test_carrying_mul() { - assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1)); - assert_eq_const_safe!($T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX)); + assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1)); + assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX)); } fn test_carrying_mul_add() { - assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1)); - assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX)); - assert_eq_const_safe!($T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX)); + assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, 0, 0), (1, $T::MAX - 1)); + assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, 0), (0, $T::MAX)); + assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul_add($T::MAX, $T::MAX, $T::MAX), ($T::MAX, $T::MAX)); } fn test_midpoint() { - assert_eq_const_safe!(<$T>::midpoint(1, 3), 2); - assert_eq_const_safe!(<$T>::midpoint(3, 1), 2); - - assert_eq_const_safe!(<$T>::midpoint(0, 0), 0); - assert_eq_const_safe!(<$T>::midpoint(0, 2), 1); - assert_eq_const_safe!(<$T>::midpoint(2, 0), 1); - assert_eq_const_safe!(<$T>::midpoint(2, 2), 2); - - assert_eq_const_safe!(<$T>::midpoint(1, 4), 2); - assert_eq_const_safe!(<$T>::midpoint(4, 1), 2); - assert_eq_const_safe!(<$T>::midpoint(3, 4), 3); - assert_eq_const_safe!(<$T>::midpoint(4, 3), 3); - - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); - - assert_eq_const_safe!(<$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); - assert_eq_const_safe!(<$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(1, 3), 2); + assert_eq_const_safe!($T: <$T>::midpoint(3, 1), 2); + + assert_eq_const_safe!($T: <$T>::midpoint(0, 0), 0); + assert_eq_const_safe!($T: <$T>::midpoint(0, 2), 1); + assert_eq_const_safe!($T: <$T>::midpoint(2, 0), 1); + assert_eq_const_safe!($T: <$T>::midpoint(2, 2), 2); + + assert_eq_const_safe!($T: <$T>::midpoint(1, 4), 2); + assert_eq_const_safe!($T: <$T>::midpoint(4, 1), 2); + assert_eq_const_safe!($T: <$T>::midpoint(3, 4), 3); + assert_eq_const_safe!($T: <$T>::midpoint(4, 3), 3); + + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MIN), (<$T>::MAX - <$T>::MIN) / 2); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, <$T>::MIN), <$T>::MIN); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, <$T>::MAX), <$T>::MAX); + + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MIN, 6), <$T>::MIN / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MIN), <$T>::MIN / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(<$T>::MAX, 6), (<$T>::MAX - <$T>::MIN) / 2 + 3); + assert_eq_const_safe!($T: <$T>::midpoint(6, <$T>::MAX), (<$T>::MAX - <$T>::MIN) / 2 + 3); } } @@ -365,154 +366,154 @@ macro_rules! uint_module { test_runtime_and_compiletime! { fn test_unbounded_shl() { // <$T>::MIN - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 1), (<$T>::MIN << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 3), (<$T>::MIN << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, 5), (<$T>::MIN << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); // <$T>::MAX - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 1), (<$T>::MAX << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 3), (<$T>::MAX << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, 5), (<$T>::MAX << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); // 1 - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 1), (1 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 3), (1 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, 5), (1 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_ONE), (1 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_TWO), (1 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_THREE), (1 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_TEST_FOUR), (1 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 1), (1 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 3), (1 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, 5), (1 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(1, SHIFT_AMOUNT_OVERFLOW3), 0); // !0 - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, 1), (!0 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, 3), (!0 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, 5), (!0 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_ONE), (!0 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_TWO), (!0 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_THREE), (!0 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 1), (!0 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 3), (!0 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, 5), (!0 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(!0, SHIFT_AMOUNT_OVERFLOW3), 0); // 8 - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 1), (8 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 3), (8 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, 5), (8 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_ONE), (8 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_TWO), (8 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_THREE), (8 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_TEST_FOUR), (8 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 1), (8 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 3), (8 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, 5), (8 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(8, SHIFT_AMOUNT_OVERFLOW3), 0); // 17 - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 1), (17 << 1)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 3), (17 << 3)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, 5), (17 << 5)); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_ONE), (17 << SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_TWO), (17 << SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_THREE), (17 << SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_TEST_FOUR), (17 << SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 1), (17 << 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 3), (17 << 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, 5), (17 << 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shl(17, SHIFT_AMOUNT_OVERFLOW3), 0); } fn test_unbounded_shr() { // <$T>::MIN - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_ONE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_TWO), (<$T>::MIN >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_THREE), (<$T>::MIN >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MIN >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 1), (<$T>::MIN >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 3), (<$T>::MIN >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, 5), (<$T>::MIN >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MIN, SHIFT_AMOUNT_OVERFLOW3), 0); // <$T>::MAX - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_ONE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_TWO), (<$T>::MAX >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_THREE), (<$T>::MAX >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_TEST_FOUR), (<$T>::MAX >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 1), (<$T>::MAX >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 3), (<$T>::MAX >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, 5), (<$T>::MAX >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(<$T>::MAX, SHIFT_AMOUNT_OVERFLOW3), 0); // 1 - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 1), (1 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 3), (1 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, 5), (1 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_ONE), (1 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_TWO), (1 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_THREE), (1 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_TEST_FOUR), (1 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 1), (1 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 3), (1 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, 5), (1 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(1, SHIFT_AMOUNT_OVERFLOW3), 0); // !0 - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, 1), (!0 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, 3), (!0 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, 5), (!0 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_ONE), (!0 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_TWO), (!0 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_THREE), (!0 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_TEST_FOUR), (!0 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 1), (!0 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 3), (!0 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, 5), (!0 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(!0, SHIFT_AMOUNT_OVERFLOW3), 0); // 8 - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 1), (8 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 3), (8 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, 5), (8 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_ONE), (8 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_TWO), (8 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_THREE), (8 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_TEST_FOUR), (8 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 1), (8 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 3), (8 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, 5), (8 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(8, SHIFT_AMOUNT_OVERFLOW3), 0); // 17 - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 1), (17 >> 1)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 3), (17 >> 3)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, 5), (17 >> 5)); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0); - assert_eq_const_safe!(<$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_ONE), (17 >> SHIFT_AMOUNT_TEST_ONE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_TWO), (17 >> SHIFT_AMOUNT_TEST_TWO)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_THREE), (17 >> SHIFT_AMOUNT_TEST_THREE)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_TEST_FOUR), (17 >> SHIFT_AMOUNT_TEST_FOUR)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 1), (17 >> 1)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 3), (17 >> 3)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, 5), (17 >> 5)); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW2), 0); + assert_eq_const_safe!($T: <$T>::unbounded_shr(17, SHIFT_AMOUNT_OVERFLOW3), 0); } } }; From a3b7990b9a3c42a4bf479ea27604927c45fd7172 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 21 Mar 2025 09:35:22 +0100 Subject: [PATCH 105/333] update rustfmt test --- src/tools/rustfmt/tests/source/pattern.rs | 2 +- src/tools/rustfmt/tests/target/pattern.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rustfmt/tests/source/pattern.rs b/src/tools/rustfmt/tests/source/pattern.rs index ed6ad690fa98d..0e5abb52394dd 100644 --- a/src/tools/rustfmt/tests/source/pattern.rs +++ b/src/tools/rustfmt/tests/source/pattern.rs @@ -91,7 +91,7 @@ fn issue3728() { fn literals() { match 42 { - const { 1 + 2 } | 4 + 1 | 2 | 4 | 6 => {} 10 | 11 | 12 | 13 | 14 => {} diff --git a/src/tools/rustfmt/tests/target/pattern.rs b/src/tools/rustfmt/tests/target/pattern.rs index e867f65929dd9..483725f95c48a 100644 --- a/src/tools/rustfmt/tests/target/pattern.rs +++ b/src/tools/rustfmt/tests/target/pattern.rs @@ -99,7 +99,7 @@ fn issue3728() { fn literals() { match 42 { - const { 1 + 2 } | 4 | 6 => {} + 1 | 2 | 4 | 6 => {} 10 | 11 | 12 | 13 | 14 => {} _ => {} } From 957aacd036d787e744a221e9a0d42d7811761a6e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Mar 2025 16:18:43 +0800 Subject: [PATCH 106/333] Move Fuchsia and RfL under `ecosystem-test-jobs/` folder Includes redirects to avoid breaking existing links. --- src/doc/rustc-dev-guide/book.toml | 4 +++- src/doc/rustc-dev-guide/src/SUMMARY.md | 4 ++-- src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md | 2 +- .../src/tests/{ => ecosystem-test-jobs}/fuchsia.md | 4 ++-- .../src/tests/{ => ecosystem-test-jobs}/rust-for-linux.md | 2 +- src/doc/rustc-dev-guide/src/tests/ecosystem.md | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) rename src/doc/rustc-dev-guide/src/tests/{ => ecosystem-test-jobs}/fuchsia.md (98%) rename src/doc/rustc-dev-guide/src/tests/{ => ecosystem-test-jobs}/rust-for-linux.md (97%) diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 67069d9930f57..eb2f6806b96fc 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -62,5 +62,7 @@ warning-policy = "error" "/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" "/diagnostics/diagnostic-codes.html" = "error-codes.html" "/miri.html" = "const-eval/interpret.html" -"/tests/integration.html" = "ecosystem.html" +"/tests/fuchsia.html" = "ecosystem-test-jobs/fuchsia.html" "/tests/headers.html" = "directives.html" +"/tests/integration.html" = "ecosystem.html" +"/tests/rust-for-linux.html" = "ecosystem-test-jobs/rust-for-linux.html" diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 075d5af4c24a5..8fc4fd33e5a3e 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -28,8 +28,8 @@ - [Minicore](./tests/minicore.md) - [Ecosystem testing](./tests/ecosystem.md) - [Crater](./tests/crater.md) - - [Fuchsia](./tests/fuchsia.md) - - [Rust for Linux](./tests/rust-for-linux.md) + - [Fuchsia](./tests/ecosystem-test-jobs/fuchsia.md) + - [Rust for Linux](./tests/ecosystem-test-jobs/rust-for-linux.md) - [Performance testing](./tests/perf.md) - [Suggest tests tool](./tests/suggest-tests.md) - [Misc info](./tests/misc.md) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md index a4658e0d842f9..e3c1a7148d3c7 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/fuchsia.md @@ -9,4 +9,4 @@ This list will be used to notify [Fuchsia][fuchsia] maintainers when the compiler or the standard library changes in a way that would break the Fuchsia integration. -[fuchsia]: ../tests/fuchsia.md +[fuchsia]: ../tests/ecosystem-test-jobs/fuchsia.md diff --git a/src/doc/rustc-dev-guide/src/tests/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md similarity index 98% rename from src/doc/rustc-dev-guide/src/tests/fuchsia.md rename to src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 2766c362cc266..b19d94d6ff734 100644 --- a/src/doc/rustc-dev-guide/src/tests/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -40,7 +40,7 @@ using your local Rust toolchain. src/ci/docker/run.sh x86_64-fuchsia ``` -See the [Testing with Docker](docker.md) chapter for more details on how to run +See the [Testing with Docker](../docker.md) chapter for more details on how to run and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and @@ -170,7 +170,7 @@ rustc book][platform-support]. [`public_configs`]: https://gn.googlesource.com/gn/+/main/docs/reference.md#var_public_configs [`//build/config:compiler`]: https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=121;drc=c26c473bef93b33117ae417893118907a026fec7 [build system]: https://fuchsia.dev/fuchsia-src/development/build/build_system -[fuchsia-ping]: ../notification-groups/fuchsia.md +[fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust code and a roughly equal amount of third-party code, as counted by tokei diff --git a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md similarity index 97% rename from src/doc/rustc-dev-guide/src/tests/rust-for-linux.md rename to src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md index bdf32ffc398db..d549ec6fca529 100644 --- a/src/doc/rustc-dev-guide/src/tests/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md @@ -48,4 +48,4 @@ line to your PR description: Then when you `@bors try` it will pick the job that builds the Rust for Linux integration. -[rfl-ping]: ../notification-groups/rust-for-linux.md +[rfl-ping]: ../../notification-groups/rust-for-linux.md diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem.md b/src/doc/rustc-dev-guide/src/tests/ecosystem.md index 083601404255b..f4b93492e0053 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem.md @@ -24,5 +24,5 @@ there aren't any significant regressions. We have CI jobs that build large open-source Rust projects that are used as regression tests in CI. Our integration jobs build the following projects: -- [Fuchsia](fuchsia.md) -- [Rust for Linux](rust-for-linux.md) +- [Fuchsia](./ecosystem-test-jobs/fuchsia.md) +- [Rust for Linux](./ecosystem-test-jobs/rust-for-linux.md) From d58ccd86c2353bcf22daee05ed44dc0780121c62 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Mar 2025 16:35:46 +0800 Subject: [PATCH 107/333] Stub out codegen backend test pages --- src/doc/rustc-dev-guide/src/SUMMARY.md | 3 +++ .../src/tests/codegen-backend-tests/cg_clif.md | 3 +++ .../src/tests/codegen-backend-tests/cg_gcc.md | 3 +++ .../src/tests/codegen-backend-tests/intro.md | 13 +++++++++++++ src/doc/rustc-dev-guide/src/tests/intro.md | 8 ++++++-- 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md create mode 100644 src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 8fc4fd33e5a3e..29085a6e85334 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -30,6 +30,9 @@ - [Crater](./tests/crater.md) - [Fuchsia](./tests/ecosystem-test-jobs/fuchsia.md) - [Rust for Linux](./tests/ecosystem-test-jobs/rust-for-linux.md) + - [Codegen backend testing](./tests/codegen-backend-tests/intro.md) + - [Cranelift codegen backend](./tests/codegen-backend-tests/cg_clif.md) + - [GCC codegen backend](./tests/codegen-backend-tests/cg_gcc.md) - [Performance testing](./tests/perf.md) - [Suggest tests tool](./tests/suggest-tests.md) - [Misc info](./tests/misc.md) diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md new file mode 100644 index 0000000000000..030ddd7dff571 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_clif.md @@ -0,0 +1,3 @@ +# Cranelift codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md new file mode 100644 index 0000000000000..4caf4c0e0eefa --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md @@ -0,0 +1,3 @@ +# GCC codegen backend tests + +TODO: please add some more information to this page. diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md new file mode 100644 index 0000000000000..c4bac26aba2c2 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md @@ -0,0 +1,13 @@ +# Codegen backend testing + +See also the [Code generation](../../../src/backend/codegen.md) chapter. + +In addition to the primary LLVM codegen backend, the rust-lang/rust CI also runs tests of the [cranelift][cg_clif] and [GCC][cg_gcc] codegen backends in certain test jobs. + +For more details on the tests involved, see: + +- [Cranelift codegen backend tests](./cg_clif.md) +- [GCC codegen backend tests](./cg_gcc.md) + +[cg_clif]: https://github.com/rust-lang/rustc_codegen_cranelift +[cg_gcc]: https://github.com/rust-lang/rustc_codegen_gcc diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index ba44a969bf950..7bf30b106b43b 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -38,7 +38,7 @@ directory, and `x` will essentially run `cargo test` on that package. Examples: | Command | Description | -| ----------------------------------------- | ------------------------------------- | +|-------------------------------------------|---------------------------------------| | `./x test library/std` | Runs tests on `std` only | | `./x test library/core` | Runs tests on `core` only | | `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | @@ -86,7 +86,7 @@ above. Examples: | Command | Description | -| ----------------------- | ------------------------------------------------------------------ | +|-------------------------|--------------------------------------------------------------------| | `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | | `./x fmt` | Runs rustfmt across the entire codebase. | | `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | @@ -155,6 +155,10 @@ chapter](ecosystem.md) for more details. A separate infrastructure is used for testing and tracking performance of the compiler. See the [Performance testing chapter](perf.md) for more details. +### Codegen backend testing + +See [Codegen backend testing](./codegen-backend-tests/intro.md). + ## Miscellaneous information There are some other useful testing-related info at [Misc info](misc.md). From 91ae8651ae0bc6fcc3b3f4e9c0cfaeef1d9342d4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Mar 2025 09:52:08 +0000 Subject: [PATCH 108/333] Rustup to rustc 1.87.0-nightly (78948ac25 2025-03-20) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1b2751c86e3cd..cbed84253fbea 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-18" +channel = "nightly-2025-03-21" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 26cfa6f819e10fa597766d8c5549b86e503ff288 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Fri, 21 Mar 2025 22:36:50 +0800 Subject: [PATCH 109/333] Note potential but private items in show_candidates Signed-off-by: xizheyin --- compiler/rustc_resolve/src/diagnostics.rs | 22 ++++++++--------- compiler/rustc_resolve/src/imports.rs | 2 +- tests/ui/imports/glob-resolve1.stderr | 5 ++++ tests/ui/imports/issue-4366-2.stderr | 5 ++++ tests/ui/imports/issue-4366.stderr | 5 ++++ .../show-private-items-issue-138626.rs | 19 +++++++++++++++ .../show-private-items-issue-138626.stderr | 20 ++++++++++++++++ tests/ui/privacy/privacy-ns1.stderr | 24 +++++++++++++++++++ tests/ui/privacy/privacy-ns2.stderr | 24 +++++++++++++++++++ tests/ui/resolve/issue-21221-1.stderr | 11 +++++++++ tests/ui/unresolved/unresolved-import.rs | 2 ++ tests/ui/unresolved/unresolved-import.stderr | 10 ++++++-- 12 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 tests/ui/imports/show-private-items-issue-138626.rs create mode 100644 tests/ui/imports/show-private-items-issue-138626.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5361af98f3c74..b1dcca4605532 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1325,11 +1325,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }) } - // If only some candidates are accessible, take just them - if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) { - candidates.retain(|x| x.accessible) - } - candidates } @@ -1794,7 +1789,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import_suggestions, Instead::Yes, FoundUse::Yes, - DiagMode::Import { append: single_nested }, + DiagMode::Import { append: single_nested, unresolved_import: false }, vec![], "", ); @@ -2751,6 +2746,8 @@ pub(crate) enum DiagMode { Pattern, /// The binding is part of a use statement Import { + /// `true` means diagnostics is for unresolved import + unresolved_import: bool, /// `true` mean add the tips afterward for case `use a::{b,c}`, /// rather than replacing within. append: bool, @@ -2801,6 +2798,7 @@ fn show_candidates( return false; } + let mut showed = false; let mut accessible_path_strings: Vec> = Vec::new(); let mut inaccessible_path_strings: Vec> = Vec::new(); @@ -2959,8 +2957,11 @@ fn show_candidates( append_candidates(&mut msg, accessible_path_strings); err.help(msg); } - true - } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) { + showed = true; + } + if !inaccessible_path_strings.is_empty() + && (!matches!(mode, DiagMode::Import { unresolved_import: false, .. })) + { let prefix = if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" }; if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] { @@ -3023,10 +3024,9 @@ fn show_candidates( err.span_note(multi_span, msg); } - true - } else { - false + showed = true; } + showed } #[derive(Debug)] diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 89b9a07435183..b38503e07b11a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -734,7 +734,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut diag, Some(err.span), candidates, - DiagMode::Import { append: false }, + DiagMode::Import { append: false, unresolved_import: true }, (source != target) .then(|| format!(" as {target}")) .as_deref() diff --git a/tests/ui/imports/glob-resolve1.stderr b/tests/ui/imports/glob-resolve1.stderr index 75e65681c3ab8..23b0db0fa465b 100644 --- a/tests/ui/imports/glob-resolve1.stderr +++ b/tests/ui/imports/glob-resolve1.stderr @@ -58,6 +58,11 @@ error[E0425]: cannot find function `import` in this scope LL | import(); | ^^^^^^ not found in this scope | +note: function `bar::import` exists but is inaccessible + --> $DIR/glob-resolve1.rs:7:5 + | +LL | fn fpriv() {} + | ^^^^^^^^^^ not accessible help: consider importing this function | LL + use other::import; diff --git a/tests/ui/imports/issue-4366-2.stderr b/tests/ui/imports/issue-4366-2.stderr index 412423f4d595e..b1c0092b05d11 100644 --- a/tests/ui/imports/issue-4366-2.stderr +++ b/tests/ui/imports/issue-4366-2.stderr @@ -16,6 +16,11 @@ error[E0423]: expected function, found module `foo` LL | foo(); | ^^^ not a function | +note: function `m1::foo` exists but is inaccessible + --> $DIR/issue-4366-2.rs:21:5 + | +LL | fn foo() {} + | ^^^^^^^^ not accessible help: consider importing this function instead | LL + use foo::foo; diff --git a/tests/ui/imports/issue-4366.stderr b/tests/ui/imports/issue-4366.stderr index e63399d554ee3..54b7f31b2313a 100644 --- a/tests/ui/imports/issue-4366.stderr +++ b/tests/ui/imports/issue-4366.stderr @@ -4,6 +4,11 @@ error[E0425]: cannot find function `foo` in this scope LL | fn sub() -> isize { foo(); 1 } | ^^^ not found in this scope | +note: function `m1::foo` exists but is inaccessible + --> $DIR/issue-4366.rs:23:5 + | +LL | fn foo() {} + | ^^^^^^^^ not accessible help: consider importing this function | LL + use foo::foo; diff --git a/tests/ui/imports/show-private-items-issue-138626.rs b/tests/ui/imports/show-private-items-issue-138626.rs new file mode 100644 index 0000000000000..d9708fc33c215 --- /dev/null +++ b/tests/ui/imports/show-private-items-issue-138626.rs @@ -0,0 +1,19 @@ +pub mod one { + mod foo { + pub struct Foo; + } + + pub use self::foo::Foo; +} + +pub mod two { + mod foo { + mod bar { + pub struct Foo; + } + } + + pub use crate::two::foo::Foo; //~ ERROR unresolved import `crate::two::foo::Foo` [E0432] +} + +fn main() {} diff --git a/tests/ui/imports/show-private-items-issue-138626.stderr b/tests/ui/imports/show-private-items-issue-138626.stderr new file mode 100644 index 0000000000000..b664462daed7d --- /dev/null +++ b/tests/ui/imports/show-private-items-issue-138626.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved import `crate::two::foo::Foo` + --> $DIR/show-private-items-issue-138626.rs:16:13 + | +LL | pub use crate::two::foo::Foo; + | ^^^^^^^^^^^^^^^^^^^^ no `Foo` in `two::foo` + | +note: struct `two::foo::bar::Foo` exists but is inaccessible + --> $DIR/show-private-items-issue-138626.rs:12:13 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ not accessible +help: consider importing this struct through its public re-export instead + | +LL - pub use crate::two::foo::Foo; +LL + pub use one::Foo; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/privacy/privacy-ns1.stderr b/tests/ui/privacy/privacy-ns1.stderr index 3396330c993cf..c782c67e71c6e 100644 --- a/tests/ui/privacy/privacy-ns1.stderr +++ b/tests/ui/privacy/privacy-ns1.stderr @@ -7,6 +7,14 @@ LL | pub struct Baz; LL | Bar(); | ^^^ | +note: these functions exist but are inaccessible + --> $DIR/privacy-ns1.rs:14:5 + | +LL | fn Bar() { } + | ^^^^^^^^ `foo1::Bar`: not accessible +... +LL | fn Bar() { } + | ^^^^^^^^ `foo3::Bar`: not accessible help: a unit struct with a similar name exists | LL - Bar(); @@ -26,6 +34,14 @@ LL | pub struct Baz; LL | Bar(); | ^^^ | +note: these functions exist but are inaccessible + --> $DIR/privacy-ns1.rs:14:5 + | +LL | fn Bar() { } + | ^^^^^^^^ `foo1::Bar`: not accessible +... +LL | fn Bar() { } + | ^^^^^^^^ `foo3::Bar`: not accessible help: a unit struct with a similar name exists | LL - Bar(); @@ -45,6 +61,14 @@ LL | pub struct Baz; LL | let _x: Box; | ^^^ | +note: these traits exist but are inaccessible + --> $DIR/privacy-ns1.rs:25:5 + | +LL | trait Bar { + | ^^^^^^^^^ `foo2::Bar`: not accessible +... +LL | trait Bar { + | ^^^^^^^^^ `foo3::Bar`: not accessible help: a struct with a similar name exists | LL - let _x: Box; diff --git a/tests/ui/privacy/privacy-ns2.stderr b/tests/ui/privacy/privacy-ns2.stderr index ac98682b2b39e..fe1f0c9bd48ca 100644 --- a/tests/ui/privacy/privacy-ns2.stderr +++ b/tests/ui/privacy/privacy-ns2.stderr @@ -4,6 +4,14 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar LL | Bar(); | ^^^ not a function, tuple struct or tuple variant | +note: these functions exist but are inaccessible + --> $DIR/privacy-ns2.rs:14:5 + | +LL | fn Bar() { } + | ^^^^^^^^ `foo1::Bar`: not accessible +... +LL | fn Bar() { } + | ^^^^^^^^ `foo3::Bar`: not accessible help: consider importing this function instead | LL + use foo2::Bar; @@ -18,6 +26,14 @@ LL | pub struct Baz; LL | Bar(); | ^^^ | +note: these functions exist but are inaccessible + --> $DIR/privacy-ns2.rs:14:5 + | +LL | fn Bar() { } + | ^^^^^^^^ `foo1::Bar`: not accessible +... +LL | fn Bar() { } + | ^^^^^^^^ `foo3::Bar`: not accessible help: a unit struct with a similar name exists | LL - Bar(); @@ -34,6 +50,14 @@ error[E0573]: expected type, found function `Bar` LL | let _x : Bar(); | ^^^^^ not a type | +note: these traits exist but are inaccessible + --> $DIR/privacy-ns2.rs:31:5 + | +LL | trait Bar { + | ^^^^^^^^^ `foo2::Bar`: not accessible +... +LL | trait Bar { + | ^^^^^^^^^ `foo3::Bar`: not accessible help: use `=` if you meant to assign | LL - let _x : Bar(); diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr index ccf03afaa19fe..dafa41bf312f5 100644 --- a/tests/ui/resolve/issue-21221-1.stderr +++ b/tests/ui/resolve/issue-21221-1.stderr @@ -19,6 +19,17 @@ error[E0412]: cannot find type `Mul` in this scope LL | fn getMul() -> Mul { | ^^^ not found in this scope | +note: these items exist but are inaccessible + --> $DIR/issue-21221-1.rs:10:5 + | +LL | enum Mul { + | ^^^^^^^^ `mul3::Mul`: not accessible +... +LL | type Mul = String; + | ^^^^^^^^^^^^^^^^^^ `mul4::Mul`: not accessible +... +LL | struct Mul{ + | ^^^^^^^^^^ `mul5::Mul`: not accessible help: consider importing one of these traits | LL + use std::ops::Mul; diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index 763e9496734dd..b0fdcf970155b 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -31,6 +31,8 @@ mod food { mod zug { pub mod baz { + //~^ NOTE module `food::zug::baz` exists but is inaccessible + //~| NOTE not accessible pub struct Foobar; } } diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index c65fe841001d7..4001695459a90 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -26,6 +26,12 @@ LL | use food::baz; | | | | | help: a similar name exists in the module: `bag` | no `baz` in `food` + | +note: module `food::zug::baz` exists but is inaccessible + --> $DIR/unresolved-import.rs:33:9 + | +LL | pub mod baz { + | ^^^^^^^^^^^ not accessible error[E0432]: unresolved import `food::beens` --> $DIR/unresolved-import.rs:19:12 @@ -37,13 +43,13 @@ LL | use food::{beens as Foo}; | help: a similar name exists in the module: `beans` error[E0432]: unresolved import `MyEnum` - --> $DIR/unresolved-import.rs:44:9 + --> $DIR/unresolved-import.rs:46:9 | LL | use MyEnum::*; | ^^^^^^ help: a similar path exists: `self::MyEnum` error[E0432]: unresolved import `Enum` - --> $DIR/unresolved-import.rs:55:9 + --> $DIR/unresolved-import.rs:57:9 | LL | use Enum::*; | ^^^^ help: a similar path exists: `self::Enum` From 5016467a23c93384ffcb58b9c5ff2f8afc349d54 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 28 Nov 2024 21:57:39 +0800 Subject: [PATCH 110/333] Implement `UniqueArc` --- library/alloc/src/sync.rs | 182 +++++++++++++++++++++++++++++++- library/alloctests/tests/arc.rs | 5 +- library/std/src/sync/mod.rs | 2 + 3 files changed, 187 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index c62f8e5b70f4d..3903303bcea6b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -20,7 +20,7 @@ use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; use core::num::NonZeroUsize; -use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver}; +use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::{Pin, PinCoerceUnsized}; use core::ptr::{self, NonNull}; @@ -4066,3 +4066,183 @@ impl core::error::Error for Arc { core::error::Error::provide(&**self, req); } } + +/// A uniquely owned [`Arc`]. +/// +/// This represents an `Arc` that is known to be uniquely owned -- that is, have exactly one strong +/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong +/// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`. +/// +/// Because they are uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common +/// use case is to have an object be mutable during its initialization phase but then have it become +/// immutable and converted to a normal `Arc`. +/// +/// This can be used as a flexible way to create cyclic data structures, as in the example below. +/// +/// ``` +/// #![feature(unique_rc_arc)] +/// use std::sync::{Arc, Weak, UniqueArc}; +/// +/// struct Gadget { +/// #[allow(dead_code)] +/// me: Weak, +/// } +/// +/// fn create_gadget() -> Option> { +/// let mut rc = UniqueArc::new(Gadget { +/// me: Weak::new(), +/// }); +/// rc.me = UniqueArc::downgrade(&rc); +/// Some(UniqueArc::into_arc(rc)) +/// } +/// +/// create_gadget().unwrap(); +/// ``` +/// +/// An advantage of using `UniqueArc` over [`Arc::new_cyclic`] to build cyclic data structures is that +/// [`Arc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the +/// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data, +/// including fallible or async constructors. +#[unstable(feature = "unique_rc_arc", issue = "112566")] +#[derive(Debug)] +pub struct UniqueArc< + T: ?Sized, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + ptr: NonNull>, + phantom: PhantomData>, + alloc: A, +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl, U: ?Sized, A: Allocator> CoerceUnsized> + for UniqueArc +{ +} + +// Depends on A = Global +impl UniqueArc { + /// Creates a new `UniqueArc`. + /// + /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. + /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will + /// point to the new [`Arc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn new(value: T) -> Self { + Self::new_in(value, Global) + } +} + +impl UniqueArc { + /// Creates a new `UniqueArc` in the provided allocator. + /// + /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading + /// these weak references will fail before the `UniqueArc` has been converted into an [`Arc`]. + /// After converting the `UniqueArc` into an [`Arc`], any weak references created beforehand will + /// point to the new [`Arc`]. + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn new_in(data: T, alloc: A) -> Self { + let (ptr, alloc) = Box::into_unique(Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueArc still stays valid. + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )); + Self { ptr: ptr.into(), phantom: PhantomData, alloc } + } +} + +impl UniqueArc { + /// Converts the `UniqueArc` into a regular [`Arc`]. + /// + /// This consumes the `UniqueArc` and returns a regular [`Arc`] that contains the `value` that + /// is passed to `into_arc`. + /// + /// Any weak references created before this method is called can now be upgraded to strong + /// references. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn into_arc(this: Self) -> Arc { + let this = ManuallyDrop::new(this); + + // Move the allocator out. + // SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in + // a `ManuallyDrop`. + let alloc: A = unsafe { ptr::read(&this.alloc) }; + + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { + // Convert our weak reference into a strong reference + (*this.ptr.as_ptr()).strong.store(1, Release); + Arc::from_inner_in(this.ptr, alloc) + } + } +} + +impl UniqueArc { + /// Creates a new weak reference to the `UniqueArc`. + /// + /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted + /// to a [`Arc`] using [`UniqueArc::into_arc`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn downgrade(this: &Self) -> Weak { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object or converting the object to a normal `Arc`. + // + // Note that we don't need to test if the weak counter is locked because there + // are no such operations like `Arc::get_mut` or `Arc::make_mut` that will lock + // the weak counter. + // + // SAFETY: This pointer was allocated at creation time so we know it is valid. + let old_size = unsafe { (*this.ptr.as_ptr()).weak.fetch_add(1, Relaxed) }; + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + abort(); + } + + Weak { ptr: this.ptr, alloc: this.alloc.clone() } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Deref for UniqueArc { + type Target = T; + + fn deref(&self) -> &T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. + unsafe { &self.ptr.as_ref().data } + } +} + +// #[unstable(feature = "unique_rc_arc", issue = "112566")] +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl DerefMut for UniqueArc { + fn deref_mut(&mut self) -> &mut T { + // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we + // have unique ownership and therefore it's safe to make a mutable reference because + // `UniqueArc` owns the only strong reference to itself. + unsafe { &mut (*self.ptr.as_ptr()).data } + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { + fn drop(&mut self) { + // See `Arc::drop_slow` which drops an `Arc` with a strong count of 0. + // SAFETY: This pointer was allocated at creation time so we know it is valid. + let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + + unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; + } +} diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs index 0baa50f439b37..45a145c6271a8 100644 --- a/library/alloctests/tests/arc.rs +++ b/library/alloctests/tests/arc.rs @@ -265,7 +265,7 @@ fn make_mut_unsized() { #[allow(unused)] mod pin_coerce_unsized { - use alloc::sync::Arc; + use alloc::sync::{Arc, UniqueArc}; use core::pin::Pin; pub trait MyTrait {} @@ -275,4 +275,7 @@ mod pin_coerce_unsized { pub fn pin_arc(arg: Pin>) -> Pin> { arg } + pub fn pin_unique_arc(arg: Pin>) -> Pin> { + arg + } } diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 5b50a3c6ccf90..e67b4f6f22f5a 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -176,6 +176,8 @@ pub use core::sync::Exclusive; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; +#[unstable(feature = "unique_rc_arc", issue = "112566")] +pub use alloc_crate::sync::UniqueArc; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::sync::{Arc, Weak}; From 9e5cca504988932581fa6c83c8626101013d64cd Mon Sep 17 00:00:00 2001 From: Frank King Date: Mon, 3 Mar 2025 10:53:25 +0800 Subject: [PATCH 111/333] Make UniqueArc invariant for soundness --- library/alloc/src/sync.rs | 8 ++++-- tests/ui/variance/variance-uniquearc.rs | 27 +++++++++++++++++++++ tests/ui/variance/variance-uniquearc.stderr | 15 ++++++++++++ tests/ui/variance/variance-uniquerc.rs | 2 +- 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 tests/ui/variance/variance-uniquearc.rs create mode 100644 tests/ui/variance/variance-uniquearc.stderr diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 3903303bcea6b..5f0133c6c56de 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4110,7 +4110,11 @@ pub struct UniqueArc< #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { ptr: NonNull>, - phantom: PhantomData>, + // Define the ownership of `ArcInner` for drop-check + _marker: PhantomData>, + // Invariance is necessary for soundness: once other `Weak` + // references exist, we already have a form of shared mutability! + _marker2: PhantomData<*mut T>, alloc: A, } @@ -4155,7 +4159,7 @@ impl UniqueArc { }, alloc, )); - Self { ptr: ptr.into(), phantom: PhantomData, alloc } + Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc } } } diff --git a/tests/ui/variance/variance-uniquearc.rs b/tests/ui/variance/variance-uniquearc.rs new file mode 100644 index 0000000000000..0358951238869 --- /dev/null +++ b/tests/ui/variance/variance-uniquearc.rs @@ -0,0 +1,27 @@ +// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164 +// see also the test for UniqueRc` in variance-uniquerc.rs +// +// inline comments explain how this code *would* compile if UniqueArc was still covariant + +#![feature(unique_rc_arc)] + +use std::sync::UniqueArc; + +fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str { + let r = UniqueArc::new(""); // UniqueArc<&'static str> + let w = UniqueArc::downgrade(&r); // Weak<&'static str> + let mut r = r; // [IF COVARIANT]: ==>> UniqueArc<&'a str> + *r = x; // assign the &'a str + let _r = UniqueArc::into_arc(r); // Arc<&'a str>, but we only care to activate the weak + let r = w.upgrade().unwrap(); // Arc<&'static str> + *r // &'static str, coerces to &'b str + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let s = String::from("Hello World!"); + let r = extend_lifetime(&s); + println!("{r}"); + drop(s); + println!("{r}"); +} diff --git a/tests/ui/variance/variance-uniquearc.stderr b/tests/ui/variance/variance-uniquearc.stderr new file mode 100644 index 0000000000000..55076dae7324b --- /dev/null +++ b/tests/ui/variance/variance-uniquearc.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/variance-uniquearc.rs:17:5 + | +LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | *r // &'static str, coerces to &'b str + | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 1 previous error + diff --git a/tests/ui/variance/variance-uniquerc.rs b/tests/ui/variance/variance-uniquerc.rs index 0c395ab06eaa3..2e9738f66dcb8 100644 --- a/tests/ui/variance/variance-uniquerc.rs +++ b/tests/ui/variance/variance-uniquerc.rs @@ -1,5 +1,5 @@ // regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164 -// we should also test UniqueArc once implemented +// see also the test for UniqueArc in variance-uniquearc.rs // // inline comments explain how this code *would* compile if UniqueRc was still covariant From b542a2bd4bbef0221a78ecbd31d4a4ea9fb22f64 Mon Sep 17 00:00:00 2001 From: Frank King Date: Mon, 3 Mar 2025 15:51:05 +0800 Subject: [PATCH 112/333] Add more APIs for UniqueArc --- library/alloc/src/sync.rs | 255 +++++++++++++++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5f0133c6c56de..b883f84d68eed 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4073,7 +4073,7 @@ impl core::error::Error for Arc { /// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong /// references will fail unless the `UniqueArc` they point to has been converted into a regular `Arc`. /// -/// Because they are uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common +/// Because it is uniquely owned, the contents of a `UniqueArc` can be freely mutated. A common /// use case is to have an object be mutable during its initialization phase but then have it become /// immutable and converted to a normal `Arc`. /// @@ -4084,7 +4084,6 @@ impl core::error::Error for Arc { /// use std::sync::{Arc, Weak, UniqueArc}; /// /// struct Gadget { -/// #[allow(dead_code)] /// me: Weak, /// } /// @@ -4104,7 +4103,6 @@ impl core::error::Error for Arc { /// previous example, `UniqueArc` allows for more flexibility in the construction of cyclic data, /// including fallible or async constructors. #[unstable(feature = "unique_rc_arc", issue = "112566")] -#[derive(Debug)] pub struct UniqueArc< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, @@ -4119,13 +4117,248 @@ pub struct UniqueArc< } #[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl Send for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +unsafe impl Sync for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +// #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for UniqueArc { } -// Depends on A = Global -impl UniqueArc { +//#[unstable(feature = "unique_rc_arc", issue = "112566")] +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +impl, U: ?Sized> DispatchFromDyn> for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Display for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Debug for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl fmt::Pointer for UniqueArc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Pointer::fmt(&(&raw const **self), f) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl borrow::Borrow for UniqueArc { + fn borrow(&self) -> &T { + &**self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl borrow::BorrowMut for UniqueArc { + fn borrow_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl AsRef for UniqueArc { + fn as_ref(&self) -> &T { + &**self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl AsMut for UniqueArc { + fn as_mut(&mut self) -> &mut T { + &mut **self + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Unpin for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl PartialEq for UniqueArc { + /// Equality for two `UniqueArc`s. + /// + /// Two `UniqueArc`s are equal if their inner values are equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five == UniqueArc::new(5)); + /// ``` + #[inline] + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(&**self, &**other) + } + + /// Inequality for two `UniqueArc`s. + /// + /// Two `UniqueArc`s are not equal if their inner values are not equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five != UniqueArc::new(6)); + /// ``` + #[inline] + fn ne(&self, other: &Self) -> bool { + PartialEq::ne(&**self, &**other) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl PartialOrd for UniqueArc { + /// Partial comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// use std::cmp::Ordering; + /// + /// let five = UniqueArc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&UniqueArc::new(6))); + /// ``` + #[inline(always)] + fn partial_cmp(&self, other: &UniqueArc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five < UniqueArc::new(6)); + /// ``` + #[inline(always)] + fn lt(&self, other: &UniqueArc) -> bool { + **self < **other + } + + /// 'Less than or equal to' comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five <= UniqueArc::new(5)); + /// ``` + #[inline(always)] + fn le(&self, other: &UniqueArc) -> bool { + **self <= **other + } + + /// Greater-than comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five > UniqueArc::new(4)); + /// ``` + #[inline(always)] + fn gt(&self, other: &UniqueArc) -> bool { + **self > **other + } + + /// 'Greater than or equal to' comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// + /// let five = UniqueArc::new(5); + /// + /// assert!(five >= UniqueArc::new(5)); + /// ``` + #[inline(always)] + fn ge(&self, other: &UniqueArc) -> bool { + **self >= **other + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Ord for UniqueArc { + /// Comparison for two `UniqueArc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// #![feature(unique_rc_arc)] + /// use std::sync::UniqueArc; + /// use std::cmp::Ordering; + /// + /// let five = UniqueArc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&UniqueArc::new(6))); + /// ``` + #[inline] + fn cmp(&self, other: &UniqueArc) -> Ordering { + (**self).cmp(&**other) + } +} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Eq for UniqueArc {} + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +impl Hash for UniqueArc { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} + +impl UniqueArc { /// Creates a new `UniqueArc`. /// /// Weak references to this `UniqueArc` can be created with [`UniqueArc::downgrade`]. Upgrading @@ -4134,6 +4367,7 @@ impl UniqueArc { /// point to the new [`Arc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] pub fn new(value: T) -> Self { Self::new_in(value, Global) } @@ -4148,6 +4382,8 @@ impl UniqueArc { /// point to the new [`Arc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + // #[unstable(feature = "allocator_api", issue = "32838")] pub fn new_in(data: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_unique(Box::new_in( ArcInner { @@ -4172,6 +4408,7 @@ impl UniqueArc { /// Any weak references created before this method is called can now be upgraded to strong /// references. #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] pub fn into_arc(this: Self) -> Arc { let this = ManuallyDrop::new(this); @@ -4195,6 +4432,7 @@ impl UniqueArc { /// Attempting to upgrade this weak reference will fail before the `UniqueArc` has been converted /// to a [`Arc`] using [`UniqueArc::into_arc`]. #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] pub fn downgrade(this: &Self) -> Weak { // Using a relaxed ordering is alright here, as knowledge of the // original reference prevents other threads from erroneously deleting @@ -4236,10 +4474,17 @@ impl DerefMut for UniqueArc { // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we // have unique ownership and therefore it's safe to make a mutable reference because // `UniqueArc` owns the only strong reference to itself. + // We also need to be careful to only create a mutable reference to the `data` field, + // as a mutable reference to the entire `ArcInner` would assert uniqueness over the + // ref count fields too, invalidating any attempt by `Weak`s to access the ref count. unsafe { &mut (*self.ptr.as_ptr()).data } } } +#[unstable(feature = "unique_rc_arc", issue = "112566")] +// #[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for UniqueArc {} + #[unstable(feature = "unique_rc_arc", issue = "112566")] unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { fn drop(&mut self) { From eb094ed7b4c600de21d1ace851349c9c38298fa8 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 6 Mar 2025 22:15:58 +0800 Subject: [PATCH 113/333] Remove `PartialEq::ne` for `UniqueArc` --- library/alloc/src/sync.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b883f84d68eed..be581661f4ce3 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4205,25 +4205,6 @@ impl PartialEq for UniqueArc { fn eq(&self, other: &Self) -> bool { PartialEq::eq(&**self, &**other) } - - /// Inequality for two `UniqueArc`s. - /// - /// Two `UniqueArc`s are not equal if their inner values are not equal. - /// - /// # Examples - /// - /// ``` - /// #![feature(unique_rc_arc)] - /// use std::sync::UniqueArc; - /// - /// let five = UniqueArc::new(5); - /// - /// assert!(five != UniqueArc::new(6)); - /// ``` - #[inline] - fn ne(&self, other: &Self) -> bool { - PartialEq::ne(&**self, &**other) - } } #[unstable(feature = "unique_rc_arc", issue = "112566")] From ee6a1598268e07cf1fbecc6ad1c2d5a5db593fb4 Mon Sep 17 00:00:00 2001 From: Chiichen Date: Sun, 23 Mar 2025 12:34:41 +0800 Subject: [PATCH 114/333] doc: fix reference to #create-a-configtoml --- src/doc/rustc-dev-guide/src/building/prerequisites.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index f49f6bb052789..6761cabac1f14 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -38,4 +38,4 @@ incremental compilation ([see here][config]). This will make compilation take longer (especially after a rebase), but will save a ton of space from the incremental caches. -[config]: ./how-to-build-and-run.md#create-a-configtoml +[config]: ./how-to-build-and-run.md#create-a-bootstraptoml From 264e1addfd72181741188ab318f2542e86ad4d53 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:26:03 +0000 Subject: [PATCH 115/333] Rustup to rustc 1.87.0-nightly (b48576b4d 2025-03-22) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index cbed84253fbea..a6b0bf5fba1aa 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-21" +channel = "nightly-2025-03-23" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 542dbbdcfed457beb70b2133e57c312537711564 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 23 Mar 2025 17:36:31 +0000 Subject: [PATCH 116/333] Fix rustc testsuite --- scripts/setup_rust_fork.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index c2c8e625f60b5..ca6426f2ba9d3 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -46,6 +46,28 @@ llvm-tools = false std-features = ["panic-unwind", "compiler-builtins-no-f16-f128"] EOF + +cat < Date: Thu, 9 Jan 2025 18:39:40 +0100 Subject: [PATCH 117/333] fix: Check empty SIMD vector in inline asm --- .../rustc_hir_analysis/src/check/intrinsicck.rs | 8 ++++++++ tests/crashes/134334.rs | 9 --------- tests/ui/simd/empty-simd-vector-in-operand.rs | 14 ++++++++++++++ tests/ui/simd/empty-simd-vector-in-operand.stderr | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) delete mode 100644 tests/crashes/134334.rs create mode 100644 tests/ui/simd/empty-simd-vector-in-operand.rs create mode 100644 tests/ui/simd/empty-simd-vector-in-operand.stderr diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index d63165f0f1698..32a582aadc1ca 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -29,6 +29,7 @@ enum NonAsmTypeReason<'tcx> { Invalid(Ty<'tcx>), InvalidElement(DefId, Ty<'tcx>), NotSizedPtr(Ty<'tcx>), + EmptySIMDArray(Ty<'tcx>), } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { @@ -102,6 +103,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; + if fields.is_empty() { + return Err(NonAsmTypeReason::EmptySIMDArray(ty)); + } let field = &fields[FieldIdx::ZERO]; let elem_ty = field.ty(self.tcx(), args); @@ -226,6 +230,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { can be used as arguments for inline assembly", ).emit(); } + NonAsmTypeReason::EmptySIMDArray(ty) => { + let msg = format!("use of empty SIMD vector `{ty}`"); + self.infcx.dcx().struct_span_err(expr.span, msg).emit(); + } } return None; } diff --git a/tests/crashes/134334.rs b/tests/crashes/134334.rs deleted file mode 100644 index d99df7bdc1eda..0000000000000 --- a/tests/crashes/134334.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #134334 -//@ only-x86_64 - -#[repr(simd)] -struct A(); - -fn main() { - std::arch::asm!("{}", in(xmm_reg) A()); -} diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs new file mode 100644 index 0000000000000..ae21461eb95b9 --- /dev/null +++ b/tests/ui/simd/empty-simd-vector-in-operand.rs @@ -0,0 +1,14 @@ +// Regression test for issue #134224. + +#![feature(repr_simd)] + +#[repr(simd)] +struct A(); +//~^ ERROR SIMD vector cannot be empty + +fn main() { + unsafe { + std::arch::asm!("{}", in(xmm_reg) A()); + //~^ use of empty SIMD vector `A` + } +} diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr new file mode 100644 index 0000000000000..a0faf5f06d209 --- /dev/null +++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr @@ -0,0 +1,15 @@ +error[E0075]: SIMD vector cannot be empty + --> $DIR/empty-simd-vector-in-operand.rs:6:1 + | +LL | struct A(); + | ^^^^^^^^ + +error: use of empty SIMD vector `A` + --> $DIR/empty-simd-vector-in-operand.rs:11:43 + | +LL | std::arch::asm!("{}", in(xmm_reg) A()); + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0075`. From ff699ce9f55e974e9181a800203fae9d73b90e37 Mon Sep 17 00:00:00 2001 From: Hadrien Eyraud Date: Mon, 3 Feb 2025 14:16:27 +0100 Subject: [PATCH 118/333] fix: running the test only on x86_64. The test was failing on aarch64-apple-darwin. --- tests/ui/simd/empty-simd-vector-in-operand.rs | 1 + tests/ui/simd/empty-simd-vector-in-operand.stderr | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs index ae21461eb95b9..2a2a6c0737db6 100644 --- a/tests/ui/simd/empty-simd-vector-in-operand.rs +++ b/tests/ui/simd/empty-simd-vector-in-operand.rs @@ -1,4 +1,5 @@ // Regression test for issue #134224. +//@ only-x86_64 #![feature(repr_simd)] diff --git a/tests/ui/simd/empty-simd-vector-in-operand.stderr b/tests/ui/simd/empty-simd-vector-in-operand.stderr index a0faf5f06d209..7210dddd461f0 100644 --- a/tests/ui/simd/empty-simd-vector-in-operand.stderr +++ b/tests/ui/simd/empty-simd-vector-in-operand.stderr @@ -1,11 +1,11 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/empty-simd-vector-in-operand.rs:6:1 + --> $DIR/empty-simd-vector-in-operand.rs:7:1 | LL | struct A(); | ^^^^^^^^ error: use of empty SIMD vector `A` - --> $DIR/empty-simd-vector-in-operand.rs:11:43 + --> $DIR/empty-simd-vector-in-operand.rs:12:43 | LL | std::arch::asm!("{}", in(xmm_reg) A()); | ^^^ From 0b2acddf01b58ef4825b5ca68f39d9f2ac86072b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 20 Mar 2025 02:12:40 +0000 Subject: [PATCH 119/333] Update `compiler-builtins` to 0.1.152 Includes the following changes related to unordered atomics: * Remove element_unordered_atomic intrinsics [1] * Remove use of `atomic_load_unordered` and undefined behaviour [2] There are a handful of other small changes, but nothing else user-visible. [1]: https://github.com/rust-lang/compiler-builtins/pull/789 [2]: https://github.com/rust-lang/compiler-builtins/pull/790 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 754025ff49db3..34249ea483451 100644 --- a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] From de8b6beac8710f6391e1fe99f774ba99bb0f54ac Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 24 Mar 2025 10:40:03 +0200 Subject: [PATCH 120/333] add needed break --- .../src/rustdoc-internals/rustdoc-test-suite.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index c2a2e6495f82c..471dd29f74fba 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -1,6 +1,7 @@ # The `rustdoc` test suite -This page is specifically about the test suite named `rustdoc`, for other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). +This page is specifically about the test suite named `rustdoc`. +For other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.md#tests). The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. From 62ec34bf5b254a3470fe74042a0ad2a53e56baed Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 24 Mar 2025 10:41:19 +0200 Subject: [PATCH 121/333] typo --- .../rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md index 471dd29f74fba..169b95a7e1adc 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-test-suite.md @@ -5,7 +5,7 @@ For other test suites used for testing rustdoc, see [Rustdoc tests](../rustdoc.m The `rustdoc` test suite is specifically used to test the HTML output of rustdoc. -This is achived by means of `htmldocck.py`, a custom checker script that leverages [XPath]. +This is achieved by means of `htmldocck.py`, a custom checker script that leverages [XPath]. [XPath]: https://en.wikipedia.org/wiki/XPath From e06d50cf327aed841de4394b7183aa815bb3ed9e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Mar 2025 16:21:31 +0000 Subject: [PATCH 122/333] Revert "Rollup merge of #136127 - WaffleLapkin:dyn_ptr_unwrap_cast, r=compiler-errors" This reverts commit 84c2050bf63f734246572345aedca9edb2abe96e, reversing changes made to a96fa317d78c78a9de996afd317603c6970efc0d. --- compiler/rustc_hir_typeck/src/coercion.rs | 68 +-------- .../ui/cast/ptr-to-trait-obj-wrap-add-auto.rs | 36 ----- .../ptr-to-trait-obj-wrap-add-auto.stderr | 48 ------ .../ptr-to-trait-obj-wrap-different-args.rs | 36 ----- ...tr-to-trait-obj-wrap-different-args.stderr | 43 ------ ...ptr-to-trait-obj-wrap-different-regions.rs | 41 ----- ...to-trait-obj-wrap-different-regions.stderr | 140 ------------------ tests/ui/cast/ptr-to-trait-obj-wrap.rs | 32 ---- 8 files changed, 8 insertions(+), 436 deletions(-) delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr delete mode 100644 tests/ui/cast/ptr-to-trait-obj-wrap.rs diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4cbc42b99ea35..f42ca3af2b35c 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -41,8 +41,8 @@ use rustc_abi::ExternAbi; use rustc_attr_parsing::InlineAttr; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, LangItem}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; @@ -55,7 +55,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -592,63 +592,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Create an obligation for `Source: CoerceUnsized`. let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target }); - let root_obligation = Obligation::new( - self.tcx, - cause.clone(), - self.fcx.param_env, - ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]), - ); - - // If the root `Source: CoerceUnsized` obligation can't possibly hold, - // we don't have to assume that this is unsizing coercion (it will always lead to an error) - // - // However, we don't want to bail early all the time, since the unholdable obligations - // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id`), - // so we only bail if there (likely) is another way to convert the types. - if !self.infcx.predicate_may_hold(&root_obligation) { - if let Some(dyn_metadata_adt_def_id) = self.tcx.lang_items().get(LangItem::DynMetadata) - && let Some(metadata_type_def_id) = self.tcx.lang_items().get(LangItem::Metadata) - { - self.probe(|_| { - let ocx = ObligationCtxt::new(&self.infcx); - - // returns `true` if `::Metadata` is `DynMetadata<_>` - let has_dyn_trait_metadata = |ty| { - let metadata_ty: Result<_, _> = ocx.structurally_normalize_ty( - &ObligationCause::dummy(), - self.fcx.param_env, - Ty::new_alias( - self.tcx, - ty::AliasTyKind::Projection, - AliasTy::new(self.tcx, metadata_type_def_id, [ty]), - ), - ); - - metadata_ty.is_ok_and(|metadata_ty| { - metadata_ty - .ty_adt_def() - .is_some_and(|d| d.did() == dyn_metadata_adt_def_id) - }) - }; - - // If both types are raw pointers to a (wrapper over a) trait object, - // this might be a cast like `*const W -> *const dyn Trait`. - // So it's better to bail and try that. (even if the cast is not possible, for - // example due to vtables not matching, cast diagnostic will likely still be better) - // - // N.B. use `target`, not `coerce_target` (the latter is a var) - if let &ty::RawPtr(source_pointee, _) = coerce_source.kind() - && let &ty::RawPtr(target_pointee, _) = target.kind() - && has_dyn_trait_metadata(source_pointee) - && has_dyn_trait_metadata(target_pointee) - { - return Err(TypeError::Mismatch); - } - - Ok(()) - })?; - } - } // Use a FIFO queue for this custom fulfillment procedure. // @@ -657,7 +600,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // and almost never more than 3. By using a SmallVec we avoid an // allocation, at the (very small) cost of (occasionally) having to // shift subsequent elements down when removing the front element. - let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![root_obligation]; + let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new( + self.tcx, + cause, + self.fcx.param_env, + ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]) + )]; // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs deleted file mode 100644 index cfc0a97989dc1..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Combination of `ptr-to-trait-obj-wrap.rs` and `ptr-to-trait-obj-add-auto.rs`. -// -// Checks that you *can't* add auto traits to trait object in pointer casts involving wrapping said -// traits structures. - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W) -> *const (dyn A + Send) { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn unwrap_nested(a: *const W>) -> *const W { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn rewrap(a: *const W) -> *const X { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn rewrap_nested(a: *const W>) -> *const W> { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn wrap(a: *const dyn A) -> *const W { - a as _ - //~^ error: cannot add auto trait `Send` to dyn bound via pointer cast -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr deleted file mode 100644 index 42cdbc34ee827..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-add-auto.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:12:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:17:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:22:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:27:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast - --> $DIR/ptr-to-trait-obj-wrap-add-auto.rs:32:5 - | -LL | a as _ - | ^^^^^^ unsupported cast - | - = note: this could allow UB elsewhere - = help: use `transmute` if you're sure this is sound - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0804`. diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs deleted file mode 100644 index ebe7a06a7a158..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Combination of `ptr-to-trait-obj-different-args.rs` and `ptr-to-trait-obj-wrap.rs`. -// -// Checks that you *can't* change type arguments of trait objects in pointer casts involving -// wrapping said traits structures. - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W>) -> *const dyn A { - a as _ - //~^ error casting `*const W<(dyn A + 'static)>` as `*const dyn A` is invalid -} - -fn unwrap_nested(a: *const W>>) -> *const W> { - a as _ - //~^ error casting `*const W + 'static)>>` as `*const W>` is invalid -} - -fn rewrap(a: *const W>) -> *const X> { - a as _ - //~^ error: casting `*const W<(dyn A + 'static)>` as `*const X>` is invalid -} - -fn rewrap_nested(a: *const W>>) -> *const W>> { - a as _ - //~^ error: casting `*const W + 'static)>>` as `*const W>>` is invalid -} - -fn wrap(a: *const dyn A) -> *const W> { - a as _ - //~^ error: casting `*const (dyn A + 'static)` as `*const W>` is invalid -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr deleted file mode 100644 index 4f85b208d05ac..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-args.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0606]: casting `*const W<(dyn A + 'static)>` as `*const dyn A` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:12:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W + 'static)>>` as `*const W>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:17:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W<(dyn A + 'static)>` as `*const X>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:22:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const W + 'static)>>` as `*const W>>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:27:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error[E0606]: casting `*const (dyn A + 'static)` as `*const W>` is invalid - --> $DIR/ptr-to-trait-obj-wrap-different-args.rs:32:5 - | -LL | a as _ - | ^^^^^^ - | - = note: the trait objects may have different vtables - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs deleted file mode 100644 index b0941277d01d3..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Combination of `ptr-to-trait-obj-different-regions-misc.rs` and `ptr-to-trait-obj-wrap.rs`. -// -// Checks that you *can't* change lifetime arguments of trait objects in pointer casts involving -// wrapping said traits structures. - -trait A<'a> {} - -struct W(T); -struct X(T); - -fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - a as _ - //~^ error - //~| error -} - -fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - a as _ - //~^ error - //~| error -} - -fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - a as _ - //~^ error: lifetime may not live long enough - //~| error: lifetime may not live long enough -} - -fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr b/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr deleted file mode 100644 index 17a0ca3c34fc8..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap-different-regions.stderr +++ /dev/null @@ -1,140 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5 - | -LL | fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:12:5 - | -LL | fn unwrap<'a, 'b>(a: *const W>) -> *const dyn A<'b> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5 - | -LL | fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:18:5 - | -LL | fn unwrap_nested<'a, 'b>(a: *const W>>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5 - | -LL | fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:24:5 - | -LL | fn rewrap<'a, 'b>(a: *const W>) -> *const X> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5 - | -LL | fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:30:5 - | -LL | fn rewrap_nested<'a, 'b>(a: *const W>>) -> *const W>> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5 - | -LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-wrap-different-regions.rs:36:5 - | -LL | fn wrap<'a, 'b>(a: *const dyn A<'a>) -> *const W> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | a as _ - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -help: `'b` and `'a` must be the same: replace one with the other - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 10 previous errors - diff --git a/tests/ui/cast/ptr-to-trait-obj-wrap.rs b/tests/ui/cast/ptr-to-trait-obj-wrap.rs deleted file mode 100644 index 9809ea80f95cf..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-wrap.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Checks that various casts of pointers to trait objects wrapped in structures -// work. Note that the metadata doesn't change when a DST is wrapped in a -// structure, so these casts *are* fine. -// -//@ check-pass - -trait A {} - -struct W(T); -struct X(T); - -fn unwrap(a: *const W) -> *const dyn A { - a as _ -} - -fn unwrap_nested(a: *const W>) -> *const W { - a as _ -} - -fn rewrap(a: *const W) -> *const X { - a as _ -} - -fn rewrap_nested(a: *const W>) -> *const W> { - a as _ -} - -fn wrap(a: *const dyn A) -> *const W { - a as _ -} - -fn main() {} From 1aed58ceb6fc2bdbd4d323fb18fd6d7c9ee21630 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 22 Mar 2025 22:29:23 +0100 Subject: [PATCH 123/333] Emit `unused_attributes` for `#[inline]` on exported functions I saw someone post a code sample that contained these two attributes, which immediately made me suspicious. My suspicions were confirmed when I did a small test and checked the compiler source code to confirm that in these cases, `#[inline]` is indeed ignored (because you can't exactly `LocalCopy`an unmangled symbol since that would lead to duplicate symbols, and doing a mix of an unmangled `GloballyShared` and mangled `LocalCopy` instantiation is too complicated for our current instatiation mode logic, which I don't want to change right now). So instead, emit the usual unused attribute lint with a message saying that the attribute is ignored in this position. I think this is not 100% true, since I expect LLVM `inlinehint` to still be applied to such a function, but that's not why people use this attribute, they use it for the `LocalCopy` instantiation mode, where it doesn't work. --- .../src/middle/codegen_fn_attrs.rs | 2 ++ compiler/rustc_middle/src/mir/mono.rs | 1 + compiler/rustc_passes/messages.ftl | 4 +++ compiler/rustc_passes/src/check_attr.rs | 17 ++++++++++ compiler/rustc_passes/src/errors.rs | 5 +++ tests/ui/lint/inline-exported.rs | 30 ++++++++++++++++++ tests/ui/lint/inline-exported.stderr | 31 +++++++++++++++++++ .../target-feature/invalid-attribute.stderr | 12 +++---- 8 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint/inline-exported.rs create mode 100644 tests/ui/lint/inline-exported.stderr diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 311bc60c3cd39..a33b1fe283b82 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -172,6 +172,8 @@ impl CodegenFnAttrs { /// * `#[no_mangle]` is present /// * `#[export_name(...)]` is present /// * `#[linkage]` is present + /// + /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint. pub fn contains_extern_indicator(&self) -> bool { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some() diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 58d5c94d03326..2aa31761178f4 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -117,6 +117,7 @@ impl<'tcx> MonoItem<'tcx> { // If the function is #[naked] or contains any other attribute that requires exactly-once // instantiation: + // We emit an unused_attributes lint for this case, which should be kept in sync if possible. let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id()); if codegen_fn_attrs.contains_extern_indicator() || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index b65430c348027..22631cc96d289 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -383,6 +383,10 @@ passes_inline_ignored_constants = .warn = {-passes_previously_accepted} .note = {-passes_see_issue(issue: "65833")} +passes_inline_ignored_for_exported = + `#[inline]` is ignored on externally exported functions + .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + passes_inline_ignored_function_prototype = `#[inline]` is ignored on function prototypes diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5ada289cc2090..5a76f7c586d4b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -445,6 +445,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } } + + // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported. + if let Some(did) = hir_id.as_owner() + && self.tcx.def_kind(did).has_codegen_attrs() + && !matches!(attr.meta_item_list().as_deref(), Some([item]) if item.has_name(sym::never)) + { + let attrs = self.tcx.codegen_fn_attrs(did); + // Not checking naked as `#[inline]` is forbidden for naked functions anyways. + if attrs.contains_extern_indicator() { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span(), + errors::InlineIgnoredForExported {}, + ); + } + } } /// Checks that `#[coverage(..)]` is applied to a function/closure/method, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9bb9b2353dc86..b282828a8ae91 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1435,6 +1435,11 @@ pub(crate) struct OnlyHasEffectOn { pub target_name: String, } +#[derive(LintDiagnostic)] +#[diag(passes_inline_ignored_for_exported)] +#[help] +pub(crate) struct InlineIgnoredForExported {} + #[derive(Diagnostic)] #[diag(passes_object_lifetime_err)] pub(crate) struct ObjectLifetimeErr { diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs new file mode 100644 index 0000000000000..69e322ef513ae --- /dev/null +++ b/tests/ui/lint/inline-exported.rs @@ -0,0 +1,30 @@ +//! Ensure the unused_attributes lint fires for externally exported functions with `#[inline]`, +//! because `#[inline]` is ignored for such functions. + +#![crate_type = "lib"] + +#![feature(linkage)] +#![feature(naked_functions)] +#![deny(unused_attributes)] + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[no_mangle] +fn no_mangle() {} + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[export_name = "export_name"] +fn export_name() {} + +#[inline] +//~^ ERROR: `#[inline]` is ignored on externally exported functions +#[linkage = "external"] +fn external_linkage() {} + +#[inline] +fn normal() {} + +#[inline] +#[linkage = "internal"] // not exported +fn internal_linkage() {} diff --git a/tests/ui/lint/inline-exported.stderr b/tests/ui/lint/inline-exported.stderr new file mode 100644 index 0000000000000..dcf63cc4090e4 --- /dev/null +++ b/tests/ui/lint/inline-exported.stderr @@ -0,0 +1,31 @@ +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:10:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` +note: the lint level is defined here + --> $DIR/inline-exported.rs:8:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:15:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + +error: `#[inline]` is ignored on externally exported functions + --> $DIR/inline-exported.rs:20:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index dc8a53041640e..05ae49d6b0ddb 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -98,6 +98,12 @@ LL | LL | trait Baz {} | ------------ not a function definition +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/invalid-attribute.rs:69:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + error: attribute should be applied to a function definition --> $DIR/invalid-attribute.rs:74:1 | @@ -163,12 +169,6 @@ error: malformed `target_feature` attribute input LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:69:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - error[E0046]: not all trait items implemented, missing: `foo` --> $DIR/invalid-attribute.rs:81:1 | From c123adf860b008f703b325d013e7c7c0cc707d56 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 15:57:07 -0500 Subject: [PATCH 124/333] rustdoc js: add nonundef and use it to remove a ts-expect-error --- src/librustdoc/html/static/js/rustdoc.d.ts | 4 +++- src/librustdoc/html/static/js/search.js | 7 +++---- src/librustdoc/html/static/js/storage.js | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index e94c6beabea39..e2ebb1391837a 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -6,8 +6,10 @@ declare global { /** Map from crate name to directory structure, for source view */ declare var srcIndex: Map; - /** Defined and documented in `main.js` */ + /** Defined and documented in `storage.js` */ declare function nonnull(x: T|null, msg: string|undefined); + /** Defined and documented in `storage.js` */ + declare function nonundef(x: T|undefined, msg: string|undefined); interface Window { /** Make the current theme easy to find */ currentTheme: HTMLLinkElement|null; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index c275127997ab1..decb4807e884e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar */ +/* global addClass, getNakedUrl, getSettingValue, getVar, nonnull, nonundef */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -338,9 +338,8 @@ function getFilteredNextElem(query, parserState, elems, isInGenerics) { // The type filter doesn't count as an element since it's a modifier. const typeFilterElem = elems.pop(); checkExtraTypeFilterCharacters(start, parserState); - // typeFilterElem is not null. If it was, the elems.length check would have fired. - // @ts-expect-error - parserState.typeFilter = typeFilterElem.normalizedPathLast; + // typeFilterElem is not undefined. If it was, the elems.length check would have fired. + parserState.typeFilter = nonundef(typeFilterElem).normalizedPathLast; parserState.pos += 1; parserState.totalElems -= 1; query.literalSearch = false; diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 748d2ef33c32c..7611372689478 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -43,6 +43,28 @@ function nonnull(x, msg) { } } +/** + * Assert that the passed value is not undefined, then return it. + * + * Takes an optional error message argument. + * + * Must be defined in this file, as it is loaded before all others. + * + * @template T + * @param {T|undefined} x + * @param {string=} msg + * @returns T + */ +// used in other files, not yet used in this one. +// eslint-disable-next-line no-unused-vars +function nonundef(x, msg) { + if (x === undefined) { + throw (msg || "unexpected null value!"); + } else { + return x; + } +} + /** * Get a configuration value. If it's not set, get the default. * From ccd95ac7fde43d6a0380895086efca3a75e1ac35 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 16:19:05 -0500 Subject: [PATCH 125/333] search.js: improve typechecking by avoiding Map.has --- src/librustdoc/html/static/js/search.js | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index decb4807e884e..a8c6193a4c135 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1310,10 +1310,9 @@ class NameTrie { let sste; if (substart >= 2) { const tail = name.substring(substart - 2, substart + 1); - if (tailTable.has(tail)) { - // it's not undefined - // @ts-expect-error - sste = tailTable.get(tail); + const entry = tailTable.get(tail); + if (entry !== undefined) { + sste = entry; } else { sste = []; tailTable.set(tail, sste); @@ -1337,10 +1336,9 @@ class NameTrie { new Lev1TParametricDescription(name.length); this.searchLev(name, 0, levParams, results); const tail = name.substring(0, 3); - if (tailTable.has(tail)) { - // it's not undefined - // @ts-expect-error - for (const entry of tailTable.get(tail)) { + const list = tailTable.get(tail); + if (list !== undefined) { + for (const entry of list) { entry.searchSubstringPrefix(name, 3, results); } } @@ -1599,10 +1597,8 @@ class DocSearch { return null; } - if (this.typeNameIdMap.has(name)) { - /** @type {{id: number, assocOnly: boolean}} */ - // @ts-expect-error - const obj = this.typeNameIdMap.get(name); + const obj = this.typeNameIdMap.get(name); + if (obj !== undefined) { obj.assocOnly = !!(isAssocType && obj.assocOnly); return obj.id; } else { @@ -2145,7 +2141,6 @@ class DocSearch { const name = elem[1]; let path = null; if (elem.length > 2 && elem[2] !== null) { - // @ts-expect-error path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; lastPath = path; } From e9a5470aabcf9dbfd8c463b3156332d75a3881ea Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 16:56:55 -0500 Subject: [PATCH 126/333] search.js: refactor handling of rawPaths in buildIndex --- src/librustdoc/html/static/js/search.js | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index a8c6193a4c135..bac174869f57d 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2077,7 +2077,8 @@ class DocSearch { descIndex += 1; } - // a String of one character item type codes + // see `RawSearchIndexCrate` in `rustdoc.d.ts` for a more + // up to date description of these fields const itemTypes = crateCorpus.t; // an array of (String) item names const itemNames = crateCorpus.n; @@ -2094,8 +2095,6 @@ class DocSearch { const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop); // a map Number, string for impl disambiguators const implDisambiguator = new Map(crateCorpus.b); - // an array of [(Number) item type, - // (String) name] const rawPaths = crateCorpus.p; const aliases = crateCorpus.a; // an array of [(Number) item index, @@ -2134,29 +2133,32 @@ class DocSearch { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = rawPaths.length; - let lastPath = itemPaths.get(0); + const lastPathU = itemPaths.get(0); + let lastPath = lastPathU === undefined ? null : lastPathU; for (let i = 0; i < len; ++i) { const elem = rawPaths[i]; const ty = elem[0]; const name = elem[1]; - let path = null; - if (elem.length > 2 && elem[2] !== null) { - path = itemPaths.has(elem[2]) ? itemPaths.get(elem[2]) : lastPath; - lastPath = path; - } - let exactPath = elem.length > 3 && elem[3] !== null ? - // @ts-expect-error - itemPaths.get(elem[3]) : - path; + /** + * @param {2|3} idx + * @param {string|null} if_null + * @param {string|null} if_not_found + * @returns {string|null} + */ + const elemPath = (idx, if_null, if_not_found) => { + if (elem.length > idx && elem[idx] !== undefined) { + const p = itemPaths.get(elem[idx]); + if (p !== undefined) { + return p; + } + return if_not_found; + } + return if_null; + }; + const path = elemPath(2, lastPath, null); + const exactPath = elemPath(3, path, path); const unboxFlag = elem.length > 4 && !!elem[4]; - if (path === undefined) { - path = null; - } - if (exactPath === undefined) { - exactPath = null; - } - lowercasePaths.push({ ty, name: name.toLowerCase(), path, exactPath, unboxFlag }); paths[i] = { ty, name, path, exactPath, unboxFlag }; } From 49bf6ca79eb7379e367578cba910d1e1cbacc7d1 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:05:35 -0500 Subject: [PATCH 127/333] search.js: add undef2null and eliminate more @ts-expect-error --- src/librustdoc/html/static/js/search.js | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index bac174869f57d..1817d91af79a6 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -33,6 +33,20 @@ function onEachBtwn(arr, func, funcBtwn) { } } +/** + * Convert any `undefined` to `null`. + * + * @template T + * @param {T|undefined} x + * @returns {T|null} + */ +function undef2null(x) { + if (x !== undefined) { + return x; + } + return null; +} + // ==================== Core search logic begin ==================== // This mapping table should match the discriminants of // `rustdoc::formats::item_type::ItemType` type in Rust. @@ -2133,8 +2147,7 @@ class DocSearch { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = rawPaths.length; - const lastPathU = itemPaths.get(0); - let lastPath = lastPathU === undefined ? null : lastPathU; + let lastPath = undef2null(itemPaths.get(0)); for (let i = 0; i < len; ++i) { const elem = rawPaths[i]; const ty = elem[0]; @@ -2192,12 +2205,11 @@ class DocSearch { } const name = itemNames[i] === "" ? lastName : itemNames[i]; const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase(); - /** @type {string} */ - // @ts-expect-error - const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath; - const paramNames = itemParamNames.has(i) ? - // @ts-expect-error - itemParamNames.get(i).split(",") : + const pathU = itemPaths.get(i); + const path = pathU !== undefined ? pathU : lastPath; + const paramNameString = itemParamNames.get(i); + const paramNames = paramNameString !== undefined ? + paramNameString.split(",") : lastParamNames; const type = itemFunctionDecoder.next(); if (type !== null) { @@ -2239,8 +2251,7 @@ class DocSearch { word, normalizedName, bitIndex, - implDisambiguator: implDisambiguator.has(i) ? - implDisambiguator.get(i) : null, + implDisambiguator: undef2null(implDisambiguator.get(i)), }; this.nameTrie.insert(normalizedName, id, this.tailTable); id += 1; From 1af16cd135dd4e62f8e68abfb0587b57eb16ce6e Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:31:39 -0500 Subject: [PATCH 128/333] search.js(query parser): rethrow error if it isn't a string array only errors that are string arrays are intended to be shown to the user, other errors are bugs, and will be shown in the console as usual. --- src/librustdoc/html/static/js/search.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1817d91af79a6..15bb3816f0b59 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2489,9 +2489,13 @@ class DocSearch { } } catch (err) { query = newParsedQuery(userQuery); - // is string list - // @ts-expect-error - query.error = err; + if (Array.isArray(err) && err.every((elem) => typeof elem == 'string')) { + query.error = err; + } else { + // rethrow the error if it isn't a string array + throw err; + } + return query; } if (!query.literalSearch) { From 8af647c04dbd300518f85619c9e9ce7a94d558c4 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 17:36:16 -0500 Subject: [PATCH 129/333] search.js: remove another Map.has() and @ts-expect-error --- src/librustdoc/html/static/js/search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 15bb3816f0b59..2317f157bb930 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2583,9 +2583,9 @@ class DocSearch { if ((elem.id === null && parsedQuery.totalElems > 1 && elem.typeFilter === -1 && elem.generics.length === 0 && elem.bindings.size === 0) || elem.typeFilter === TY_GENERIC) { - if (genericSymbols.has(elem.normalizedPathLast)) { - // @ts-expect-error - elem.id = genericSymbols.get(elem.normalizedPathLast); + const id = genericSymbols.get(elem.normalizedPathLast); + if (id !== undefined) { + elem.id = id; } else { elem.id = -(genericSymbols.size + 1); genericSymbols.set(elem.normalizedPathLast, elem.id); From 714be45b974ae16a010503587e4628bc72fd107b Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:11:43 -0500 Subject: [PATCH 130/333] search.js: refactor transformResults --- src/librustdoc/html/static/js/rustdoc.d.ts | 12 +++++++-- src/librustdoc/html/static/js/search.js | 29 +++++++++++++--------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index e2ebb1391837a..91a58fab86eff 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -257,12 +257,20 @@ declare namespace rustdoc { ty: number, type?: FunctionSearchType, paramNames?: string[], - displayType: Promise>>|null, - displayTypeMappedNames: Promise]>>|null, + displayTypeSignature: Promise | null, item: Row, dontValidate?: boolean, } + /** + * output of `formatDisplayTypeSignature` + */ + interface DisplayTypeSignature { + type: Array, + mappedNames: Map, + whereClause: Map>, + } + /** * A pair of [inputs, outputs], or 0 for null. This is stored in the search index. * The JavaScript deserializes this into FunctionSearchType. diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 2317f157bb930..bd09631d487b4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2777,15 +2777,28 @@ class DocSearch { for (const result of results) { if (result.id !== -1) { const res = buildHrefAndPath(this.searchIndex[result.id]); + // many of these properties don't strictly need to be + // copied over, but copying them over satisfies tsc, + // and hopefully plays nice with the shape optimization + // of the browser engine. + /** @type {rustdoc.ResultObject} */ const obj = Object.assign({ + parent: result.parent, + type: result.type, dist: result.dist, + path_dist: result.path_dist, + index: result.index, + desc: result.desc, + item: result.item, displayPath: pathSplitter(res[0]), + fullPath: "", + href: "", + displayTypeSignature: null, }, this.searchIndex[result.id]); // To be sure than it some items aren't considered as duplicate. - // @ts-expect-error - obj.fullPath = res[2] + "|" + obj.ty; - // @ts-expect-error + obj.fullPath = res[2] + "|" + obj.ty + if (duplicates.has(obj.fullPath)) { continue; } @@ -2798,18 +2811,15 @@ class DocSearch { if (duplicates.has(res[2] + "|" + TY_IMPORT)) { continue; } - // @ts-expect-error duplicates.add(obj.fullPath); duplicates.add(res[2]); if (typeInfo !== null) { - // @ts-expect-error obj.displayTypeSignature = // @ts-expect-error this.formatDisplayTypeSignature(obj, typeInfo); } - // @ts-expect-error obj.href = res[1]; out.push(obj); if (out.length >= MAX_RESULTS) { @@ -2817,7 +2827,6 @@ class DocSearch { } } } - // @ts-expect-error return out; }; @@ -2830,11 +2839,7 @@ class DocSearch { * * @param {rustdoc.ResultObject} obj * @param {"sig"|"elems"|"returned"|null} typeInfo - * @returns {Promise<{ - * "type": Array, - * "mappedNames": Map, - * "whereClause": Map>, - * }>} + * @returns {Promise} */ this.formatDisplayTypeSignature = async(obj, typeInfo) => { const objType = obj.type; From ca514c1a13b419606fe051ec897a25a07dc7aa26 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:20:51 -0500 Subject: [PATCH 131/333] search.js: fix signature of pushText --- src/librustdoc/html/static/js/search.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index bd09631d487b4..f714f361d4b99 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2901,7 +2901,7 @@ class DocSearch { const whereClause = new Map(); const fnParamNames = obj.paramNames || []; - // @ts-expect-error + /** @type {string[]} */ const queryParamNames = []; /** * Recursively writes a map of IDs to query generic names, @@ -2934,7 +2934,7 @@ class DocSearch { * index 2 is not highlighted, etc. * * @param {{name?: string, highlighted?: boolean}} fnType - input - * @param {[string]} result + * @param {string[]} result */ const pushText = (fnType, result) => { // If !!(result.length % 2) == false, then pushing a new slot starts an even @@ -2946,7 +2946,6 @@ class DocSearch { // needs coerced to a boolean. if (!!(result.length % 2) === !!fnType.highlighted) { result.push(""); - // @ts-expect-error } else if (result.length === 0 && !!fnType.highlighted) { result.push(""); result.push(""); @@ -2960,7 +2959,7 @@ class DocSearch { * or a trait bound on Fn, FnMut, or FnOnce. * * @param {rustdoc.HighlightedFunctionType} fnType - input - * @param {[string]} result + * @param {string[]} result */ const writeHof = (fnType, result) => { const hofOutput = fnType.bindings.get(this.typeNameIdOfOutput) || []; @@ -3000,7 +2999,7 @@ class DocSearch { * Returns `false` if the supplied type isn't special. * * @param {rustdoc.HighlightedFunctionType} fnType - * @param {[string]} result + * @param {string[]} result */ const writeSpecialPrimitive = (fnType, result) => { if (fnType.id === this.typeNameIdOfArray || fnType.id === this.typeNameIdOfSlice || @@ -3047,7 +3046,7 @@ class DocSearch { * updating the where clause and generic type param map. * * @param {rustdoc.HighlightedFunctionType} fnType - * @param {[string]} result + * @param {string[]} result */ const writeFn = (fnType, result) => { if (fnType.id !== null && fnType.id < 0) { @@ -3065,7 +3064,6 @@ class DocSearch { for (const [queryId, fnId] of mgens) { if (fnId === fnType.id) { mappedNames.set( - // @ts-expect-error queryParamNames[-1 - queryId], fnParamNames[-1 - fnType.id], ); @@ -3080,7 +3078,6 @@ class DocSearch { const where = []; onEachBtwn( fnType.generics, - // @ts-expect-error nested => writeFn(nested, where), // @ts-expect-error () => pushText({ name: " + ", highlighted: false }, where), @@ -3115,7 +3112,6 @@ class DocSearch { // shown in the where clause and name mapping output, but is // redundant in this spot for (const value of values) { - // @ts-expect-error writeFn(value, []); } return true; From 7f141985ff337926639db092b2ecb5b05a763cd7 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:24:07 -0500 Subject: [PATCH 132/333] search.js: use @type instead of @ts-expect-error --- src/librustdoc/html/static/js/search.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index f714f361d4b99..5dda3d34e104c 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3153,26 +3153,22 @@ class DocSearch { } } }; - // @ts-expect-error + /** @type {string[]} */ const type = []; onEachBtwn( fnInputs, - // @ts-expect-error fnType => writeFn(fnType, type), // @ts-expect-error () => pushText({ name: ", ", highlighted: false }, type), ); - // @ts-expect-error pushText({ name: " -> ", highlighted: false }, type); onEachBtwn( fnOutput, - // @ts-expect-error fnType => writeFn(fnType, type), // @ts-expect-error () => pushText({ name: ", ", highlighted: false }, type), ); - // @ts-expect-error return {type, mappedNames, whereClause}; }; From 3245e7b069b52d16e82065f05c7c968fab7b3f2b Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:27:42 -0500 Subject: [PATCH 133/333] search.js: fix return type of unifyFunctionTypes --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 5dda3d34e104c..ba672ffb7a415 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3483,8 +3483,7 @@ class DocSearch { } } } - // @ts-expect-error - return false; + return null; } // Multiple element recursive case From 4a00a8449e3603823f5d0c5d01afc4425ed4b448 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:29:21 -0500 Subject: [PATCH 134/333] search.js: give type to unifiedGenericsMgens --- src/librustdoc/html/static/js/search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index ba672ffb7a415..1ba34027a0af2 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3539,7 +3539,7 @@ class DocSearch { } /** @type {rustdoc.HighlightedFunctionType[]|null} */ let unifiedGenerics = []; - // @ts-expect-error + /** @type {null|Map} */ let unifiedGenericsMgens = null; /** @type {rustdoc.HighlightedFunctionType[]|null} */ const passesUnification = unifyFunctionTypes( @@ -3593,7 +3593,6 @@ class DocSearch { // @ts-expect-error queryElem.bindings.get(k), whereClause, - // @ts-expect-error unifiedGenericsMgens, solutionCb, unboxingDepth, From 523f413a738822d0312ea82ea69b21b6900af68a Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 18:40:06 -0500 Subject: [PATCH 135/333] search.js: give type annotation to newSolutions --- src/librustdoc/html/static/js/search.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1ba34027a0af2..a54104c3809ea 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3990,7 +3990,7 @@ class DocSearch { } const fnTypeBindings = fnType.bindings.get(name); mgensSolutionSet = mgensSolutionSet.flatMap(mgens => { - // @ts-expect-error + /** @type{Array | null>} */ const newSolutions = []; unifyFunctionTypes( // @ts-expect-error @@ -4006,7 +4006,6 @@ class DocSearch { }, unboxingDepth, ); - // @ts-expect-error return newSolutions; }); } @@ -4254,6 +4253,7 @@ class DocSearch { return false; } + // this does not yet have a type in `rustdoc.d.ts`. // @ts-expect-error function createAliasFromItem(item) { return { From 1b8b09a01d6b0acf24b070cd997bff6cb739dfec Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 24 Mar 2025 19:11:55 -0500 Subject: [PATCH 136/333] search.js: fix whitespace --- src/librustdoc/html/static/js/search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index a54104c3809ea..651d12bb2e907 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2798,7 +2798,7 @@ class DocSearch { // To be sure than it some items aren't considered as duplicate. obj.fullPath = res[2] + "|" + obj.ty - + if (duplicates.has(obj.fullPath)) { continue; } From 8524a7c4b7faab823f7e03d012b365bb05b82654 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 25 Mar 2025 10:31:05 +0000 Subject: [PATCH 137/333] Fix UWP reparse point check --- library/std/src/sys/fs/windows.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 06bba019393a5..15727c996837b 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -547,7 +547,7 @@ impl File { ))?; attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); - if attr.file_type().is_reparse_point() { + if attr.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed(); cvt(c::GetFileInformationByHandleEx( self.handle.as_raw_handle(), From 1875905a94f72e043eb356efe30d40fe165fea20 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Mar 2025 17:14:58 +0000 Subject: [PATCH 138/333] Rustup to rustc 1.87.0-nightly (f8c27dfe1 2025-03-24) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index a6b0bf5fba1aa..ab650c05d3572 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-23" +channel = "nightly-2025-03-25" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 328846c6eb650580f93addb687a8f5fd863bd892 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 139/333] Rename `is_like_osx` to `is_like_darwin` --- .../rustc_codegen_cranelift/src/abi/mod.rs | 2 +- .../rustc_codegen_cranelift/src/constant.rs | 2 +- .../src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 6 +++--- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- compiler/rustc_codegen_llvm/src/va_arg.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 12 +++++------ compiler/rustc_codegen_ssa/src/back/linker.rs | 20 +++++++++---------- .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/back/mod.rs | 2 +- compiler/rustc_codegen_ssa/src/back/rpath.rs | 4 ++-- .../rustc_codegen_ssa/src/back/rpath/tests.rs | 6 +++--- compiler/rustc_codegen_ssa/src/back/write.rs | 4 ++-- .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 6 +++--- compiler/rustc_target/src/asm/aarch64.rs | 2 +- compiler/rustc_target/src/asm/arm.rs | 2 +- compiler/rustc_target/src/callconv/mod.rs | 2 +- compiler/rustc_target/src/callconv/x86.rs | 2 +- .../rustc_target/src/spec/base/apple/mod.rs | 2 +- compiler/rustc_target/src/spec/json.rs | 4 ++-- compiler/rustc_target/src/spec/mod.rs | 16 +++++++-------- 24 files changed, 54 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index e8076ce77abcf..ddd119e0c6108 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -641,7 +641,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( .flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()), ); - if fx.tcx.sess.target.is_like_osx && fx.tcx.sess.target.arch == "aarch64" { + if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == "aarch64" { // Add any padding arguments needed for Apple AArch64. // There's no need to pad the argument list unless variadic arguments are actually being // passed. diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index bcc70f4567fbd..c8527c3a57dfe 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -391,7 +391,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant data.set_align(alloc.align.bytes()); if let Some(section_name) = section_name { - let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let (segment_name, section_name) = if tcx.sess.target.is_like_darwin { // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp let mut parts = section_name.as_str().split(','); let Some(segment_name) = parts.next() else { diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index bba6567774d7e..286e02b986b3c 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -58,7 +58,7 @@ impl DebugContext { // FIXME this should be configurable // macOS doesn't seem to support DWARF > 3 // 5 version is required for md5 file hash - version: if tcx.sess.target.is_like_osx { + version: if tcx.sess.target.is_like_darwin { 3 } else { // FIXME change to version 5 once the gdb and lldb shipping with the latest debian diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c514b7a428bc6..0dc0a91829886 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.options.is_like_osx { + if self.tcx.sess.target.options.is_like_darwin { // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bead4c82a8120..bf6138142b649 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1024,7 +1024,7 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: } pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static CStr { - if cgcx.target_is_like_osx { + if cgcx.target_is_like_darwin { c"__LLVM,__bitcode" } else if cgcx.target_is_like_aix { c".ipa" @@ -1077,7 +1077,7 @@ unsafe fn embed_bitcode( // and COFF we emit the sections using module level inline assembly for that // reason (see issue #90326 for historical background). unsafe { - if cgcx.target_is_like_osx + if cgcx.target_is_like_darwin || cgcx.target_is_like_aix || cgcx.target_arch == "wasm32" || cgcx.target_arch == "wasm64" @@ -1096,7 +1096,7 @@ unsafe fn embed_bitcode( let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline"); llvm::set_initializer(llglobal, llconst); - let section = if cgcx.target_is_like_osx { + let section = if cgcx.target_is_like_darwin { c"__LLVM,__cmdline" } else if cgcx.target_is_like_aix { c".info" diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index a64627eaf5986..fdf62a08065c2 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -120,7 +120,7 @@ impl CodegenCx<'_, '_> { } // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { + if self.tcx.sess.target.is_like_darwin { return false; } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 8baa69cefe1e2..c216f0f4a09d0 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -399,7 +399,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 - "aarch64" if target.is_like_osx => { + "aarch64" if target.is_like_darwin => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true) } "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 74597f6263d4f..9fa26a33f233e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1012,7 +1012,7 @@ fn link_natively( // On macOS the external `dsymutil` tool is used to create the packed // debug information. Note that this will read debug information from // the objects on the filesystem which we'll clean up later. - SplitDebuginfo::Packed if sess.target.is_like_osx => { + SplitDebuginfo::Packed if sess.target.is_like_darwin => { let prog = Command::new("dsymutil").arg(out_filename).output(); match prog { Ok(prog) => { @@ -1043,7 +1043,7 @@ fn link_natively( let strip = sess.opts.cg.strip; - if sess.target.is_like_osx { + if sess.target.is_like_darwin { let stripcmd = "rust-objcopy"; match (strip, crate_type) { (Strip::Debuginfo, _) => { @@ -1241,7 +1241,7 @@ fn add_sanitizer_libraries( // Everywhere else the runtimes are currently distributed as static // libraries which should be linked to executables only. if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) - && !(sess.target.is_like_osx || sess.target.is_like_msvc) + && !(sess.target.is_like_darwin || sess.target.is_like_msvc) { return; } @@ -1294,7 +1294,7 @@ fn link_sanitizer_runtime( let channel = option_env!("CFG_RELEASE_CHANNEL").map(|channel| format!("-{channel}")).unwrap_or_default(); - if sess.target.is_like_osx { + if sess.target.is_like_darwin { // On Apple platforms, the sanitizer is always built as a dylib, and // LLVM will link to `@rpath/*.dylib`, so we need to specify an // rpath to the library as well (the rpath should be absolute, see @@ -2182,7 +2182,7 @@ fn add_rpath_args( let rpath_config = RPathConfig { libs: &*libs, out_filename: out_filename.to_path_buf(), - is_like_osx: sess.target.is_like_osx, + is_like_darwin: sess.target.is_like_darwin, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config)); @@ -3044,7 +3044,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool /// - The deployment target. /// - The SDK version. fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { return; } let LinkerFlavor::Darwin(cc, _) = flavor else { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f5e0c1bce9c1..33440361c6f0c 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -373,7 +373,7 @@ impl<'a> GccLinker<'a> { // * On OSX they have their own linker, not binutils' // * For WebAssembly the only functional linker is LLD, which doesn't // support hint flags - !self.sess.target.is_like_osx && !self.sess.target.is_like_wasm + !self.sess.target.is_like_darwin && !self.sess.target.is_like_wasm } // Some platforms take hints about whether a library is static or dynamic. @@ -425,7 +425,7 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { if self.is_cc() { // `-dynamiclib` makes `cc` pass `-dylib` to the linker. self.cc_arg("-dynamiclib"); @@ -470,7 +470,7 @@ impl<'a> GccLinker<'a> { fn with_as_needed(&mut self, as_needed: bool, f: impl FnOnce(&mut Self)) { if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. @@ -485,7 +485,7 @@ impl<'a> GccLinker<'a> { f(self); if !as_needed { - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // See above FIXME comment } else if self.is_gnu && !self.sess.target.is_like_windows { self.link_arg("--as-needed"); @@ -618,7 +618,7 @@ impl<'a> Linker for GccLinker<'a> { let colon = if verbatim && self.is_gnu { ":" } else { "" }; if !whole_archive { self.link_or_cc_arg(format!("-l{colon}{name}")); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.link_arg("-force_load"); @@ -634,7 +634,7 @@ impl<'a> Linker for GccLinker<'a> { self.hint_static(); if !whole_archive { self.link_or_cc_arg(path); - } else if self.sess.target.is_like_osx { + } else if self.sess.target.is_like_darwin { self.link_arg("-force_load").link_arg(path); } else { self.link_arg("--whole-archive").link_arg(path).link_arg("--no-whole-archive"); @@ -669,7 +669,7 @@ impl<'a> Linker for GccLinker<'a> { // -dead_strip can't be part of the pre_link_args because it's also used // for partial linking when using multiple codegen units (-r). So we // insert it here. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-dead_strip"); // If we're building a dylib, we don't use --gc-sections because LLVM @@ -727,7 +727,7 @@ impl<'a> Linker for GccLinker<'a> { fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { // MacOS linker doesn't support stripping symbols directly anymore. - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { return; } @@ -794,7 +794,7 @@ impl<'a> Linker for GccLinker<'a> { debug!("EXPORTED SYMBOLS:"); - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { // Write a plain, newline-separated list of symbols let res: io::Result<()> = try { let mut f = File::create_buffered(&path)?; @@ -840,7 +840,7 @@ impl<'a> Linker for GccLinker<'a> { } } - if self.sess.target.is_like_osx { + if self.sess.target.is_like_darwin { self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 68b453ff42425..83a9ea0603a2f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -214,7 +214,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Cow<'_, str> { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess)) .into() } else { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index d633cc98ac87e..7bb8979e8820f 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -9,7 +9,7 @@ use tracing::debug; pub(super) struct RPathConfig<'a> { pub libs: &'a [&'a Path], pub out_filename: PathBuf, - pub is_like_osx: bool, + pub is_like_darwin: bool, pub linker_is_gnu: bool, } @@ -63,7 +63,7 @@ fn get_rpaths_relative_to_output(config: &RPathConfig<'_>) -> Vec { fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsString { // Mac doesn't appear to support $ORIGIN - let prefix = if config.is_like_osx { "@loader_path" } else { "$ORIGIN" }; + let prefix = if config.is_like_darwin { "@loader_path" } else { "$ORIGIN" }; // Strip filenames let lib = lib.parent().unwrap(); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index f1a30105c5908..ab8fbedb81297 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -28,7 +28,7 @@ fn test_rpath_relative() { if cfg!(target_os = "macos") { let config = &mut RPathConfig { libs: &[], - is_like_osx: true, + is_like_darwin: true, linker_is_gnu: false, out_filename: PathBuf::from("bin/rustc"), }; @@ -38,7 +38,7 @@ fn test_rpath_relative() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("bin/rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; let res = get_rpath_relative_to_output(config, Path::new("lib/libstd.so")); @@ -51,7 +51,7 @@ fn test_rpath_relative_issue_119571() { let config = &mut RPathConfig { libs: &[], out_filename: PathBuf::from("rustc"), - is_like_osx: false, + is_like_darwin: false, linker_is_gnu: true, }; // Should not panic when out_filename only contains filename. diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 216a18e72edff..d16ab2798da50 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -352,7 +352,7 @@ pub struct CodegenContext { pub is_pe_coff: bool, pub target_can_use_split_dwarf: bool, pub target_arch: String, - pub target_is_like_osx: bool, + pub target_is_like_darwin: bool, pub target_is_like_aix: bool, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, @@ -1216,7 +1216,7 @@ fn start_executing_work( is_pe_coff: tcx.sess.target.is_like_windows, target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(), target_arch: tcx.sess.target.arch.to_string(), - target_is_like_osx: tcx.sess.target.is_like_osx, + target_is_like_darwin: tcx.sess.target.is_like_darwin, target_is_like_aix: tcx.sess.target.is_like_aix, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d16d4ed228389..4a0c3bb170a31 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -213,7 +213,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // somewhat, and is subject to change in the future (which // is a good thing, because this would ideally be a bit // more firmed up). - let is_like_elf = !(tcx.sess.target.is_like_osx + let is_like_elf = !(tcx.sess.target.is_like_darwin || tcx.sess.target.is_like_windows || tcx.sess.target.is_like_wasm); codegen_fn_attrs.flags |= if is_like_elf { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 37755e7d61db1..30755a2e86ee5 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -779,7 +779,7 @@ fn print_crate_info( } } DeploymentTarget => { - if sess.target.is_like_osx { + if sess.target.is_like_darwin { println_info!( "{}={}", apple::deployment_target_env_var(&sess.target.os), diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1671b7e06b0af..0249678664a8d 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -73,7 +73,7 @@ pub fn walk_native_lib_search_dirs( || sess.target.os == "linux" || sess.target.os == "fuchsia" || sess.target.is_like_aix - || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() + || sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty() { f(&sess.target_tlib_path.dir, false)?; } @@ -258,7 +258,7 @@ impl<'tcx> Collector<'tcx> { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => { - if !sess.target.is_like_osx { + if !sess.target.is_like_darwin { sess.dcx().emit_err(errors::LinkFrameworkApple { span }); } NativeLibKind::Framework { as_needed: None } @@ -532,7 +532,7 @@ impl<'tcx> Collector<'tcx> { let mut renames = FxHashSet::default(); for lib in &self.tcx.sess.opts.libs { if let NativeLibKind::Framework { .. } = lib.kind - && !self.tcx.sess.target.is_like_osx + && !self.tcx.sess.target.is_like_darwin { // Cannot check this when parsing options because the target is not yet available. self.tcx.dcx().emit_err(errors::LibFrameworkApple); diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index cdccb3e5d728e..43a8d9ca119df 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -78,7 +78,7 @@ pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet< target.os == "android" || target.os == "fuchsia" || target.env == "ohos" - || target.is_like_osx + || target.is_like_darwin || target.is_like_windows || target_features.contains(&sym::reserve_x18) } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index ff0cbddecf78b..7fea10ff067bf 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -68,7 +68,7 @@ impl ArmInlineAsmRegClass { // This uses the same logic as useR7AsFramePointer in LLVM fn frame_pointer_is_r7(target_features: &FxIndexSet, target: &Target) -> bool { - target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) + target.is_like_darwin || (!target.is_like_windows && target_features.contains(&sym::thumb_mode)) } fn frame_pointer_r11( diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 6d0ee3c7ee58a..4a55a25baf420 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -670,7 +670,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } }, "aarch64" | "arm64ec" => { - let kind = if cx.target_spec().is_like_osx { + let kind = if cx.target_spec().is_like_darwin { aarch64::AbiKind::DarwinPCS } else if cx.target_spec().is_like_windows { aarch64::AbiKind::Win64 diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 6f112b4940057..ba3c140621129 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -104,7 +104,7 @@ where let byval_align = if arg.layout.align.abi < align_4 { // (1.) align_4 - } else if t.is_like_osx && contains_vector(cx, arg.layout) { + } else if t.is_like_darwin && contains_vector(cx, arg.layout) { // (3.) align_16 } else { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 66c85146c2944..fd0e47b55aaa0 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -115,7 +115,7 @@ pub(crate) fn base( function_sections: false, dynamic_linking: true, families: cvs!["unix"], - is_like_osx: true, + is_like_darwin: true, binary_format: BinaryFormat::MachO, // LLVM notes that macOS 10.11+ and iOS 9+ default // to v4, so we do the same. diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index 134405f3630e7..23b21860c43eb 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -592,7 +592,7 @@ impl Target { key!(families, target_families); key!(abi_return_struct_as_int, bool); key!(is_like_aix, bool); - key!(is_like_osx, bool); + key!(is_like_darwin, bool); key!(is_like_solaris, bool); key!(is_like_windows, bool); key!(is_like_msvc, bool); @@ -770,7 +770,7 @@ impl ToJson for Target { target_option_val!(families, "target-family"); target_option_val!(abi_return_struct_as_int); target_option_val!(is_like_aix); - target_option_val!(is_like_osx); + target_option_val!(is_like_darwin); target_option_val!(is_like_solaris); target_option_val!(is_like_windows); target_option_val!(is_like_msvc); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 263646d8347be..c7c62cd5a1970 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -81,7 +81,7 @@ pub enum Lld { /// of classes that we call "linker flavors". /// /// Technically, it's not even necessary, we can nearly always infer the flavor from linker name -/// and target properties like `is_like_windows`/`is_like_osx`/etc. However, the PRs originally +/// and target properties like `is_like_windows`/`is_like_darwin`/etc. However, the PRs originally /// introducing `-Clinker-flavor` (#40018 and friends) were aiming to reduce this kind of inference /// and provide something certain and explicitly specified instead, and that design goal is still /// relevant now. @@ -2403,7 +2403,7 @@ pub struct TargetOptions { /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. /// Also indicates whether to use Apple-specific ABI changes, such as extending function /// parameters to 32-bits. - pub is_like_osx: bool, + pub is_like_darwin: bool, /// Whether the target toolchain is like Solaris's. /// Only useful for compiling against Illumos/Solaris, /// as they have a different set of linker flags. Defaults to false. @@ -2697,7 +2697,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati impl TargetOptions { pub fn supports_comdat(&self) -> bool { // XCOFF and MachO don't support COMDAT. - !self.is_like_aix && !self.is_like_osx + !self.is_like_aix && !self.is_like_darwin } } @@ -2801,7 +2801,7 @@ impl Default for TargetOptions { families: cvs![], abi_return_struct_as_int: false, is_like_aix: false, - is_like_osx: false, + is_like_darwin: false, is_like_solaris: false, is_like_windows: false, is_like_msvc: false, @@ -3067,9 +3067,9 @@ impl Target { } check_eq!( - self.is_like_osx, + self.is_like_darwin, self.vendor == "apple", - "`is_like_osx` must be set if and only if `vendor` is `apple`" + "`is_like_darwin` must be set if and only if `vendor` is `apple`" ); check_eq!( self.is_like_solaris, @@ -3095,9 +3095,9 @@ impl Target { // Check that default linker flavor is compatible with some other key properties. check_eq!( - self.is_like_osx, + self.is_like_darwin, matches!(self.linker_flavor, LinkerFlavor::Darwin(..)), - "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set" + "`linker_flavor` must be `darwin` if and only if `is_like_darwin` is set" ); check_eq!( self.is_like_msvc, From a7bafc0afc3dba988a7bf85198c493b20523eaa0 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 26 Mar 2025 15:23:47 +0100 Subject: [PATCH 140/333] Change the syntax of the internal `weak!` macro Change the syntax to include parameter names and a trailing semicolon. Motivation: - Mirror the `syscall!` macro. - Allow rustfmt to format it (when wrapped in parentheses). - For better documentation (having the parameter names available in the source code is a bit nicer). - Allow future improvements to this macro where we can sometimes use the symbol directly when it's statically known to be available. --- library/std/src/sys/fs/unix.rs | 16 +++--- library/std/src/sys/pal/unix/fd.rs | 52 ++++++++++++++----- library/std/src/sys/pal/unix/kernel_copy.rs | 16 +++--- .../std/src/sys/pal/unix/stack_overflow.rs | 30 ++++++++--- library/std/src/sys/pal/unix/thread.rs | 13 +++-- library/std/src/sys/pal/unix/time.rs | 7 ++- library/std/src/sys/pal/unix/weak.rs | 40 ++++++++------ library/std/src/sys/process/unix/unix.rs | 42 ++++++++------- library/std/src/sys/random/linux.rs | 8 +-- 9 files changed, 144 insertions(+), 80 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7c3ed8029f7dd..60e6559fa6b99 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -155,15 +155,15 @@ cfg_has_statx! {{ enum STATX_STATE{ Unknown = 0, Present, Unavailable } static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8); - syscall! { + syscall!( fn statx( fd: c_int, pathname: *const c_char, flags: c_int, mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } + statxbuf: *mut libc::statx, + ) -> c_int; + ); let statx_availability = STATX_SAVED_STATE.load(Ordering::Relaxed); if statx_availability == STATX_STATE::Unavailable as u8 { @@ -1540,7 +1540,9 @@ impl File { let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; // futimens requires Android API level 19 cvt(unsafe { - weak!(fn futimens(c_int, *const libc::timespec) -> c_int); + weak!( + fn futimens(fd: c_int, times: *const libc::timespec) -> c_int; + ); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), None => return Err(io::const_error!( @@ -1556,7 +1558,9 @@ impl File { use crate::sys::{time::__timespec64, weak::weak}; // Added in glibc 2.34 - weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int); + weak!( + fn __futimens64(fd: c_int, times: *const __timespec64) -> c_int; + ); if let Some(futimens64) = __futimens64.get() { let to_timespec = |time: Option| time.map(|time| time.t.to_timespec64()) diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index f03c440e30e12..2ec8d01c13f46 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -232,14 +232,14 @@ impl FileDesc { // implementation if `preadv` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::syscall! { + super::weak::syscall!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { preadv( @@ -257,7 +257,14 @@ impl FileDesc { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv64.get() { Some(preadv) => { @@ -286,7 +293,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn preadv( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match preadv.get() { Some(preadv) => { @@ -428,14 +442,14 @@ impl FileDesc { // implementation if `pwritev` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::syscall! { + super::weak::syscall!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, n_iovec: libc::c_int, - offset: off64_t - ) -> isize - } + offset: off64_t, + ) -> isize; + ); let ret = cvt(unsafe { pwritev( @@ -450,7 +464,14 @@ impl FileDesc { #[cfg(all(target_os = "android", target_pointer_width = "32"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev64( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev64.get() { Some(pwritev) => { @@ -479,7 +500,14 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); + super::weak::weak!( + fn pwritev( + fd: libc::c_int, + iovec: *const libc::iovec, + n_iovec: libc::c_int, + offset: off64_t, + ) -> isize; + ); match pwritev.get() { Some(pwritev) => { diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index bbf29f3252341..d42a7e2a7fc51 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -604,16 +604,16 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> _ => true, }; - syscall! { + syscall!( fn copy_file_range( fd_in: libc::c_int, off_in: *mut libc::loff_t, fd_out: libc::c_int, off_out: *mut libc::loff_t, len: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); fn probe_copy_file_range_support() -> u8 { // In some cases, we cannot determine availability from the first @@ -727,16 +727,16 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> // Android builds use feature level 14, but the libc wrapper for splice is // gated on feature level 21+, so we have to invoke the syscall directly. #[cfg(target_os = "android")] - syscall! { + syscall!( fn splice( srcfd: libc::c_int, src_offset: *const i64, dstfd: libc::c_int, dst_offset: *const i64, len: libc::size_t, - flags: libc::c_int - ) -> libc::ssize_t - } + flags: libc::c_int, + ) -> libc::ssize_t; + ); #[cfg(target_os = "linux")] use libc::splice; diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 4bd0cedd44ccb..34b3948e3f671 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -424,18 +424,32 @@ mod imp { let pages = PAGES.get_or_init(|| { use crate::sys::weak::dlsym; - dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int); + dlsym!( + fn sysctlbyname( + name: *const libc::c_char, + oldp: *mut libc::c_void, + oldlenp: *mut libc::size_t, + newp: *const libc::c_void, + newlen: libc::size_t, + ) -> libc::c_int; + ); let mut guard: usize = 0; let mut size = size_of_val(&guard); let oid = c"security.bsd.stack_guard_page"; match sysctlbyname.get() { - Some(fcn) if unsafe { - fcn(oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0) == 0 - } => guard, + Some(fcn) + if unsafe { + fcn( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) == 0 + } => + { + guard + } _ => 1, } }); diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index bb34c2fabe559..9078dd1c23166 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -193,11 +193,12 @@ impl Thread { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn set_name(name: &CStr) { - weak! { + weak!( fn pthread_setname_np( - libc::pthread_t, *const libc::c_char - ) -> libc::c_int - } + thread: libc::pthread_t, + name: *const libc::c_char, + ) -> libc::c_int; + ); if let Some(f) = pthread_setname_np.get() { #[cfg(target_os = "nto")] @@ -762,7 +763,9 @@ unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628) // We shouldn't really be using such an internal symbol, but there's currently // no other way to account for the TLS size. - dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); + dlsym!( + fn __pthread_get_minstack(attr: *const libc::pthread_attr_t) -> libc::size_t; + ); match __pthread_get_minstack.get() { None => libc::PTHREAD_STACK_MIN, diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index c0a3044660b7e..b8469b1681f03 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -123,7 +123,12 @@ impl Timespec { // __clock_gettime64 was added to 32-bit arches in glibc 2.34, // and it handles both vDSO calls and ENOSYS fallbacks itself. - weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int); + weak!( + fn __clock_gettime64( + clockid: libc::clockid_t, + tp: *mut __timespec64, + ) -> libc::c_int; + ); if let Some(clock_gettime64) = __clock_gettime64.get() { let mut t = MaybeUninit::uninit(); diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index ce3f66a83748b..e7f4e005cc48c 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -29,7 +29,7 @@ use crate::{mem, ptr}; // We can use true weak linkage on ELF targets. #[cfg(all(unix, not(target_vendor = "apple")))] pub(crate) macro weak { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( let ref $name: ExternWeak $ret> = { unsafe extern "C" { #[linkage = "extern_weak"] @@ -62,10 +62,16 @@ impl ExternWeak { } pub(crate) macro dlsym { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + dlsym!( + #[link_name = stringify!($name)] + fn $name($($param : $t),*) -> $ret; + ); ), - (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( + ( + #[link_name = $sym:expr] + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( static DLSYM: DlsymWeak $ret> = DlsymWeak::new(concat!($sym, '\0')); let $name = &DLSYM; @@ -143,15 +149,15 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( // FIXME(#115199): Rust currently omits weak function definitions // and its metadata from LLVM IR. #[no_sanitize(cfi)] - unsafe fn $name($($arg_name: $t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { super::os::set_errno(libc::ENOSYS); -1 @@ -162,16 +168,18 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - weak! { fn $name($($t),*) -> $ret } + ( + fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty; + ) => ( + unsafe fn $name($($param: $t),*) -> $ret { + weak!(fn $name($($param: $t),*) -> $ret;); // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` // interposition, but if it's not found just use a raw syscall. if let Some(fun) = $name.get() { - fun($($arg_name),*) + fun($($param),*) } else { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } ) @@ -179,9 +187,9 @@ pub(crate) macro syscall { #[cfg(any(target_os = "linux", target_os = "android"))] pub(crate) macro raw_syscall { - (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( - unsafe fn $name($($arg_name:$t),*) -> $ret { - libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret + (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( + unsafe fn $name($($param: $t),*) -> $ret { + libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } ) } diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 42542f81b6545..191a09c8da913 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -461,18 +461,20 @@ impl Command { if #[cfg(target_os = "linux")] { use crate::sys::weak::weak; - weak! { + weak!( fn pidfd_spawnp( - *mut libc::c_int, - *const libc::c_char, - *const libc::posix_spawn_file_actions_t, - *const libc::posix_spawnattr_t, - *const *mut libc::c_char, - *const *mut libc::c_char - ) -> libc::c_int - } + pidfd: *mut libc::c_int, + path: *const libc::c_char, + file_actions: *const libc::posix_spawn_file_actions_t, + attrp: *const libc::posix_spawnattr_t, + argv: *const *mut libc::c_char, + envp: *const *mut libc::c_char, + ) -> libc::c_int; + ); - weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int } + weak!( + fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int; + ); static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0); const UNKNOWN: u8 = 0; @@ -593,19 +595,19 @@ impl Command { // https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addchdir.html. // The _np version is more widely available, though, so try that first. - weak! { + weak!( fn posix_spawn_file_actions_addchdir_np( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); - weak! { + weak!( fn posix_spawn_file_actions_addchdir( - *mut libc::posix_spawn_file_actions_t, - *const libc::c_char - ) -> libc::c_int - } + file_actions: *mut libc::posix_spawn_file_actions_t, + path: *const libc::c_char, + ) -> libc::c_int; + ); posix_spawn_file_actions_addchdir_np .get() diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index e3cb79285cd15..c0591ec0c1527 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -73,13 +73,13 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { // A weak symbol allows interposition, e.g. for perf measurements that want to // disable randomness for consistency. Otherwise, we'll try a raw syscall. // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28) - syscall! { + syscall!( fn getrandom( buffer: *mut libc::c_void, length: libc::size_t, - flags: libc::c_uint - ) -> libc::ssize_t - } + flags: libc::c_uint, + ) -> libc::ssize_t; + ); static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true); static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true); From a86e0dacbce4e9bc624ef1ebd71a575c9dd0aa01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:08:03 +0100 Subject: [PATCH 141/333] doc(hir::Place): clarify that places aren't always place expressions --- compiler/rustc_middle/src/hir/place.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 316ad80eb9857..60ce8544aa0ed 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -53,7 +53,10 @@ pub struct Projection<'tcx> { pub kind: ProjectionKind, } -/// A `Place` represents how a value is located in memory. +/// A `Place` represents how a value is located in memory. This does not +/// always correspond to a syntactic place expression. For example, when +/// processing a pattern, a `Place` can be used to refer to the sub-value +/// currently being inspected. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] @@ -67,7 +70,10 @@ pub struct Place<'tcx> { pub projections: Vec>, } -/// A `PlaceWithHirId` represents how a value is located in memory. +/// A `PlaceWithHirId` represents how a value is located in memory. This does not +/// always correspond to a syntactic place expression. For example, when +/// processing a pattern, a `Place` can be used to refer to the sub-value +/// currently being inspected. /// /// This is an HIR version of [`rustc_middle::mir::Place`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] From 376c88ee6fb910fa32ac8966788e9b8e3569a74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:41:10 +0100 Subject: [PATCH 142/333] ExprUseVisitor: add clarifying doc comments --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c71a5ea8b9761..1b007200549f9 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1,6 +1,9 @@ //! A different sort of visitor for walking fn bodies. Unlike the //! normal visitor, which just walks the entire body in one shot, the //! `ExprUseVisitor` determines how expressions are being used. +//! +//! In the compiler, this is only used for upvar inference, but there +//! are many uses within clippy. use std::cell::{Ref, RefCell}; use std::ops::Deref; @@ -35,11 +38,8 @@ pub trait Delegate<'tcx> { /// The value found at `place` is moved, depending /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`. /// - /// Use of a `Copy` type in a ByValue context is considered a use - /// by `ImmBorrow` and `borrow` is called instead. This is because - /// a shared borrow is the "minimum access" that would be needed - /// to perform a copy. - /// + /// If the value is `Copy`, [`copy`][Self::copy] is called instead, which + /// by default falls back to [`borrow`][Self::borrow]. /// /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic @@ -73,6 +73,10 @@ pub trait Delegate<'tcx> { /// The value found at `place` is being copied. /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details). + /// + /// If an implementation is not provided, use of a `Copy` type in a ByValue context is instead + /// considered a use by `ImmBorrow` and `borrow` is called instead. This is because a shared + /// borrow is the "minimum access" that would be needed to perform a copy. fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default // we treat a copy of `x` as a borrow of `x`. @@ -141,6 +145,8 @@ impl<'tcx, D: Delegate<'tcx>> Delegate<'tcx> for &mut D { } } +/// This trait makes `ExprUseVisitor` usable with both [`FnCtxt`] +/// and [`LateContext`], depending on where in the compiler it is used. pub trait TypeInformationCtxt<'tcx> { type TypeckResults<'a>: Deref> where @@ -268,9 +274,9 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } } -/// The ExprUseVisitor type +/// A visitor that reports how each expression is being used. /// -/// This is the code that actually walks the tree. +/// See [module-level docs][self] and [`Delegate`] for details. pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> { cx: Cx, /// We use a `RefCell` here so that delegates can mutate themselves, but we can @@ -1285,7 +1291,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.pat_ty_unadjusted(pat) } - /// Like `TypeckResults::pat_ty`, but ignores implicit `&` patterns. + /// Like [`Self::pat_ty_adjusted`], but ignores implicit `&` patterns. fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> Result, Cx::Error> { let base_ty = self.node_ty(pat.hir_id)?; trace!(?base_ty); From aab12930f5b71489f4c27db9d45897a2563a407e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 03:49:46 +0100 Subject: [PATCH 143/333] ExprUseVisitor: error -> bug in helper names A name like "report_error" suggests that the error in question might be user facing. Use "bug" to make it clear that the error in question will be an ICE. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 1b007200549f9..58bac159f37da 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -160,7 +160,7 @@ pub trait TypeInformationCtxt<'tcx> { fn try_structurally_resolve_type(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; - fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error; + fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error; fn error_reported_in_ty(&self, ty: Ty<'tcx>) -> Result<(), Self::Error>; @@ -195,7 +195,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> { (**self).try_structurally_resolve_type(sp, ty) } - fn report_error(&self, span: Span, msg: impl ToString) -> Self::Error { + fn report_bug(&self, span: Span, msg: impl ToString) -> Self::Error { self.dcx().span_delayed_bug(span, msg.to_string()) } @@ -245,7 +245,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { t } - fn report_error(&self, span: Span, msg: impl ToString) -> ! { + fn report_bug(&self, span: Span, msg: impl ToString) -> ! { span_bug!(span, "{}", msg.to_string()) } @@ -1218,7 +1218,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference /// tied to `x`. The type of `x'` will be a borrowed pointer. impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> { - fn resolve_type_vars_or_error( + fn resolve_type_vars_or_bug( &self, id: HirId, ty: Option>, @@ -1228,10 +1228,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty = self.cx.resolve_vars_if_possible(ty); self.cx.error_reported_in_ty(ty)?; if ty.is_ty_var() { - debug!("resolve_type_vars_or_error: infer var from {:?}", ty); + debug!("resolve_type_vars_or_bug: infer var from {:?}", ty); Err(self .cx - .report_error(self.cx.tcx().hir().span(id), "encountered type variable")) + .report_bug(self.cx.tcx().hir().span(id), "encountered type variable")) } else { Ok(ty) } @@ -1248,15 +1248,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } fn node_ty(&self, hir_id: HirId) -> Result, Cx::Error> { - self.resolve_type_vars_or_error(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) + self.resolve_type_vars_or_bug(hir_id, self.cx.typeck_results().node_type_opt(hir_id)) } fn expr_ty(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_error(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) + self.resolve_type_vars_or_bug(expr.hir_id, self.cx.typeck_results().expr_ty_opt(expr)) } fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Result, Cx::Error> { - self.resolve_type_vars_or_error( + self.resolve_type_vars_or_bug( expr.hir_id, self.cx.typeck_results().expr_ty_adjusted_opt(expr), ) @@ -1321,7 +1321,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx debug!("By-ref binding of non-derefable type"); Err(self .cx - .report_error(pat.span, "by-ref binding of non-derefable type")) + .report_bug(pat.span, "by-ref binding of non-derefable type")) } } } else { @@ -1610,7 +1610,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Some(ty) => ty, None => { debug!("explicit deref of non-derefable type: {:?}", base_curr_ty); - return Err(self.cx.report_error( + return Err(self.cx.report_bug( self.cx.tcx().hir().span(node), "explicit deref of non-derefable type", )); @@ -1635,7 +1635,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty::Adt(adt_def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() else { return Err(self .cx - .report_error(span, "struct or tuple struct pattern not applied to an ADT")); + .report_bug(span, "struct or tuple struct pattern not applied to an ADT")); }; match res { @@ -1681,7 +1681,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let ty = self.cx.typeck_results().node_type(pat_hir_id); match self.cx.try_structurally_resolve_type(span, ty).kind() { ty::Tuple(args) => Ok(args.len()), - _ => Err(self.cx.report_error(span, "tuple pattern not applied to a tuple")), + _ => Err(self.cx.report_bug(span, "tuple pattern not applied to a tuple")), } } @@ -1860,7 +1860,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(self .cx - .report_error(pat.span, "explicit index of non-indexable type")); + .report_bug(pat.span, "explicit index of non-indexable type")); }; let elt_place = self.cat_projection( pat.hir_id, From f16195382c93e2aac65028618a6d506501229632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Feb 2025 10:25:44 +0100 Subject: [PATCH 144/333] ExprUseVisitor: remove leftover mentions of mem-categorization In #124902, mem-categorization got merged into ExprUseVisitor itself. Adjust the comments that have become misleading or confusing following this change. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 63 ++++--------------- compiler/rustc_hir_typeck/src/upvar.rs | 10 +-- 2 files changed, 16 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 58bac159f37da..806604677fe0b 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -867,7 +867,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// Walks the autoref `autoref` applied to the autoderef'd - /// `expr`. `base_place` is the mem-categorized form of `expr` + /// `expr`. `base_place` is `expr` represented as a place, /// after all relevant autoderefs have occurred. fn walk_autoref( &self, @@ -1170,53 +1170,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } -/// The job of the categorization methods is to analyze an expression to -/// determine what kind of memory is used in evaluating it (for example, -/// where dereferences occur and what kind of pointer is dereferenced; -/// whether the memory is mutable, etc.). +/// The job of the methods whose name starts with `cat_` is to analyze +/// expressions and construct the corresponding [`Place`]s. The `cat` +/// stands for "categorize", this is a leftover from long ago when +/// places were called "categorizations". /// -/// Categorization effectively transforms all of our expressions into -/// expressions of the following forms (the actual enum has many more -/// possibilities, naturally, but they are all variants of these base -/// forms): -/// ```ignore (not-rust) -/// E = rvalue // some computed rvalue -/// | x // address of a local variable or argument -/// | *E // deref of a ptr -/// | E.comp // access to an interior component -/// ``` -/// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an -/// address where the result is to be found. If Expr is a place, then this -/// is the address of the place. If `Expr` is an rvalue, this is the address of -/// some temporary spot in memory where the result is stored. -/// -/// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)` -/// as follows: -/// -/// - `cat`: what kind of expression was this? This is a subset of the -/// full expression forms which only includes those that we care about -/// for the purpose of the analysis. -/// - `mutbl`: mutability of the address `A`. -/// - `ty`: the type of data found at the address `A`. -/// -/// The resulting categorization tree differs somewhat from the expressions -/// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is -/// decomposed into two operations: a dereference to reach the array data and -/// then an index to jump forward to the relevant item. -/// -/// ## By-reference upvars -/// -/// One part of the codegen which may be non-obvious is that we translate -/// closure upvars into the dereference of a borrowed pointer; this more closely -/// resembles the runtime codegen. So, for example, if we had: -/// -/// let mut x = 3; -/// let y = 5; -/// let inc = || x += y; -/// -/// Then when we categorize `x` (*within* the closure) we would yield a -/// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference -/// tied to `x`. The type of `x'` will be a borrowed pointer. +/// Note that a [`Place`] differs somewhat from the expression itself. For +/// example, auto-derefs are explicit. Also, an index `a[b]` is decomposed into +/// two operations: a dereference to reach the array data and then an index to +/// jump forward to the relevant item. impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D> { fn resolve_type_vars_or_bug( &self, @@ -1239,10 +1201,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx None => { // FIXME: We shouldn't be relying on the infcx being tainted. self.cx.tainted_by_errors()?; - bug!( - "no type for node {} in mem_categorization", - self.cx.tcx().hir_id_to_string(id) - ); + bug!("no type for node {} in ExprUseVisitor", self.cx.tcx().hir_id_to_string(id)); } } } @@ -1517,7 +1476,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } - def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def), + def => span_bug!(span, "unexpected definition in ExprUseVisitor: {:?}", def), } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index fc98a603dd852..d07bfade15708 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -18,12 +18,12 @@ //! from there). //! //! The fact that we are inferring borrow kinds as we go results in a -//! semi-hacky interaction with mem-categorization. In particular, -//! mem-categorization will query the current borrow kind as it -//! categorizes, and we'll return the *current* value, but this may get +//! semi-hacky interaction with the way `ExprUseVisitor` is computing +//! `Place`s. In particular, it will query the current borrow kind as it +//! goes, and we'll return the *current* value, but this may get //! adjusted later. Therefore, in this module, we generally ignore the -//! borrow kind (and derived mutabilities) that are returned from -//! mem-categorization, since they may be inaccurate. (Another option +//! borrow kind (and derived mutabilities) that `ExprUseVisitor` returns +//! within `Place`s, since they may be inaccurate. (Another option //! would be to use a unification scheme, where instead of returning a //! concrete borrow kind like `ty::ImmBorrow`, we return a //! `ty::InferBorrow(upvar_id)` or something like that, but this would From 908504ec2865186b2e2963e07d24b8849ba828e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 26 Mar 2025 16:22:26 +0100 Subject: [PATCH 145/333] ExprUseVisitor: use tracing::instrument as appropriate Replace debug! calls that output a worse version of what #[instrument] does. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 806604677fe0b..6fb289235de96 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::infer::InferCtxtExt; -use tracing::{debug, trace}; +use tracing::{debug, instrument, trace}; use crate::fn_ctxt::FnCtxt; @@ -320,9 +320,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } + #[instrument(skip(self), level = "debug")] fn consume_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { - debug!("delegate_consume(place_with_id={:?})", place_with_id); - if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) { self.delegate.borrow_mut().copy(place_with_id, diag_expr_id); } else { @@ -330,9 +329,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } } + #[instrument(skip(self), level = "debug")] pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) { - debug!("delegate_consume_or_clone(place_with_id={:?})", place_with_id); - // `x.use` will do one of the following // * if it implements `Copy`, it will be a copy // * if it implements `UseCloned`, it will be a call to `clone` @@ -357,18 +355,16 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } // FIXME: It's suspicious that this is public; clippy should probably use `walk_expr`. + #[instrument(skip(self), level = "debug")] pub fn consume_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("consume_expr(expr={:?})", expr); - let place_with_id = self.cat_expr(expr)?; self.consume_or_copy(&place_with_id, place_with_id.hir_id); self.walk_expr(expr)?; Ok(()) } + #[instrument(skip(self), level = "debug")] pub fn consume_or_clone_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("consume_or_clone_expr(expr={:?})", expr); - let place_with_id = self.cat_expr(expr)?; self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id); self.walk_expr(expr)?; @@ -382,17 +378,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } + #[instrument(skip(self), level = "debug")] fn borrow_expr(&self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) -> Result<(), Cx::Error> { - debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); - let place_with_id = self.cat_expr(expr)?; self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk); self.walk_expr(expr) } + #[instrument(skip(self), level = "debug")] pub fn walk_expr(&self, expr: &hir::Expr<'_>) -> Result<(), Cx::Error> { - debug!("walk_expr(expr={:?})", expr); - self.walk_adjustment(expr)?; match expr.kind { @@ -739,9 +733,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// Indicates that the value of `blk` will be consumed, meaning either copied or moved /// depending on its type. + #[instrument(skip(self), level = "debug")] fn walk_block(&self, blk: &hir::Block<'_>) -> Result<(), Cx::Error> { - debug!("walk_block(blk.hir_id={})", blk.hir_id); - for stmt in blk.stmts { self.walk_stmt(stmt)?; } @@ -948,14 +941,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// The core driver for walking a pattern + #[instrument(skip(self), level = "debug")] fn walk_pat( &self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, has_guard: bool, ) -> Result<(), Cx::Error> { - debug!("walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})", discr_place, pat, has_guard); - let tcx = self.cx.tcx(); self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { match pat.kind { @@ -1048,6 +1040,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing /// closure as the DefId. + #[instrument(skip(self), level = "debug")] fn walk_captures(&self, closure_expr: &hir::Closure<'_>) -> Result<(), Cx::Error> { fn upvar_is_local_variable( upvars: Option<&FxIndexMap>, @@ -1057,8 +1050,6 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx upvars.map(|upvars| !upvars.contains_key(&upvar_id)).unwrap_or(body_owner_is_closure) } - debug!("walk_captures({:?})", closure_expr); - let tcx = self.cx.tcx(); let closure_def_id = closure_expr.def_id; // For purposes of this function, coroutine and closures are equivalent. From 0a05677d22825f66018361c3b6a55148bfc85650 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 26 Mar 2025 06:37:56 -0700 Subject: [PATCH 146/333] `lower_pat_expr`: use the pattern's type instead of the literal's This allows us to remove the field `treat_byte_string_as_slice` from `TypeckResults`, since the pattern's type contains everything necessary to get the correct lowering for byte string literal patterns. This leaves the implementation of `string_deref_patterns` broken, to be fixed in the next commit. --- compiler/rustc_hir_typeck/src/pat.rs | 4 --- compiler/rustc_hir_typeck/src/writeback.rs | 3 -- .../rustc_middle/src/ty/typeck_results.rs | 7 ----- .../src/thir/pattern/const_to_pat.rs | 31 ++----------------- .../rustc_mir_build/src/thir/pattern/mod.rs | 17 +++++++--- 5 files changed, 15 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f1f956779c94f..5a2cead33deff 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -632,10 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let tcx = self.tcx; trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); - self.typeck_results - .borrow_mut() - .treat_byte_string_as_slice - .insert(lt.hir_id.local_id); pat_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_slice(tcx, tcx.types.u8)); } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index b63c0b6ab7e09..109023c513e35 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -81,9 +81,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports); wbcx.typeck_results.used_trait_imports = used_trait_imports; - wbcx.typeck_results.treat_byte_string_as_slice = - mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice); - debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results); self.tcx.arena.alloc(wbcx.typeck_results) diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 06054e22e7601..3d3f4e2773a2d 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -197,12 +197,6 @@ pub struct TypeckResults<'tcx> { /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>, - /// We sometimes treat byte string literals (which are of type `&[u8; N]`) - /// as `&[u8]`, depending on the pattern in which they are used. - /// This hashset records all instances where we behave - /// like this to allow `const_to_pat` to reliably handle this situation. - pub treat_byte_string_as_slice: ItemLocalSet, - /// Contains the data for evaluating the effect of feature `capture_disjoint_fields` /// on closure size. pub closure_size_eval: LocalDefIdMap>, @@ -237,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> { closure_fake_reads: Default::default(), rvalue_scopes: Default::default(), coroutine_stalled_predicates: Default::default(), - treat_byte_string_as_slice: Default::default(), closure_size_eval: Default::default(), offset_of_data: Default::default(), } 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 667d59d858e3a..372453688d242 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 @@ -58,25 +58,13 @@ struct ConstToPat<'tcx> { span: Span, id: hir::HirId, - treat_byte_string_as_slice: bool, - c: ty::Const<'tcx>, } impl<'tcx> ConstToPat<'tcx> { fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self { trace!(?pat_ctxt.typeck_results.hir_owner); - ConstToPat { - tcx: pat_ctxt.tcx, - typing_env: pat_ctxt.typing_env, - span, - id, - treat_byte_string_as_slice: pat_ctxt - .typeck_results - .treat_byte_string_as_slice - .contains(&id.local_id), - c, - } + ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c } } fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { @@ -108,8 +96,6 @@ impl<'tcx> ConstToPat<'tcx> { uv: ty::UnevaluatedConst<'tcx>, ty: Ty<'tcx>, ) -> Box> { - trace!(self.treat_byte_string_as_slice); - // It's not *technically* correct to be revealing opaque types here as borrowcheck has // not run yet. However, CTFE itself uses `TypingMode::PostAnalysis` unconditionally even // during typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821). @@ -307,21 +293,8 @@ impl<'tcx> ConstToPat<'tcx> { ty, ); } else { - // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when - // matching against references, you can only use byte string literals. - // The typechecker has a special case for byte string literals, by treating them - // as slices. This means we turn `&[T; N]` constants into slice patterns, which - // has no negative effects on pattern matching, even if we're actually matching on - // arrays. - let pointee_ty = match *pointee_ty.kind() { - ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => { - Ty::new_slice(tcx, elem_ty) - } - _ => *pointee_ty, - }; // References have the same valtree representation as their pointee. - let subpattern = self.valtree_to_pat(cv, pointee_ty); - PatKind::Deref { subpattern } + PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) } } } }, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4bfeab44bf4b9..66c2223efc8c7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -130,7 +130,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Lower the endpoint into a temporary `PatKind` that will then be // deconstructed to obtain the constant value and other data. - let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr); + let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr, None); // Unpeel any ascription or inline-const wrapper nodes. loop { @@ -294,7 +294,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Never => PatKind::Never, - hir::PatKind::Expr(value) => self.lower_pat_expr(value), + hir::PatKind::Expr(value) => self.lower_pat_expr(value, Some(ty)), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); @@ -630,7 +630,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`) /// - Inline const blocks (e.g. `const { 1 + 1 }`) /// - Literals, possibly negated (e.g. `-128u8`, `"hello"`) - fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> { + fn lower_pat_expr( + &mut self, + expr: &'tcx hir::PatExpr<'tcx>, + pat_ty: Option>, + ) -> PatKind<'tcx> { let (lit, neg) = match &expr.kind { hir::PatExprKind::Path(qpath) => { return self.lower_path(qpath, expr.hir_id, expr.span).kind; @@ -641,7 +645,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatExprKind::Lit { lit, negated } => (lit, *negated), }; - let ct_ty = self.typeck_results.node_type(expr.hir_id); + // We handle byte string literal patterns by using the pattern's type instead of the + // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference, + // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the + // pattern's type means we'll properly translate it to a slice reference pattern. This works + // because slices and arrays have the same valtree representation. + let ct_ty = pat_ty.unwrap_or_else(|| self.typeck_results.node_type(expr.hir_id)); let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; let constant = self.tcx.at(expr.span).lit_to_const(lit_input); self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind From 3779c6b7974f715c1fba0e6b559798a16178193c Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 26 Mar 2025 08:20:20 -0700 Subject: [PATCH 147/333] add a temporary workaround for `string_deref_patterns` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 66c2223efc8c7..d20e051548bf1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, Integer}; 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_hir::{self as hir, LangItem, RangeEnd}; use rustc_index::Idx; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ @@ -650,7 +650,26 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the // pattern's type means we'll properly translate it to a slice reference pattern. This works // because slices and arrays have the same valtree representation. - let ct_ty = pat_ty.unwrap_or_else(|| self.typeck_results.node_type(expr.hir_id)); + // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if + // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. + // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is + // superseded by a more general implementation of deref patterns. + let ct_ty = match pat_ty { + Some(pat_ty) + if let ty::Adt(def, _) = *pat_ty.kind() + && self.tcx.is_lang_item(def.did(), LangItem::String) => + { + if !self.tcx.features().string_deref_patterns() { + span_bug!( + expr.span, + "matching on `String` went through without enabling string_deref_patterns" + ); + } + self.typeck_results.node_type(expr.hir_id) + } + Some(pat_ty) => pat_ty, + None => self.typeck_results.node_type(expr.hir_id), + }; let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; let constant = self.tcx.at(expr.span).lit_to_const(lit_input); self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind From af7359ee4fd25ac5fd92fa20c8b37405ac0d0c05 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 26 Mar 2025 12:10:47 -0700 Subject: [PATCH 148/333] Add release notes for 1.86.0 --- RELEASES.md | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 755e73a34c6bf..3047a0c366a42 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,125 @@ +Version 1.86.0 (2025-04-03) +========================== + + + +Language +-------- +- [Stabilize the ability to upcast a trait object to one of its supertraits.](https://github.com/rust-lang/rust/pull/134367) +- [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090) +- [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397) +- Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604) +- [More pointers are now detected as definitely not-null based on their alignment in const eval.](https://github.com/rust-lang/rust/pull/133700) +- [Empty `repr()` attribute applied to invalid items are now correctly rejected.](https://github.com/rust-lang/rust/pull/133925) +- [Inner attributes `#![test]` and `#![rustfmt::skip]` are no longer accepted in more places than intended.](https://github.com/rust-lang/rust/pull/134276) + + + +Compiler +-------- +- [Debug-assert that raw pointers are non-null on access.](https://github.com/rust-lang/rust/pull/134424) +- [Change `-O` to mean `-C opt-level=3` instead of `-C opt-level=2` to match Cargo's defaults.](https://github.com/rust-lang/rust/pull/135439) +- [Fix emission of `overflowing_literals` under certain macro environments.](https://github.com/rust-lang/rust/pull/136393) + + + +Platform Support +---------------- +- [Replace `i686-unknown-redox` target with `i586-unknown-redox`.](https://github.com/rust-lang/rust/pull/136698) +- [Increase baseline CPU of `i686-unknown-hurd-gnu` to Pentium 4.](https://github.com/rust-lang/rust/pull/136700) +- New tier 3 targets: + - [`{aarch64-unknown,x86_64-pc}-nto-qnx710_iosock`](https://github.com/rust-lang/rust/pull/133631). + For supporting Neutrino QNX 7.1 with `io-socket` network stack. + - [`{aarch64-unknown,x86_64-pc}-nto-qnx800`](https://github.com/rust-lang/rust/pull/133631). + For supporting Neutrino QNX 8.0 (`no_std`-only). + - [`{x86_64,i686}-win7-windows-gnu`](https://github.com/rust-lang/rust/pull/134609). + Intended for backwards compatibility with Windows 7. `{x86_64,i686}-win7-windows-msvc` are the Windows MSVC counterparts that already exist as Tier 3 targets. + - [`amdgcn-amd-amdhsa`](https://github.com/rust-lang/rust/pull/134740). + - [`x86_64-pc-cygwin`](https://github.com/rust-lang/rust/pull/134999). + - [`{mips,mipsel}-mti-none-elf`](https://github.com/rust-lang/rust/pull/135074). + Initial bare-metal support. + - [`m68k-unknown-none-elf`](https://github.com/rust-lang/rust/pull/135085). + - [`armv7a-nuttx-{eabi,eabihf}`, `aarch64-unknown-nuttx`, and `thumbv7a-nuttx-{eabi,eabihf}`](https://github.com/rust-lang/rust/pull/135757). + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + +Libraries +--------- +- The type of `FromBytesWithNulError` in `CStr::from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>` was [changed from an opaque struct to an enum](https://github.com/rust-lang/rust/pull/134143), allowing users to examine why the conversion failed. +- [Remove `RustcDecodable` and `RustcEncodable`.](https://github.com/rust-lang/rust/pull/134272) +- [Deprecate libtest's `--logfile` option.](https://github.com/rust-lang/rust/pull/134283) +- [On recent versions of Windows, `std::fs::remove_file` will now remove read-only files.](https://github.com/rust-lang/rust/pull/134679) + + + +Stabilized APIs +--------------- + +- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down) +- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up) +- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut) +- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut) +- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html) +- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut) +- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut) +- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones) +- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if) +- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait) +- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force) +- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait) + +These APIs are now stable in const contexts: + +- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html) +- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut) +- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position) +- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary) +- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at) +- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked) +- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut) +- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked) + + + +Cargo +----- +- [When merging, replace rather than combine configuration keys that refer to a program path and its arguments.](https://github.com/rust-lang/cargo/pull/15066/) +- [Error if both `--package` and `--workspace` are passed but the requested package is missing.](https://github.com/rust-lang/cargo/pull/15071/) This was previously silently ignored, which was considered a bug since missing packages should be reported. +- [Deprecate the token argument in `cargo login` to avoid shell history leaks.](https://github.com/rust-lang/cargo/pull/15057/) +- [Simplify the implementation of `SourceID` comparisons.](https://github.com/rust-lang/cargo/pull/14980/) This may potentially change behavior if the canonicalized URL compares differently in alternative registries. + + + +Rustdoc +----- +- [Add a sans-serif font setting.](https://github.com/rust-lang/rust/pull/133636) + + + +Compatibility Notes +------------------- +- [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951) + Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail. +- [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300) +- The future incompatibility lint `cenum_impl_drop_cast` [has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. +- [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037) + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807) +The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. + + Version 1.85.1 (2025-03-18) ========================== From 74b7599230996968c476a5ea9b5e44be545e673e Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 26 Mar 2025 19:33:46 -0500 Subject: [PATCH 149/333] satisfy eslint --- src/librustdoc/html/static/js/search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 651d12bb2e907..f3f4878b1627c 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar, nonnull, nonundef */ +/* global addClass, getNakedUrl, getSettingValue, getVar, nonundef */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -2489,7 +2489,7 @@ class DocSearch { } } catch (err) { query = newParsedQuery(userQuery); - if (Array.isArray(err) && err.every((elem) => typeof elem == 'string')) { + if (Array.isArray(err) && err.every(elem => typeof elem === "string")) { query.error = err; } else { // rethrow the error if it isn't a string array @@ -2797,7 +2797,7 @@ class DocSearch { }, this.searchIndex[result.id]); // To be sure than it some items aren't considered as duplicate. - obj.fullPath = res[2] + "|" + obj.ty + obj.fullPath = res[2] + "|" + obj.ty; if (duplicates.has(obj.fullPath)) { continue; From a9a21bde85b41f19fe46b3cd06601829ed842d8f Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 27 Mar 2025 18:32:48 +0100 Subject: [PATCH 150/333] Delete from_method from rustc_on_unimplemented documentation --- src/doc/rustc-dev-guide/src/diagnostics.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 972309b5cd343..6f72ea902f5d6 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -954,9 +954,6 @@ application of these fields based on a variety of attributes when using `Self="std::iter::Iterator"`. This is needed because `Self` is a keyword which cannot appear in attributes. - `direct`: user-specified rather than derived obligation. - - `from_method`: usable both as boolean (whether the flag is present, like - `crate_local`) or matching against a particular method. Currently used - for `try`. - `from_desugaring`: usable both as boolean (whether the flag is present) or matching against a particular desugaring. The desugaring is identified with its variant name in the `DesugaringKind` enum. From 65624d9ea5c2aee3f3c7729f3b8d72c0920df6e6 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 26 Mar 2025 20:32:14 -0500 Subject: [PATCH 151/333] tester.js: ignore displayTypeSignature if it is null --- src/tools/rustdoc-js/tester.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index ea575f27799a9..f70fc917770c6 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -451,7 +451,7 @@ function loadSearchJS(doc_folder, resource_suffix) { if (!Object.prototype.hasOwnProperty.call(entry, key)) { continue; } - if (key === "displayTypeSignature") { + if (key === "displayTypeSignature" && entry.displayTypeSignature !== null) { const {type, mappedNames, whereClause} = await entry.displayTypeSignature; entry.displayType = arrayToCode(type); From d4870874158d70e3f6863412ea729dd70d1baf7b Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 27 Mar 2025 17:24:21 -0500 Subject: [PATCH 152/333] search.js: revert usage of nonundef for now (not available under test) specifically, `storage.js` is not loaded during `rustdoc-js` and `rustdoc-js-std` tests. --- src/librustdoc/html/static/js/search.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index f3f4878b1627c..dce5fddb3177e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue, getVar, nonundef */ +/* global addClass, getNakedUrl, getSettingValue, getVar */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -353,7 +353,8 @@ function getFilteredNextElem(query, parserState, elems, isInGenerics) { const typeFilterElem = elems.pop(); checkExtraTypeFilterCharacters(start, parserState); // typeFilterElem is not undefined. If it was, the elems.length check would have fired. - parserState.typeFilter = nonundef(typeFilterElem).normalizedPathLast; + // @ts-expect-error + parserState.typeFilter = typeFilterElem.normalizedPathLast; parserState.pos += 1; parserState.totalElems -= 1; query.literalSearch = false; From 827cb1b2a7b4334b38b20c291a95de62894c335c Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 28 Mar 2025 12:14:09 +0000 Subject: [PATCH 153/333] use `try_fold` instead of `fold` --- compiler/stable_mir/src/mir/body.rs | 3 +-- compiler/stable_mir/src/mir/visit.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index b1bf7bce828c3..2a1c163de3c45 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1057,8 +1057,7 @@ impl Place { /// In order to retrieve the correct type, the `locals` argument must match the list of all /// locals from the function body where this place originates from. pub fn ty(&self, locals: &[LocalDecl]) -> Result { - let start_ty = locals[self.local].ty; - self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?)) + self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) } } diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 09447e70dfb18..9d2368ba33202 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -563,7 +563,7 @@ pub struct PlaceRef<'a> { impl PlaceRef<'_> { /// Get the type of this place. pub fn ty(&self, locals: &[LocalDecl]) -> Result { - self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?)) + self.projection.iter().try_fold(locals[self.local].ty, |place_ty, elem| elem.ty(place_ty)) } } From 9ef35ddc0ca236db91d444a31de5fc8ac835ce9b Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 28 Mar 2025 12:21:21 +0000 Subject: [PATCH 154/333] use `slice::contains` where applicable --- compiler/rustc_builtin_macros/src/edition_panic.rs | 10 +++++----- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- compiler/rustc_mir_build/src/builder/scope.rs | 2 +- compiler/rustc_passes/src/entry.rs | 2 +- compiler/rustc_session/src/utils.rs | 11 ++++++----- compiler/rustc_span/src/lib.rs | 2 +- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index b39c9861fd643..ccfcc3079ebf8 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -74,11 +74,11 @@ pub(crate) fn use_panic_2021(mut span: Span) -> bool { // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) loop { let expn = span.ctxt().outer_expn_data(); - if let Some(features) = expn.allow_internal_unstable { - if features.iter().any(|&f| f == sym::edition_panic) { - span = expn.call_site; - continue; - } + if let Some(features) = expn.allow_internal_unstable + && features.contains(&sym::edition_panic) + { + span = expn.call_site; + continue; } break expn.edition >= Edition::Edition2021; } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 216a18e72edff..ccc0273280fe3 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2186,7 +2186,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { // indirectly from ThinLTO. In theory these are not needed as ThinLTO could resolve // these, but it currently does not do so. let can_have_static_objects = - tcx.sess.lto() == Lto::Thin || tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib); + tcx.sess.lto() == Lto::Thin || tcx.crate_types().contains(&CrateType::Rlib); tcx.sess.target.is_like_windows && can_have_static_objects && diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d16d4ed228389..a85d032f36eee 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -604,7 +604,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let Some((name, _)) = lang_items::extract(attrs) && let Some(lang_item) = LangItem::from_name(name) { - if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) { + if WEAK_LANG_ITEMS.contains(&lang_item) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } if let Some(link_name) = lang_item.link_name() { diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index e56c0ae92cac6..e42336a1dbbcc 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -1496,7 +1496,7 @@ fn build_scope_drops<'tcx>( // path, then don't generate the drop. (We only take this into // account for non-unwind paths so as not to disturb the // caching mechanism.) - if scope.moved_locals.iter().any(|&o| o == local) { + if scope.moved_locals.contains(&local) { continue; } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index d2729876ebbb4..2a435c4b2e05c 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -24,7 +24,7 @@ struct EntryContext<'tcx> { } fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { - let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable); + let any_exe = tcx.crate_types().contains(&CrateType::Executable); if !any_exe { // No need to find a main function. return None; diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index fcede379b893a..2243e831b66ec 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -149,14 +149,15 @@ pub fn extra_compiler_flags() -> Option<(Vec, bool)> { arg[a.len()..].to_string() }; let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); - if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { + if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&option) { excluded_cargo_defaults = true; } else { result.push(a.to_string()); - match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { - Some(s) => result.push(format!("{s}=[REDACTED]")), - None => result.push(content), - } + result.push(if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&option) { + format!("{option}=[REDACTED]") + } else { + content + }); } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f19d4d9f3624e..9e6ba2e1b9ce2 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -876,7 +876,7 @@ impl Span { self.ctxt() .outer_expn_data() .allow_internal_unstable - .is_some_and(|features| features.iter().any(|&f| f == feature)) + .is_some_and(|features| features.contains(&feature)) } /// Checks if this span arises from a compiler desugaring of kind `kind`. From cdbb219f835ebb3dad05a02c48afa10c33f21f2b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 12:38:32 -0300 Subject: [PATCH 155/333] Fix code generation link --- .../rustc-dev-guide/src/tests/codegen-backend-tests/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md index c4bac26aba2c2..6bf46ddcd21a6 100644 --- a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/intro.md @@ -1,6 +1,6 @@ # Codegen backend testing -See also the [Code generation](../../../src/backend/codegen.md) chapter. +See also the [Code generation](../../backend/codegen.md) chapter. In addition to the primary LLVM codegen backend, the rust-lang/rust CI also runs tests of the [cranelift][cg_clif] and [GCC][cg_gcc] codegen backends in certain test jobs. From 9300fa19b73e569d7c38f51149d9537a6ef0a232 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 28 Mar 2025 16:53:17 +0000 Subject: [PATCH 156/333] Bump to 1.88.0 --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index f6342716723fc..59be592144c28 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.87.0 +1.88.0 From 40b1f4899a9081c0d8edf56072aaeb510b63a415 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 18:32:12 +0100 Subject: [PATCH 157/333] Add the feature gate for the `super let` experiment. --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_parse/src/parser/stmt.rs | 15 ++++++++++++++- compiler/rustc_parse/src/parser/token_type.rs | 4 ++++ compiler/rustc_span/src/symbol.rs | 1 + tests/ui/feature-gates/feature-gate-super-let.rs | 4 ++++ .../feature-gates/feature-gate-super-let.stderr | 13 +++++++++++++ 7 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/ui/feature-gates/feature-gate-super-let.rs create mode 100644 tests/ui/feature-gates/feature-gate-super-let.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 31ff102c127a3..4f50e21fc7d08 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -505,6 +505,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(contracts, "contracts are incomplete"); gate_all!(contracts_internals, "contract internal machinery is for internal use only"); gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); + gate_all!(super_let, "`super let` is experimental"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 72468dd4714d7..b4499fb2a6a41 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -630,6 +630,8 @@ declare_features! ( (unstable, strict_provenance_lints, "1.61.0", Some(130351)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), + /// Allows `super let` statements. + (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 97cd4d2117f87..2cd09aa8959c4 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -73,7 +73,20 @@ impl<'a> Parser<'a> { }); } - let stmt = if self.token.is_keyword(kw::Let) { + let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) { + self.collect_tokens(None, attrs, force_collect, |this, attrs| { + this.expect_keyword(exp!(Super))?; + this.psess.gated_spans.gate(sym::super_let, this.prev_token.span); + this.expect_keyword(exp!(Let))?; + let local = this.parse_local(attrs)?; // FIXME(mara): implement super let + let trailing = Trailing::from(capture_semi && this.token == token::Semi); + Ok(( + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), + trailing, + UsePreAttrPos::No, + )) + })? + } else if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(exp!(Let))?; let local = this.parse_local(attrs)?; diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index 886438fd583a3..add3c9702019c 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -114,6 +114,7 @@ pub enum TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -250,6 +251,7 @@ impl TokenType { KwSelfUpper, KwStatic, KwStruct, + KwSuper, KwTrait, KwTry, KwType, @@ -324,6 +326,7 @@ impl TokenType { TokenType::KwSelfUpper => Some(kw::SelfUpper), TokenType::KwStatic => Some(kw::Static), TokenType::KwStruct => Some(kw::Struct), + TokenType::KwSuper => Some(kw::Super), TokenType::KwTrait => Some(kw::Trait), TokenType::KwTry => Some(kw::Try), TokenType::KwType => Some(kw::Type), @@ -549,6 +552,7 @@ macro_rules! exp { (SelfUpper) => { exp!(@kw, SelfUpper, KwSelfUpper) }; (Static) => { exp!(@kw, Static, KwStatic) }; (Struct) => { exp!(@kw, Struct, KwStruct) }; + (Super) => { exp!(@kw, Super, KwSuper) }; (Trait) => { exp!(@kw, Trait, KwTrait) }; (Try) => { exp!(@kw, Try, KwTry) }; (Type) => { exp!(@kw, Type, KwType) }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712cd..cc1b324eb00d3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2036,6 +2036,7 @@ symbols! { sub_assign, sub_with_overflow, suggestion, + super_let, supertrait_item_shadowing, surface_async_drop_in_place, sym, diff --git a/tests/ui/feature-gates/feature-gate-super-let.rs b/tests/ui/feature-gates/feature-gate-super-let.rs new file mode 100644 index 0000000000000..cfe92a42669d1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.rs @@ -0,0 +1,4 @@ +fn main() { + super let a = 1; + //~^ ERROR `super let` is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-super-let.stderr b/tests/ui/feature-gates/feature-gate-super-let.stderr new file mode 100644 index 0000000000000..a64e1b374f9c0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-super-let.stderr @@ -0,0 +1,13 @@ +error[E0658]: `super let` is experimental + --> $DIR/feature-gate-super-let.rs:2:5 + | +LL | super let a = 1; + | ^^^^^ + | + = note: see issue #139076 for more information + = help: add `#![feature(super_let)]` 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 1 previous error + +For more information about this error, try `rustc --explain E0658`. From dd4f616423219d81ffd34786d6a589b3ad7ba803 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 28 Mar 2025 19:32:36 +0100 Subject: [PATCH 158/333] std: deduplicate `errno` accesses By marking `__errno_location` as `#[ffi_const]` and `std::sys::os::errno` as `#[inline]`, this PR allows merging multiple calls to `io::Error::last_os_error()` into one. --- library/std/src/lib.rs | 1 + library/std/src/sys/pal/unix/os.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ad005833ad53e..9dcedaa13f661 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] +#![feature(ffi_const)] #![feature(formatting_options)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 30282fbf65541..f47421c67051b 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -59,11 +59,14 @@ unsafe extern "C" { #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] + // SAFETY: this will always return the same pointer on a given thread. + #[unsafe(ffi_const)] fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] +#[inline] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } @@ -72,16 +75,19 @@ pub fn errno() -> i32 { // needed for readdir and syscall! #[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it +#[inline] pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } } #[cfg(target_os = "vxworks")] +#[inline] pub fn errno() -> i32 { unsafe { libc::errnoGet() } } #[cfg(target_os = "rtems")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -92,6 +98,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -103,6 +110,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] #[allow(dead_code)] +#[inline] pub fn set_errno(e: i32) { unsafe extern "C" { #[thread_local] From 7c74474d8d9fb2a714d86bae7a5099d27899e150 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 28 Mar 2025 16:32:28 +0300 Subject: [PATCH 159/333] hygiene: Rewrite `apply_mark_internal` to be more understandable --- compiler/rustc_span/src/hygiene.rs | 121 +++++++++--------- .../nonterminal-token-hygiene.stdout | 20 +-- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 4390085cd049a..e7a8dee27f568 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -75,6 +75,21 @@ pub struct SyntaxContextData { } impl SyntaxContextData { + fn new( + (parent, outer_expn, outer_transparency): SyntaxContextKey, + opaque: SyntaxContext, + opaque_and_semitransparent: SyntaxContext, + ) -> SyntaxContextData { + SyntaxContextData { + outer_expn, + outer_transparency, + parent, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + } + } + fn root() -> SyntaxContextData { SyntaxContextData { outer_expn: ExpnId::root(), @@ -543,7 +558,7 @@ impl HygieneData { ) -> SyntaxContext { assert_ne!(expn_id, ExpnId::root()); if transparency == Transparency::Opaque { - return self.apply_mark_internal(ctxt, expn_id, transparency); + return self.alloc_ctxt(ctxt, expn_id, transparency); } let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); @@ -554,7 +569,7 @@ impl HygieneData { }; if call_site_ctxt.is_root() { - return self.apply_mark_internal(ctxt, expn_id, transparency); + return self.alloc_ctxt(ctxt, expn_id, transparency); } // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a @@ -567,74 +582,60 @@ impl HygieneData { // // See the example at `test/ui/hygiene/legacy_interaction.rs`. for (expn_id, transparency) in self.marks(ctxt) { - call_site_ctxt = self.apply_mark_internal(call_site_ctxt, expn_id, transparency); + call_site_ctxt = self.alloc_ctxt(call_site_ctxt, expn_id, transparency); } - self.apply_mark_internal(call_site_ctxt, expn_id, transparency) + self.alloc_ctxt(call_site_ctxt, expn_id, transparency) } - fn apply_mark_internal( + /// Allocate a new context with the given key, or retrieve it from cache if the given key + /// already exists. The auxiliary fields are calculated from the key. + fn alloc_ctxt( &mut self, - ctxt: SyntaxContext, + parent: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - let syntax_context_data = &mut self.syntax_context_data; - debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; - let mut opaque_and_semitransparent = - syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; - - if transparency >= Transparency::Opaque { - let parent = opaque; - opaque = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque - }); - } + debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); - if transparency >= Transparency::SemiTransparent { - let parent = opaque_and_semitransparent; - opaque_and_semitransparent = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque_and_semitransparent = - SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent - }); + // Look into the cache first. + let key = (parent, expn_id, transparency); + if let Some(ctxt) = self.syntax_context_map.get(&key) { + return *ctxt; } - let parent = ctxt; - *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - SyntaxContext::from_usize(syntax_context_data.len() - 1) - }) + // Reserve a new syntax context. + let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); + self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + self.syntax_context_map.insert(key, ctxt); + + // Opaque and semi-transparent versions of the parent. Note that they may be equal to the + // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, + // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques + // and semi-transparents. + let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; + let parent_opaque_and_semitransparent = + self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; + + // Evaluate opaque and semi-transparent versions of the new syntax context. + let (opaque, opaque_and_semitransparent) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), + Transparency::SemiTransparent => ( + parent_opaque, + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + ), + Transparency::Opaque => ( + // Will be the same as `ctxt` if the expn chain contains only opaques. + self.alloc_ctxt(parent_opaque, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + ), + }; + + // Fill the full data, now that we have it. + self.syntax_context_data[ctxt.as_u32() as usize] = + SyntaxContextData::new(key, opaque, opaque_and_semitransparent); + ctxt } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index c80a33206fb4f..6fd6cb474693b 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#4 */; +struct S /* 0#5 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From 5952f01712521d6700a58eeb0ad8b25db7c8fd68 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Fri, 28 Mar 2025 20:10:31 +0100 Subject: [PATCH 160/333] Fix trivial typo of `BoundVariableKind` --- src/doc/rustc-dev-guide/src/ty_module/binders.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty_module/binders.md index defb7cde514a0..71157eca9b11e 100644 --- a/src/doc/rustc-dev-guide/src/ty_module/binders.md +++ b/src/doc/rustc-dev-guide/src/ty_module/binders.md @@ -40,7 +40,7 @@ We did not always explicitly track the set of bound vars introduced by each `Bin ``` Binder( fn(&'^1_0 &'^1 T/#0), - &[BoundVariarbleKind::Region(...)], + &[BoundVariableKind::Region(...)], ) ``` This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. From fbe5e555214c079d82985c40b44a3b992d695fab Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Thu, 27 Mar 2025 22:43:23 -0700 Subject: [PATCH 161/333] bootstrap: Avoid cloning change-id list --- src/bootstrap/src/bin/main.rs | 2 +- src/bootstrap/src/core/config/config.rs | 2 +- src/bootstrap/src/utils/change_tracker.rs | 22 +++++++++------------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 7ec3140c03862..cbfe00a757ce4 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -191,7 +191,7 @@ fn check_version(config: &Config) -> Option { } msg.push_str("There have been changes to x.py since you last updated:\n"); - msg.push_str(&human_readable_changes(&changes)); + msg.push_str(&human_readable_changes(changes)); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bbb0fbfbb9351..1712be7f947fa 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1381,7 +1381,7 @@ impl Config { if !changes.is_empty() { println!( "WARNING: There have been changes to x.py since you last updated:\n{}", - crate::human_readable_changes(&changes) + crate::human_readable_changes(changes) ); } } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 5314141dd1b02..244391739f38a 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -35,29 +35,25 @@ impl Display for ChangeSeverity { } } -pub fn find_recent_config_change_ids(current_id: usize) -> Vec { - if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) { +pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo] { + if let Some(index) = + CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id) + { + // Skip the current_id and IDs before it + &CONFIG_CHANGE_HISTORY[index + 1..] + } else { // If the current change-id is greater than the most recent one, return // an empty list (it may be due to switching from a recent branch to an // older one); otherwise, return the full list (assuming the user provided // the incorrect change-id by accident). if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) { if current_id > config.change_id { - return Vec::new(); + return &[]; } } - return CONFIG_CHANGE_HISTORY.to_vec(); + CONFIG_CHANGE_HISTORY } - - let index = - CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap(); - - CONFIG_CHANGE_HISTORY - .iter() - .skip(index + 1) // Skip the current_id and IDs before it - .cloned() - .collect() } pub fn human_readable_changes(changes: &[ChangeInfo]) -> String { From 122d7e1dcd921eafabd5c76d050d997876110e08 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 15:24:49 +0100 Subject: [PATCH 162/333] Remove `terminating_scopes` hash set. --- .../rustc_hir_analysis/src/check/region.rs | 259 +++++++----------- 1 file changed, 95 insertions(+), 164 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2528adb937b31..cf66ab708bb9e 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -8,7 +8,6 @@ use std::mem; -use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -45,28 +44,6 @@ struct ScopeResolutionVisitor<'tcx> { scope_tree: ScopeTree, cx: Context, - - /// `terminating_scopes` is a set containing the ids of each - /// statement, or conditional/repeating expression. These scopes - /// are calling "terminating scopes" because, when attempting to - /// find the scope of a temporary, by default we search up the - /// enclosing scopes until we encounter the terminating scope. A - /// conditional/repeating expression is one which is not - /// guaranteed to execute exactly once upon entering the parent - /// scope. This could be because the expression only executes - /// conditionally, such as the expression `b` in `a && b`, or - /// because the expression may execute many times, such as a loop - /// body. The reason that we distinguish such expressions is that, - /// upon exiting the parent scope, we cannot statically know how - /// many times the expression executed, and thus if the expression - /// creates temporaries we cannot know statically how many such - /// temporaries we would have to cleanup. Therefore, we ensure that - /// the temporaries never outlast the conditional/repeating - /// expression, preventing the need for dynamic checks and/or - /// arbitrary amounts of stack space. Terminating scopes end - /// up being contained in a DestructionScope that contains the - /// destructor's execution. - terminating_scopes: FxHashSet, } /// Records the lifetime of a local variable as `cx.var_parent` @@ -81,7 +58,11 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It } } -fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hir::Block<'tcx>) { +fn resolve_block<'tcx>( + visitor: &mut ScopeResolutionVisitor<'tcx>, + blk: &'tcx hir::Block<'tcx>, + terminating: bool, +) { debug!("resolve_block(blk.hir_id={:?})", blk.hir_id); let prev_cx = visitor.cx; @@ -111,7 +92,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // `other_argument()` has run and also the call to `quux(..)` // itself has returned. - visitor.enter_node_scope_with_dtor(blk.hir_id.local_id); + visitor.enter_node_scope_with_dtor(blk.hir_id.local_id, terminating); visitor.cx.var_parent = visitor.cx.parent; { @@ -140,8 +121,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // the sequence of visits agree with the order in the default // `hir::intravisit` visitor. mem::swap(&mut prev_cx, &mut visitor.cx); - visitor.terminating_scopes.insert(els.hir_id.local_id); - visitor.visit_block(els); + resolve_block(visitor, els, true); // From now on, we continue normally. visitor.cx = prev_cx; } @@ -169,12 +149,12 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi if let Some(tail_expr) = blk.expr { let local_id = tail_expr.hir_id.local_id; let edition = blk.span.edition(); - if edition.at_least_rust_2024() { - visitor.terminating_scopes.insert(local_id); - } else if !visitor - .tcx - .lints_that_dont_need_to_run(()) - .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) + let terminating = edition.at_least_rust_2024(); + if !terminating + && !visitor + .tcx + .lints_that_dont_need_to_run(()) + .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) { // If this temporary scope will be changing once the codebase adopts Rust 2024, // and we are linting about possible semantic changes that would result, @@ -185,7 +165,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi .backwards_incompatible_scope .insert(local_id, Scope { local_id, data: ScopeData::Node }); } - visitor.visit_expr(tail_expr); + resolve_expr(visitor, tail_expr, terminating); } } @@ -203,18 +183,14 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: let prev_cx = visitor.cx; - visitor.terminating_scopes.insert(arm.hir_id.local_id); - - visitor.enter_node_scope_with_dtor(arm.hir_id.local_id); + visitor.enter_node_scope_with_dtor(arm.hir_id.local_id, true); visitor.cx.var_parent = visitor.cx.parent; - if let Some(expr) = arm.guard - && !has_let_expr(expr) - { - visitor.terminating_scopes.insert(expr.hir_id.local_id); + resolve_pat(visitor, arm.pat); + if let Some(guard) = arm.guard { + resolve_expr(visitor, guard, !has_let_expr(guard)); } - - intravisit::walk_arm(visitor, arm); + resolve_expr(visitor, arm.body, false); visitor.cx = prev_cx; } @@ -243,126 +219,24 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi // associated destruction scope that represents the scope of the // statement plus its destructors, and thus the scope for which // regions referenced by the destructors need to survive. - visitor.terminating_scopes.insert(stmt_id); let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id); + visitor.enter_node_scope_with_dtor(stmt_id, true); intravisit::walk_stmt(visitor, stmt); visitor.cx.parent = prev_parent; } -fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) { +fn resolve_expr<'tcx>( + visitor: &mut ScopeResolutionVisitor<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + terminating: bool, +) { debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr); let prev_cx = visitor.cx; - visitor.enter_node_scope_with_dtor(expr.hir_id.local_id); - - { - let terminating_scopes = &mut visitor.terminating_scopes; - let mut terminating = |id: hir::ItemLocalId| { - terminating_scopes.insert(id); - }; - match expr.kind { - // Conditional or repeating scopes are always terminating - // scopes, meaning that temporaries cannot outlive them. - // This ensures fixed size stacks. - hir::ExprKind::Binary( - source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, - l, - r, - ) => { - // expr is a short circuiting operator (|| or &&). As its - // functionality can't be overridden by traits, it always - // processes bool sub-expressions. bools are Copy and thus we - // can drop any temporaries in evaluation (read) order - // (with the exception of potentially failing let expressions). - // We achieve this by enclosing the operands in a terminating - // scope, both the LHS and the RHS. - - // We optimize this a little in the presence of chains. - // Chains like a && b && c get lowered to AND(AND(a, b), c). - // In here, b and c are RHS, while a is the only LHS operand in - // that chain. This holds true for longer chains as well: the - // leading operand is always the only LHS operand that is not a - // binop itself. Putting a binop like AND(a, b) into a - // terminating scope is not useful, thus we only put the LHS - // into a terminating scope if it is not a binop. - - let terminate_lhs = match l.kind { - // let expressions can create temporaries that live on - hir::ExprKind::Let(_) => false, - // binops already drop their temporaries, so there is no - // need to put them into a terminating scope. - // This is purely an optimization to reduce the number of - // terminating scopes. - hir::ExprKind::Binary( - source_map::Spanned { - node: hir::BinOpKind::And | hir::BinOpKind::Or, .. - }, - .., - ) => false, - // otherwise: mark it as terminating - _ => true, - }; - if terminate_lhs { - terminating(l.hir_id.local_id); - } - - // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries - // should live beyond the immediate expression - if !matches!(r.kind, hir::ExprKind::Let(_)) { - terminating(r.hir_id.local_id); - } - } - hir::ExprKind::If(_, then, Some(otherwise)) => { - terminating(then.hir_id.local_id); - terminating(otherwise.hir_id.local_id); - } - - hir::ExprKind::If(_, then, None) => { - terminating(then.hir_id.local_id); - } - - hir::ExprKind::Loop(body, _, _, _) => { - terminating(body.hir_id.local_id); - } - - hir::ExprKind::DropTemps(expr) => { - // `DropTemps(expr)` does not denote a conditional scope. - // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. - terminating(expr.hir_id.local_id); - } - - hir::ExprKind::AssignOp(..) - | hir::ExprKind::Index(..) - | hir::ExprKind::Unary(..) - | hir::ExprKind::Call(..) - | hir::ExprKind::MethodCall(..) => { - // FIXME(https://github.com/rust-lang/rfcs/issues/811) Nested method calls - // - // The lifetimes for a call or method call look as follows: - // - // call.id - // - arg0.id - // - ... - // - argN.id - // - call.callee_id - // - // The idea is that call.callee_id represents *the time when - // the invoked function is actually running* and call.id - // represents *the time to prepare the arguments and make the - // call*. See the section "Borrows in Calls" borrowck/README.md - // for an extended explanation of why this distinction is - // important. - // - // record_superlifetime(new_cx, expr.callee_id); - } - - _ => {} - } - } + visitor.enter_node_scope_with_dtor(expr.hir_id.local_id, terminating); let prev_pessimistic = visitor.pessimistic_yield; @@ -417,6 +291,53 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi // properly, we can't miss any types. match expr.kind { + // Conditional or repeating scopes are always terminating + // scopes, meaning that temporaries cannot outlive them. + // This ensures fixed size stacks. + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, + left, + right, + ) => { + // expr is a short circuiting operator (|| or &&). As its + // functionality can't be overridden by traits, it always + // processes bool sub-expressions. bools are Copy and thus we + // can drop any temporaries in evaluation (read) order + // (with the exception of potentially failing let expressions). + // We achieve this by enclosing the operands in a terminating + // scope, both the LHS and the RHS. + + // We optimize this a little in the presence of chains. + // Chains like a && b && c get lowered to AND(AND(a, b), c). + // In here, b and c are RHS, while a is the only LHS operand in + // that chain. This holds true for longer chains as well: the + // leading operand is always the only LHS operand that is not a + // binop itself. Putting a binop like AND(a, b) into a + // terminating scope is not useful, thus we only put the LHS + // into a terminating scope if it is not a binop. + + let terminate_lhs = match left.kind { + // let expressions can create temporaries that live on + hir::ExprKind::Let(_) => false, + // binops already drop their temporaries, so there is no + // need to put them into a terminating scope. + // This is purely an optimization to reduce the number of + // terminating scopes. + hir::ExprKind::Binary( + source_map::Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. }, + .., + ) => false, + // otherwise: mark it as terminating + _ => true, + }; + + // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries + // should live beyond the immediate expression + let terminate_rhs = !matches!(right.kind, hir::ExprKind::Let(_)); + + resolve_expr(visitor, left, terminate_lhs); + resolve_expr(visitor, right, terminate_rhs); + } // Manually recurse over closures, because they are nested bodies // that share the parent environment. We handle const blocks in // `visit_inline_const`. @@ -485,9 +406,9 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); - visitor.visit_expr(then); + resolve_expr(visitor, then, true); visitor.cx = expr_cx; - visitor.visit_expr(otherwise); + resolve_expr(visitor, otherwise, true); } hir::ExprKind::If(cond, then, None) => { @@ -500,10 +421,20 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); - visitor.visit_expr(then); + resolve_expr(visitor, then, true); visitor.cx = expr_cx; } + hir::ExprKind::Loop(body, _, _, _) => { + resolve_block(visitor, body, true); + } + + hir::ExprKind::DropTemps(expr) => { + // `DropTemps(expr)` does not denote a conditional scope. + // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. + resolve_expr(visitor, expr, true); + } + _ => intravisit::walk_expr(visitor, expr), } @@ -786,12 +717,12 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { self.cx.parent = Some(child_scope); } - fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId) { + fn enter_node_scope_with_dtor(&mut self, id: hir::ItemLocalId, terminating: bool) { // If node was previously marked as a terminating scope during the // recursive visit of its parent node in the HIR, then we need to // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. - if self.terminating_scopes.contains(&id) { + if terminating { self.enter_scope(Scope { local_id: id, data: ScopeData::Destruction }); } self.enter_scope(Scope { local_id: id, data: ScopeData::Node }); @@ -803,13 +734,11 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { // visited the body. let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0); let outer_cx = self.cx; - let outer_ts = mem::take(&mut self.terminating_scopes); // The 'pessimistic yield' flag is set to true when we are // processing a `+=` statement and have to make pessimistic // control flow assumptions. This doesn't apply to nested // bodies within the `+=` statements. See #69307. let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); - self.terminating_scopes.insert(hir_id.local_id); self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::CallSite }); self.enter_scope(Scope { local_id: hir_id.local_id, data: ScopeData::Arguments }); @@ -819,14 +748,13 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> { // Restore context we had at the start. self.expr_and_pat_count = outer_ec; self.cx = outer_cx; - self.terminating_scopes = outer_ts; self.pessimistic_yield = outer_pessimistic_yield; } } impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { fn visit_block(&mut self, b: &'tcx Block<'tcx>) { - resolve_block(self, b); + resolve_block(self, b, false); } fn visit_body(&mut self, body: &hir::Body<'tcx>) { @@ -850,7 +778,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { } // The body of the every fn is a root scope. - this.visit_expr(body.value) + resolve_expr(this, body.value, true); } else { // Only functions have an outer terminating (drop) scope, while // temporaries in constant initializers may be 'static, but only @@ -871,6 +799,10 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { // (i.e., `'static`), which means that after `g` returns, it drops, // and all the associated destruction scope rules apply. this.cx.var_parent = None; + this.enter_scope(Scope { + local_id: body.value.hir_id.local_id, + data: ScopeData::Destruction, + }); resolve_local(this, None, Some(body.value)); } }) @@ -886,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_stmt(self, s); } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - resolve_expr(self, ex); + resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { resolve_local(self, Some(l.pat), l.init) @@ -916,7 +848,6 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { scope_tree: ScopeTree::default(), expr_and_pat_count: 0, cx: Context { parent: None, var_parent: None }, - terminating_scopes: Default::default(), pessimistic_yield: false, fixup_scopes: vec![], }; From 5004e10ceb5c02a7170d81adb551a25f6f9e3565 Mon Sep 17 00:00:00 2001 From: Frank King Date: Sat, 29 Mar 2025 12:13:38 +0800 Subject: [PATCH 163/333] Add a test for `Weak` created from `UniqueArc::downgrade` --- library/alloctests/tests/arc.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/library/alloctests/tests/arc.rs b/library/alloctests/tests/arc.rs index 45a145c6271a8..00bdf527133f7 100644 --- a/library/alloctests/tests/arc.rs +++ b/library/alloctests/tests/arc.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::cell::{Cell, RefCell}; use std::iter::TrustedLen; -use std::sync::{Arc, Weak}; +use std::sync::{Arc, UniqueArc, Weak}; #[test] fn uninhabited() { @@ -263,6 +263,27 @@ fn make_mut_unsized() { assert_eq!(*other_data, [110, 20, 30]); } +#[test] +fn test_unique_arc_weak() { + let data = UniqueArc::new(32); + + // Test that `Weak` downgraded from `UniqueArc` cannot be upgraded. + let weak = UniqueArc::downgrade(&data); + assert_eq!(weak.strong_count(), 0); + assert_eq!(weak.weak_count(), 0); + assert!(weak.upgrade().is_none()); + + // Test that `Weak` can now be upgraded after the `UniqueArc` being converted to `Arc`. + let strong = UniqueArc::into_arc(data); + assert_eq!(*strong, 32); + assert_eq!(weak.strong_count(), 1); + assert_eq!(weak.weak_count(), 1); + let upgraded = weak.upgrade().unwrap(); + assert_eq!(*upgraded, 32); + assert_eq!(weak.strong_count(), 2); + assert_eq!(weak.weak_count(), 1); +} + #[allow(unused)] mod pin_coerce_unsized { use alloc::sync::{Arc, UniqueArc}; From 163ea4acd0e93d5a45ea44b42a999abe39d0a93f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 10:38:44 +0100 Subject: [PATCH 164/333] Add more tests for pin!(). Co-authored-by: Daniel Henry-Mantilla --- library/coretests/tests/pin_macro.rs | 11 ++++++++ tests/ui/pin-macro/pin_move.rs | 26 +++++++++++++++++++ tests/ui/pin-macro/pin_move.stderr | 38 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/ui/pin-macro/pin_move.rs create mode 100644 tests/ui/pin-macro/pin_move.stderr diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index 639eab740c0b8..3174c91a6498b 100644 --- a/library/coretests/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs @@ -47,3 +47,14 @@ fn temp_lifetime() { } async fn foo(_: &mut usize) {} } + +#[test] +fn transitive_extension() { + async fn temporary() {} + + // `pin!` witnessed in the wild being used like this, even if it yields + // a `Pin<&mut &mut impl Unpin>`; it does work because `pin!` + // happens to transitively extend the lifespan of `temporary()`. + let p = pin!(&mut temporary()); + let _use = p; +} diff --git a/tests/ui/pin-macro/pin_move.rs b/tests/ui/pin-macro/pin_move.rs new file mode 100644 index 0000000000000..0f6d34fad951f --- /dev/null +++ b/tests/ui/pin-macro/pin_move.rs @@ -0,0 +1,26 @@ +//@ edition:2024 + +use core::marker::PhantomPinned; +use core::pin::pin; + +fn a() { + struct NotCopy(T); + #[allow(unused_mut)] + let mut pointee = NotCopy(PhantomPinned); + pin!(pointee); + let _moved = pointee; + //~^ ERROR use of moved value +} + +fn b() { + struct NotCopy(T); + let mut pointee = NotCopy(PhantomPinned); + pin!(*&mut pointee); + //~^ ERROR cannot move + let _moved = pointee; +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr new file mode 100644 index 0000000000000..c9b8ad9b2021f --- /dev/null +++ b/tests/ui/pin-macro/pin_move.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `pointee` + --> $DIR/pin_move.rs:11:18 + | +LL | let mut pointee = NotCopy(PhantomPinned); + | ----------- move occurs because `pointee` has type `a::NotCopy`, which does not implement the `Copy` trait +LL | pin!(pointee); + | ------- value moved here +LL | let _moved = pointee; + | ^^^^^^^ value used here after move + | +note: if `a::NotCopy` implemented `Clone`, you could clone the value + --> $DIR/pin_move.rs:7:5 + | +LL | struct NotCopy(T); + | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | pin!(pointee); + | ------- you could clone this value + +error[E0507]: cannot move out of a mutable reference + --> $DIR/pin_move.rs:18:10 + | +LL | pin!(*&mut pointee); + | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait + | +note: if `b::NotCopy` implemented `Clone`, you could clone the value + --> $DIR/pin_move.rs:16:5 + | +LL | struct NotCopy(T); + | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +LL | let mut pointee = NotCopy(PhantomPinned); +LL | pin!(*&mut pointee); + | ------------- you could clone this value + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0507. +For more information about an error, try `rustc --explain E0382`. From 366095d6c738821ab6745bf3b224e8643e0eb464 Mon Sep 17 00:00:00 2001 From: bohan Date: Sat, 29 Mar 2025 17:37:01 +0800 Subject: [PATCH 165/333] less decoding if it has the same syntax context --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 10 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 203 ++++++------------ .../nonterminal-token-hygiene.stdout | 20 +- 5 files changed, 81 insertions(+), 158 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747ca..34e4f2f26022a 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,7 +36,7 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData}; +use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; @@ -193,7 +193,7 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; +type SyntaxContextTable = LazyTable>>; type ExpnDataTable = LazyTable>>; type ExpnHashTable = LazyTable>>; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 14e3ce8bef6b2..ce6219c207fdb 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,7 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, }; use rustc_span::source_map::Spanned; use rustc_span::{ @@ -75,9 +75,9 @@ pub struct OnDiskCache { alloc_decoding_state: AllocDecodingState, // A map from syntax context ids to the position of their associated - // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext` + // `SyntaxContextKey`. We use a `u32` instead of a `SyntaxContext` // to represent the fact that we are storing *encoded* ids. When we decode - // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`, + // a `SyntaxContextKey`, a new id will be allocated from the global `HygieneData`, // which will almost certainly be different than the serialized id. syntax_contexts: FxHashMap, // A map from the `DefPathHash` of an `ExpnId` to the position @@ -305,7 +305,7 @@ impl OnDiskCache { let mut expn_data = UnhashMap::default(); let mut foreign_expn_data = UnhashMap::default(); - // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current + // Encode all hygiene data (`SyntaxContextKey` and `ExpnData`) from the current // session. hygiene_encode_context.encode( @@ -566,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { // We look up the position of the associated `SyntaxData` and decode it. let pos = syntax_contexts.get(&id).unwrap(); this.with_position(pos.to_usize(), |decoder| { - let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); + let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); data }) }) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 19e2b57456327..134f76d7248d9 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -111,7 +111,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextData, + rustc_span::hygiene::SyntaxContextKey, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 4390085cd049a..f94858856729c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,9 +24,6 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) -use std::cell::RefCell; -use std::collections::hash_map::Entry; -use std::collections::hash_set::Entry as SetEntry; use std::hash::Hash; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -34,7 +31,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; -use rustc_data_structures::sync::{Lock, WorkerLocal}; +use rustc_data_structures::sync::Lock; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -59,10 +56,10 @@ impl !PartialOrd for SyntaxContext {} /// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. /// The other fields are only for caching. -type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); +pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] -pub struct SyntaxContextData { +struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, @@ -94,6 +91,21 @@ impl SyntaxContextData { self.dollar_crate_name == kw::Empty } + fn new( + (parent, outer_expn, outer_transparency): SyntaxContextKey, + opaque: SyntaxContext, + opaque_and_semitransparent: SyntaxContext, + ) -> Self { + SyntaxContextData { + parent, + outer_expn, + outer_transparency, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + } + } + fn key(&self) -> SyntaxContextKey { (self.parent, self.outer_expn, self.outer_transparency) } @@ -574,67 +586,49 @@ impl HygieneData { fn apply_mark_internal( &mut self, - ctxt: SyntaxContext, + parent: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - let syntax_context_data = &mut self.syntax_context_data; - debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; - let mut opaque_and_semitransparent = - syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; - - if transparency >= Transparency::Opaque { - let parent = opaque; - opaque = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque: new_opaque, - opaque_and_semitransparent: new_opaque, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque - }); - } - - if transparency >= Transparency::SemiTransparent { - let parent = opaque_and_semitransparent; - opaque_and_semitransparent = *self - .syntax_context_map - .entry((parent, expn_id, transparency)) - .or_insert_with(|| { - let new_opaque_and_semitransparent = - SyntaxContext::from_usize(syntax_context_data.len()); - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent: new_opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - new_opaque_and_semitransparent - }); + debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); + // Look into the cache first. + let key = (parent, expn_id, transparency); + if let Some(ctxt) = self.syntax_context_map.get(&key) { + return *ctxt; } + // Reserve a new syntax context. + let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); + self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + self.syntax_context_map.insert(key, ctxt); + + // Opaque and semi-transparent versions of the parent. Note that they may be equal to the + // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, + // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques + // and semi-transparents. + let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; + let parent_opaque_and_semitransparent = + self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; + + // Evaluate opaque and semi-transparent versions of the new syntax context. + let (opaque, opaque_and_semitransparent) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), + Transparency::SemiTransparent => ( + parent_opaque, + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), + ), + Transparency::Opaque => ( + // Will be the same as `ctxt` if the expn chain contains only opaques. + self.apply_mark_internal(parent_opaque, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. + self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), + ), + }; - let parent = ctxt; - *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { - syntax_context_data.push(SyntaxContextData { - outer_expn: expn_id, - outer_transparency: transparency, - parent, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - }); - SyntaxContext::from_usize(syntax_context_data.len() - 1) - }) + // Fill the full data, now that we have it. + self.syntax_context_data[ctxt.as_u32() as usize] = + SyntaxContextData::new(key, opaque, opaque_and_semitransparent); + ctxt } } @@ -1265,7 +1259,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1323,9 +1317,6 @@ struct HygieneDecodeContextInner { /// Additional information used to assist in decoding hygiene data pub struct HygieneDecodeContext { inner: Lock, - - /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1396,10 +1387,10 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context SyntaxContextData>( +pub fn decode_syntax_context SyntaxContextKey>( d: &mut D, context: &HygieneDecodeContext, - decode_data: F, + decode_ctxt_key: F, ) -> SyntaxContext { let raw_id: u32 = Decodable::decode(d); if raw_id == 0 { @@ -1408,58 +1399,9 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } - let pending_ctxt = { - let mut inner = context.inner.lock(); - - // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between - // raw ids from different crate metadatas. - if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { - // This has already been decoded. - return ctxt; - } - - match inner.decoding.entry(raw_id) { - Entry::Occupied(ctxt_entry) => { - let pending_ctxt = *ctxt_entry.get(); - match context.local_in_progress.borrow_mut().entry(raw_id) { - // We're decoding this already on the current thread. Return here and let the - // function higher up the stack finish decoding to handle recursive cases. - // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok - // during reminder of the decoding process, it's certainly not ok after the - // top level decoding function returns. - SetEntry::Occupied(..) => return pending_ctxt, - // Some other thread is currently decoding this. - // Race with it (alternatively we could wait here). - // We cannot return this value, unlike in the recursive case above, because it - // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. - SetEntry::Vacant(entry) => { - entry.insert(); - pending_ctxt - } - } - } - Entry::Vacant(entry) => { - // We are the first thread to start decoding. Mark the current thread as being progress. - context.local_in_progress.borrow_mut().insert(raw_id); - - // Allocate and store SyntaxContext id *before* calling the decoder function, - // as the SyntaxContextData may reference itself. - let new_ctxt = HygieneData::with(|hygiene_data| { - // Push a dummy SyntaxContextData to ensure that nobody else can get the - // same ID as us. This will be overwritten after call `decode_data`. - hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); - SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) - }); - entry.insert(new_ctxt); - new_ctxt - } - } - }; - // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let ctxt_data = decode_data(d, raw_id); - let ctxt_key = ctxt_data.key(); + let ctxt_key = decode_ctxt_key(d, raw_id); let ctxt = HygieneData::with(|hygiene_data| { match hygiene_data.syntax_context_map.get(&ctxt_key) { @@ -1473,29 +1415,10 @@ pub fn decode_syntax_context SyntaxContext Some(&ctxt) => ctxt, // This is a completely new context. // Overwrite its placeholder data with our decoded data. - None => { - let ctxt_data_ref = - &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; - let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); - // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. - // We don't care what the encoding crate set this to - we want to resolve it - // from the perspective of the current compilation session. - ctxt_data_ref.dollar_crate_name = kw::DollarCrate; - // Make sure nothing weird happened while `decode_data` was running. - if !prev_ctxt_data.is_decode_placeholder() { - // Another thread may have already inserted the decoded data, - // but the decoded data should match. - assert_eq!(prev_ctxt_data, *ctxt_data_ref); - } - hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); - pending_ctxt - } + None => hygiene_data.apply_mark_internal(ctxt_key.0, ctxt_key.1, ctxt_key.2), } }); - // Mark the context as completed - context.local_in_progress.borrow_mut().remove(&raw_id); - let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; if inner.remapped_ctxts.len() < new_len { @@ -1507,7 +1430,7 @@ pub fn decode_syntax_context SyntaxContext ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { @@ -1515,7 +1438,7 @@ fn for_all_ctxts_in( ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() }); for (ctxt, data) in all_data.into_iter() { - f(ctxt.0, ctxt, &data); + f(ctxt.0, ctxt, &data.key()); } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index c80a33206fb4f..6fd6cb474693b 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#4 */; +struct S /* 0#5 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From cf451f08307168f32ffc74b478026e5e3ebc5ca9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Mar 2025 12:52:10 +0300 Subject: [PATCH 166/333] compiletest: Support matching diagnostics on lines below --- src/doc/rustc-dev-guide/src/tests/ui.md | 15 +++++++++++++++ src/tools/compiletest/src/errors.rs | 8 +++++++- tests/ui/parser/issues/issue-103451.rs | 2 +- tests/ui/parser/issues/issue-10636-2.rs | 2 +- .../issue-58094-missing-right-square-bracket.rs | 3 +-- ...ssue-58094-missing-right-square-bracket.stderr | 2 +- tests/ui/parser/issues/issue-62524.rs | 3 ++- tests/ui/parser/issues/issue-62524.stderr | 2 +- tests/ui/parser/issues/issue-62554.rs | 3 +-- tests/ui/parser/issues/issue-62554.stderr | 2 +- tests/ui/parser/issues/issue-62894.rs | 2 +- tests/ui/parser/issues/issue-62973.rs | 4 +++- tests/ui/parser/issues/issue-62973.stderr | 6 +++--- tests/ui/parser/issues/issue-63116.rs | 3 ++- tests/ui/parser/issues/issue-63116.stderr | 4 ++-- tests/ui/parser/issues/issue-63135.rs | 3 +-- tests/ui/parser/issues/issue-63135.stderr | 2 +- tests/ui/parser/issues/issue-81804.rs | 5 ++--- tests/ui/parser/issues/issue-81804.stderr | 4 ++-- tests/ui/parser/issues/issue-81827.rs | 7 ++----- tests/ui/parser/issues/issue-81827.stderr | 4 ++-- tests/ui/parser/issues/issue-84104.rs | 2 +- tests/ui/parser/issues/issue-84148-2.rs | 2 +- tests/ui/parser/issues/issue-88770.rs | 3 +-- tests/ui/parser/issues/issue-88770.stderr | 2 +- tests/ui/parser/mbe_missing_right_paren.rs | 2 +- tests/ui/parser/missing_right_paren.rs | 3 +-- tests/ui/parser/missing_right_paren.stderr | 2 +- tests/ui/parser/unbalanced-doublequote.rs | 4 +--- tests/ui/parser/unbalanced-doublequote.stderr | 2 +- tests/ui/parser/use-unclosed-brace.rs | 2 +- 31 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 98bb9dee76c57..1190c2646af10 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below): * `~|`: Associates the error level and message with the *same* line as the *previous comment*. This is more convenient than using multiple carets when there are multiple messages associated with the same line. +* `~v`: Associates the error level and message with the *next* error + annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv` + is three lines below the error annotation line. * `~?`: Used to match error levels and messages with errors not having line information. These can be placed on any line in the test file, but are conventionally placed at the end. @@ -273,6 +276,18 @@ fn main() { //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023] ``` +#### Positioned above error line + +Use the `//~v` idiom with number of v's in the string to indicate the number +of lines below. This is typically used in lexer or parser tests matching on errors like unclosed +delimiter or unclosed literal happening at the end of file. + +```rust,ignore +// ignore-tidy-trailing-newlines +//~v ERROR this file contains an unclosed delimiter +fn main((ؼ +``` + #### Error without line information Use `//~?` to match an error without line information. diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index c0566ef93b924..b68f817146fd7 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -122,13 +122,17 @@ fn parse_expected( // //~| // //~^ // //~^^^^^ + // //~v + // //~vvvvv // //~? // //[rev1]~ // //[rev1,rev2]~^^ static RE: OnceLock = OnceLock::new(); let captures = RE - .get_or_init(|| Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||\^*)").unwrap()) + .get_or_init(|| { + Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||[v\^]*)").unwrap() + }) .captures(line)?; match (test_revision, captures.name("revs")) { @@ -164,6 +168,8 @@ fn parse_expected( (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line"))) } else if line_num_adjust == "?" { (false, None) + } else if line_num_adjust.starts_with('v') { + (false, Some(line_num + line_num_adjust.len())) } else { (false, Some(line_num - line_num_adjust.len())) }; diff --git a/tests/ui/parser/issues/issue-103451.rs b/tests/ui/parser/issues/issue-103451.rs index 6b0928229e912..687dbc632d678 100644 --- a/tests/ui/parser/issues/issue-103451.rs +++ b/tests/ui/parser/issues/issue-103451.rs @@ -1,4 +1,4 @@ -//@ error-pattern: this file contains an unclosed delimiter struct R { } +//~vv ERROR this file contains an unclosed delimiter struct S { x: [u8; R diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs index 7200ea1f1dd1f..dcc03fec545cd 100644 --- a/tests/ui/parser/issues/issue-10636-2.rs +++ b/tests/ui/parser/issues/issue-10636-2.rs @@ -1,7 +1,7 @@ -//@ error-pattern: mismatched closing delimiter: `}` // FIXME(31528) we emit a bunch of silly errors here due to continuing past the // first one. This would be easy-ish to address by better recovery in tokenisation. +//~vvvvv ERROR mismatched closing delimiter: `}` pub fn trace_option(option: Option) { option.map(|some| 42; diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs index 7952d29c26024..0c0fbd7d5929b 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs @@ -1,5 +1,4 @@ // Fixed in #66054. // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter #[Ѕ \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr index 14f5469f6af94..28fd78d660ddc 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 | LL | #[Ѕ | - ^ diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs index a219f662cf78c..a8c7d6eb9fdd1 100644 --- a/tests/ui/parser/issues/issue-62524.rs +++ b/tests/ui/parser/issues/issue-62524.rs @@ -1,6 +1,7 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 1 previous error + #![allow(uncommon_codepoints)] +//~vv ERROR this file contains an unclosed delimiter y![ Ϥ, \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr index d83a49aedd6e8..c1ff6e7e7158e 100644 --- a/tests/ui/parser/issues/issue-62524.stderr +++ b/tests/ui/parser/issues/issue-62524.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62524.rs:6:3 + --> $DIR/issue-62524.rs:7:3 | LL | y![ | - unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs index 9f196e4b0d614..4a8a1684a412d 100644 --- a/tests/ui/parser/issues/issue-62554.rs +++ b/tests/ui/parser/issues/issue-62554.rs @@ -1,5 +1,4 @@ -//@ error-pattern:this file contains an unclosed delimiter - fn main() {} +//~v ERROR this file contains an unclosed delimiter fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr index d4aaef1618139..50515c4c574a1 100644 --- a/tests/ui/parser/issues/issue-62554.stderr +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62554.rs:5:89 + --> $DIR/issue-62554.rs:4:89 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { | - - - - -^ diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs index 5b1627a255372..c49cbe4b934dd 100644 --- a/tests/ui/parser/issues/issue-62894.rs +++ b/tests/ui/parser/issues/issue-62894.rs @@ -1,6 +1,6 @@ // Regression test for #62894, shouldn't crash. -//@ error-pattern: this file contains an unclosed delimiter +//~vvv ERROR this file contains an unclosed delimiter fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! fn main() {} diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs index 5c666d802fe44..a091e4eec1d92 100644 --- a/tests/ui/parser/issues/issue-62973.rs +++ b/tests/ui/parser/issues/issue-62973.rs @@ -1,8 +1,10 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 3 previous errors fn main() {} +//~vvv ERROR mismatched closing delimiter: `)` +//~vv ERROR mismatched closing delimiter: `)` +//~vvv ERROR this file contains an unclosed delimiter fn p() { match s { v, E { [) {) } diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr index 493183988e18b..ea3e2bebee404 100644 --- a/tests/ui/parser/issues/issue-62973.stderr +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:27 + --> $DIR/issue-62973.rs:8:27 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:30 + --> $DIR/issue-62973.rs:8:30 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-62973.rs:8:2 + --> $DIR/issue-62973.rs:10:2 | LL | fn p() { match s { v, E { [) {) } | - - - - missing open `(` for this delimiter diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs index 3be9606b4edbc..48abe639e8d97 100644 --- a/tests/ui/parser/issues/issue-63116.rs +++ b/tests/ui/parser/issues/issue-63116.rs @@ -1,3 +1,4 @@ // fixed by #66361 -//@ error-pattern: aborting due to 2 previous errors +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter impl W $DIR/issue-63116.rs:3:14 + --> $DIR/issue-63116.rs:4:14 | LL | impl W $DIR/issue-63116.rs:3:18 + --> $DIR/issue-63116.rs:4:18 | LL | impl W $DIR/issue-63135.rs:3:16 + --> $DIR/issue-63135.rs:2:16 | LL | fn i(n{...,f # | - - ^ diff --git a/tests/ui/parser/issues/issue-81804.rs b/tests/ui/parser/issues/issue-81804.rs index 7c9e6e905825b..57951ca5c4bc1 100644 --- a/tests/ui/parser/issues/issue-81804.rs +++ b/tests/ui/parser/issues/issue-81804.rs @@ -1,6 +1,5 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter - fn main() {} +//~vv ERROR mismatched closing delimiter: `}` +//~v ERROR this file contains an unclosed delimiter fn p([=(} diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr index 6caaaa792b196..f12c6a61ce5ec 100644 --- a/tests/ui/parser/issues/issue-81804.stderr +++ b/tests/ui/parser/issues/issue-81804.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `}` - --> $DIR/issue-81804.rs:6:8 + --> $DIR/issue-81804.rs:5:8 | LL | fn p([=(} | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p([=(} | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-81804.rs:6:11 + --> $DIR/issue-81804.rs:5:11 | LL | fn p([=(} | -- ^ diff --git a/tests/ui/parser/issues/issue-81827.rs b/tests/ui/parser/issues/issue-81827.rs index a2bd345fc050e..7dfeec13022a0 100644 --- a/tests/ui/parser/issues/issue-81827.rs +++ b/tests/ui/parser/issues/issue-81827.rs @@ -1,10 +1,7 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: mismatched closing delimiter: `]` - #![crate_name="0"] - - fn main() {} +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter fn r()->i{0|{#[cfg(r(0{]0 diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr index d12c74b4a3420..986ed6b7e70f9 100644 --- a/tests/ui/parser/issues/issue-81827.stderr +++ b/tests/ui/parser/issues/issue-81827.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `]` - --> $DIR/issue-81827.rs:10:23 + --> $DIR/issue-81827.rs:7:23 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - ^^ mismatched closing delimiter @@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0 | closing delimiter possibly meant for this error: this file contains an unclosed delimiter - --> $DIR/issue-81827.rs:10:27 + --> $DIR/issue-81827.rs:7:27 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - - - ^ diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs index bced05e684a7f..6baf882701d3c 100644 --- a/tests/ui/parser/issues/issue-84104.rs +++ b/tests/ui/parser/issues/issue-84104.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter #[i=i::<ښܖ< diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs index 560475bd32c3f..452279021ab9d 100644 --- a/tests/ui/parser/issues/issue-84148-2.rs +++ b/tests/ui/parser/issues/issue-84148-2.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter fn f(t:for<>t? diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs index ecc50481f65d7..0dd18435ce3ff 100644 --- a/tests/ui/parser/issues/issue-88770.rs +++ b/tests/ui/parser/issues/issue-88770.rs @@ -1,7 +1,6 @@ // Regression test for the ICE described in #88770. -//@ error-pattern:this file contains an unclosed delimiter - +//~vvvv ERROR this file contains an unclosed delimiter fn m(){print!("",(c for&g u e diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr index 5b54072d009fb..137cfea7e1d0d 100644 --- a/tests/ui/parser/issues/issue-88770.stderr +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-88770.rs:8:3 + --> $DIR/issue-88770.rs:7:3 | LL | fn m(){print!("",(c for&g | - - - unclosed delimiter diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs index 9c57b0ebcfc3d..851919316647d 100644 --- a/tests/ui/parser/mbe_missing_right_paren.rs +++ b/tests/ui/parser/mbe_missing_right_paren.rs @@ -1,3 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter macro_rules! abc(ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs index bbf4519a713ee..311a16c214c39 100644 --- a/tests/ui/parser/missing_right_paren.rs +++ b/tests/ui/parser/missing_right_paren.rs @@ -1,4 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter fn main((ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr index 4815f04fbce07..97ccb40a5a2a7 100644 --- a/tests/ui/parser/missing_right_paren.stderr +++ b/tests/ui/parser/missing_right_paren.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing_right_paren.rs:4:11 + --> $DIR/missing_right_paren.rs:3:11 | LL | fn main((ؼ | -- ^ diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs index d9c936186ea07..43e23a70271b0 100644 --- a/tests/ui/parser/unbalanced-doublequote.rs +++ b/tests/ui/parser/unbalanced-doublequote.rs @@ -1,6 +1,4 @@ -//@ error-pattern: unterminated double quote string - - +//~vv ERROR unterminated double quote string fn main() { " } diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr index d40b982da7c39..60057eddbb423 100644 --- a/tests/ui/parser/unbalanced-doublequote.stderr +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -1,5 +1,5 @@ error[E0765]: unterminated double quote string - --> $DIR/unbalanced-doublequote.rs:5:5 + --> $DIR/unbalanced-doublequote.rs:3:5 | LL | / " LL | | } diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs index 6679651fe47e2..aa52fe92ac1ba 100644 --- a/tests/ui/parser/use-unclosed-brace.rs +++ b/tests/ui/parser/use-unclosed-brace.rs @@ -1,4 +1,3 @@ -//@ error-pattern: this file contains an unclosed delimiter use foo::{bar, baz; use std::fmt::Display; @@ -7,4 +6,5 @@ mod bar { } mod baz { } +//~v ERROR this file contains an unclosed delimiter fn main() {} From 439048e074e1a4293e1839875e799329d92e4f81 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:21:51 +0100 Subject: [PATCH 167/333] `BackendRepr::is_signed`: comment why this may panics --- compiler/rustc_abi/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3f28dc7a1efae..843d5ca61dddb 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1462,7 +1462,8 @@ impl BackendRepr { !self.is_unsized() } - /// Returns `true` if this is a single signed integer scalar + /// Returns `true` if this is a single signed integer scalar. + /// Sanity check: panics if this is not a scalar type (see PR #70189). #[inline] pub fn is_signed(&self) -> bool { match self { From daeb449640b189069f76a13a4a208b1a6d6a32b6 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sat, 29 Mar 2025 12:39:06 +0100 Subject: [PATCH 168/333] Mark .pp files as Rust --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index d29c15fe712f3..8700d5d6dcff1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ *.h rust *.rs rust diff=rust *.fixed linguist-language=Rust +*.pp linguist-language=Rust *.mir linguist-language=Rust src/etc/installer/gfx/* binary src/vendor/** -text From 89c9c21b06c8661242b0545f690ac3e716327ac6 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 22 Mar 2025 11:24:33 +0000 Subject: [PATCH 169/333] Start using with_native_path in std::sys::fs --- library/std/src/fs.rs | 16 +-- library/std/src/sys/fs/mod.rs | 101 +++++++++++++++++-- library/std/src/sys/fs/unix.rs | 179 +++++++++++++++------------------ 3 files changed, 181 insertions(+), 115 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f9a360585e852..01fbd27e39914 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2362,7 +2362,7 @@ impl AsInner for DirEntry { #[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { - fs_imp::unlink(path.as_ref()) + fs_imp::remove_file(path.as_ref()) } /// Given a path, queries the file system to get information about a file, @@ -2401,7 +2401,7 @@ pub fn remove_file>(path: P) -> io::Result<()> { #[doc(alias = "stat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { - fs_imp::stat(path.as_ref()).map(Metadata) + fs_imp::metadata(path.as_ref()).map(Metadata) } /// Queries the metadata about a file without following symlinks. @@ -2436,7 +2436,7 @@ pub fn metadata>(path: P) -> io::Result { #[doc(alias = "lstat")] #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { - fs_imp::lstat(path.as_ref()).map(Metadata) + fs_imp::symlink_metadata(path.as_ref()).map(Metadata) } /// Renames a file or directory to a new name, replacing the original file if @@ -2590,7 +2590,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { #[doc(alias = "CreateHardLink", alias = "linkat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(original: P, link: Q) -> io::Result<()> { - fs_imp::link(original.as_ref(), link.as_ref()) + fs_imp::hard_link(original.as_ref(), link.as_ref()) } /// Creates a new symbolic link on the filesystem. @@ -2656,7 +2656,7 @@ pub fn soft_link, Q: AsRef>(original: P, link: Q) -> io::Re /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { - fs_imp::readlink(path.as_ref()) + fs_imp::read_link(path.as_ref()) } /// Returns the canonical, absolute form of a path with all intermediate @@ -2832,7 +2832,7 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "rmdir", alias = "RemoveDirectory")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { - fs_imp::rmdir(path.as_ref()) + fs_imp::remove_dir(path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use @@ -2959,7 +2959,7 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir>(path: P) -> io::Result { - fs_imp::readdir(path.as_ref()).map(ReadDir) + fs_imp::read_dir(path.as_ref()).map(ReadDir) } /// Changes the permissions found on a file or a directory. @@ -2995,7 +2995,7 @@ pub fn read_dir>(path: P) -> io::Result { #[doc(alias = "chmod", alias = "SetFileAttributes")] #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { - fs_imp::set_perm(path.as_ref(), perm.0) + fs_imp::set_permissions(path.as_ref(), perm.0) } impl DirBuilder { diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index c2e19eb393a16..3b176d0d16c44 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -1,28 +1,115 @@ #![deny(unsafe_op_in_unsafe_fn)] +use crate::io; +use crate::path::{Path, PathBuf}; + pub mod common; cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; - pub use unix::*; + use unix as imp; + pub use unix::{chown, fchown, lchown}; + #[cfg(not(target_os = "fuchsia"))] + pub use unix::chroot; + pub(crate) use unix::debug_assert_fd_is_open; + #[cfg(any(target_os = "linux", target_os = "android"))] + pub(crate) use unix::CachedFileMetadata; + use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path; } else if #[cfg(target_os = "windows")] { mod windows; - pub use windows::*; + use windows as imp; + pub use windows::{symlink_inner, junction_point}; } else if #[cfg(target_os = "hermit")] { mod hermit; - pub use hermit::*; + use hermit as imp; } else if #[cfg(target_os = "solid_asp3")] { mod solid; - pub use solid::*; + use solid as imp; } else if #[cfg(target_os = "uefi")] { mod uefi; - pub use uefi::*; + use uefi as imp; } else if #[cfg(target_os = "wasi")] { mod wasi; - pub use wasi::*; + use wasi as imp; } else { mod unsupported; - pub use unsupported::*; + use unsupported as imp; } } + +// FIXME: Replace this with platform-specific path conversion functions. +#[cfg(not(target_family = "unix"))] +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { + f(path) +} + +pub use imp::{ + DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, + ReadDir, +}; + +pub fn read_dir(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::readdir(path) +} + +pub fn remove_file(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::unlink) +} + +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new))) +} + +pub fn remove_dir(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::rmdir) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // FIXME: use with_native_path + imp::remove_dir_all(path) +} + +pub fn read_link(path: &Path) -> io::Result { + with_native_path(path, &imp::readlink) +} + +pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::symlink(original, link)) + }) +} + +pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::link(original, link)) + }) +} + +pub fn metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::stat) +} + +pub fn symlink_metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::lstat) +} + +pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> { + with_native_path(path, &|path| imp::set_perm(path, perm.clone())) +} + +pub fn canonicalize(path: &Path) -> io::Result { + with_native_path(path, &imp::canonicalize) +} + +pub fn copy(from: &Path, to: &Path) -> io::Result { + // FIXME: use with_native_path + imp::copy(from, to) +} + +pub fn exists(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::exists(path) +} diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 7c3ed8029f7dd..e32392ca94eb2 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -926,7 +926,7 @@ impl DirEntry { miri ))] pub fn metadata(&self) -> io::Result { - lstat(&self.path()) + run_path_with_cstr(&self.path(), &lstat) } #[cfg(any( @@ -1653,7 +1653,7 @@ impl fmt::Debug for File { fn get_path(fd: c_int) -> Option { let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - readlink(&p).ok() + run_path_with_cstr(&p, &readlink).ok() } #[cfg(any(target_vendor = "apple", target_os = "netbsd"))] @@ -1671,7 +1671,7 @@ impl fmt::Debug for File { // fallback to procfs as last resort let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - return readlink(&p).ok(); + return run_path_with_cstr(&p, &readlink).ok() } else { return None; } @@ -1826,127 +1826,106 @@ pub fn readdir(path: &Path) -> io::Result { } } -pub fn unlink(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())) +pub fn unlink(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()) } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - run_path_with_cstr(old, &|old| { - run_path_with_cstr(new, &|new| { - cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) - }) - }) +pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())) +pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { + cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())) +pub fn rmdir(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()) } -pub fn readlink(p: &Path) -> io::Result { - run_path_with_cstr(p, &|c_path| { - let p = c_path.as_ptr(); - - let mut buf = Vec::with_capacity(256); +pub fn readlink(c_path: &CStr) -> io::Result { + let p = c_path.as_ptr(); - loop { - let buf_read = - cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? - as usize; + let mut buf = Vec::with_capacity(256); - unsafe { - buf.set_len(buf_read); - } + loop { + let buf_read = + cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize; - if buf_read != buf.capacity() { - buf.shrink_to_fit(); + unsafe { + buf.set_len(buf_read); + } - return Ok(PathBuf::from(OsString::from_vec(buf))); - } + if buf_read != buf.capacity() { + buf.shrink_to_fit(); - // Trigger the internal buffer resizing logic of `Vec` by requiring - // more space than the current capacity. The length is guaranteed to be - // the same as the capacity due to the if statement above. - buf.reserve(1); + return Ok(PathBuf::from(OsString::from_vec(buf))); } - }) + + // Trigger the internal buffer resizing logic of `Vec` by requiring + // more space than the current capacity. The length is guaranteed to be + // the same as the capacity due to the if statement above. + buf.reserve(1); + } } -pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) - }) - }) +pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> { + cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) } -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { - // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves - // it implementation-defined whether `link` follows symlinks, so rely on the - // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. - // Android has `linkat` on newer versions, but we happen to know `link` - // always has the correct behavior, so it's here as well. - cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; - } else { - // Where we can, use `linkat` instead of `link`; see the comment above - // this one for details on why. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; - } - } - Ok(()) - }) - }) +pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { + // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves + // it implementation-defined whether `link` follows symlinks, so rely on the + // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. + // Android has `linkat` on newer versions, but we happen to know `link` + // always has the correct behavior, so it's here as well. + cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + } else { + // Where we can, use `linkat` instead of `link`; see the comment above + // this one for details on why. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; + } + } + Ok(()) } -pub fn stat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn stat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn lstat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn lstat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn canonicalize(p: &Path) -> io::Result { - let r = run_path_with_cstr(p, &|path| unsafe { - Ok(libc::realpath(path.as_ptr(), ptr::null_mut())) - })?; +pub fn canonicalize(path: &CStr) -> io::Result { + let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) }; if r.is_null() { return Err(io::Error::last_os_error()); } @@ -2324,19 +2303,19 @@ mod remove_dir_impl { Ok(()) } - fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + fn remove_dir_all_modern(p: &CStr) -> io::Result<()> { // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks. let attr = lstat(p)?; if attr.file_type().is_symlink() { - crate::fs::remove_file(p) + super::unlink(p) } else { - run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p)) + remove_dir_all_recursive(None, &p) } } pub fn remove_dir_all(p: &Path) -> io::Result<()> { - remove_dir_all_modern(p) + run_path_with_cstr(p, &remove_dir_all_modern) } } From 02899f86f5b6d3aa87e9809fa3ee0d91fa3df574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sat, 29 Mar 2025 17:27:33 +0100 Subject: [PATCH 170/333] Properly document FakeReads --- compiler/rustc_middle/src/mir/syntax.rs | 112 ++++++++++++++++++------ 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4f86703e95376..6d6e6a1f185b5 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> { /// See [`Rvalue`] documentation for details on each of those. Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), - /// This represents all the reading that a pattern match may do (e.g., inspecting constants and - /// discriminant values), and the kind of pattern it comes from. This is in order to adapt - /// potential error messages to these specific patterns. + /// When executed at runtime, this is a nop. /// - /// Note that this also is emitted for regular `let` bindings to ensure that locals that are - /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` + /// During static analysis, a fake read: + /// - requires that the value being read is initialized (or, in the case + /// of closures, that it was fully initialized at some point in the past) + /// - constitutes a use of a value for the purposes of NLL (i.e. if the + /// value being fake-read is a reference, the lifetime of that reference + /// will be extended to cover the `FakeRead`) + /// - but, unlike an actual read, does *not* invalidate any exclusive + /// borrows. /// - /// When executed at runtime this is a nop. + /// See [`FakeReadCause`] for more details on the situations in which a + /// `FakeRead` is emitted. /// /// Disallowed after drop elaboration. FakeRead(Box<(FakeReadCause, Place<'tcx>)>), @@ -518,28 +523,59 @@ pub enum RetagKind { /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] pub enum FakeReadCause { - /// Inject a fake read of the borrowed input at the end of each guards - /// code. + /// A fake read injected into a match guard to ensure that the discriminants + /// that are being matched on aren't modified while the match guard is being + /// evaluated. + /// + /// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is + /// inserted for each discriminant accessed in the entire `match` statement. + /// + /// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is + /// inserted to keep the fake borrows alive until that point. /// /// This should ensure that you cannot change the variant for an enum while /// you are in the midst of matching on it. ForMatchGuard, - /// `let x: !; match x {}` doesn't generate any read of x so we need to - /// generate a read of x to check that it is initialized and safe. + /// Fake read of the scrutinee of a `match` or destructuring `let` + /// (i.e. `let` with non-trivial pattern). + /// + /// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)` + /// and insert it into the `otherwise_block` (which is supposed to be + /// unreachable for irrefutable pattern-matches like `match` or `let`). + /// + /// This is necessary because `let x: !; match x {}` doesn't generate any + /// actual read of x, so we need to generate a `FakeRead` to check that it + /// is initialized. /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional LocalDefId will be None. + /// If the `FakeRead(ForMatchedPlace)` is being performed with a closure + /// that doesn't capture the required upvars, the `FakeRead` within the + /// closure is omitted entirely. + /// + /// To make sure that this is still sound, if a closure matches against + /// a Place starting with an Upvar, we hoist the `FakeRead` to the + /// definition point of the closure. + /// + /// If the `FakeRead` comes from being hoisted out of a closure like this, + /// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`. // // We can use LocalDefId here since fake read statements are removed // before codegen in the `CleanupNonCodegenStatements` pass. ForMatchedPlace(Option), - /// A fake read of the RefWithinGuard version of a bind-by-value variable - /// in a match guard to ensure that its value hasn't change by the time - /// we create the OutsideGuard version. + /// A fake read injected into a match guard to ensure that the places + /// bound by the pattern are immutable for the duration of the match guard. + /// + /// Within a match guard, references are created for each place that the + /// pattern creates a binding for — this is known as the `RefWithinGuard` + /// version of the variables. To make sure that the references stay + /// alive until the end of the match guard, and properly prevent the + /// places in question from being modified, a `FakeRead(ForGuardBinding)` + /// is inserted at the end of the match guard. + /// + /// For details on how these references are created, see the extensive + /// documentation on `bind_matched_candidate_for_guard` in + /// `rustc_mir_build`. ForGuardBinding, /// Officially, the semantics of @@ -552,22 +588,42 @@ pub enum FakeReadCause { /// However, if we see the simple pattern `let var = `, we optimize this to /// evaluate `` directly into the variable `var`. This is mostly unobservable, /// but in some cases it can affect the borrow checker, as in #53695. - /// Therefore, we insert a "fake read" here to ensure that we get - /// appropriate errors. /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional DefId will be None. + /// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let` + /// with a trivial pattern. + /// + /// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)` + /// is supposed to mean. If it was accurate to what MIR lowering does, + /// would it even make sense to hoist these out of closures like + /// `ForMatchedPlace`? ForLet(Option), - /// If we have an index expression like + /// Currently, index expressions overloaded through the `Index` trait + /// get lowered differently than index expressions with builtin semantics + /// for arrays and slices — the latter will emit code to perform + /// bound checks, and then return a MIR place that will only perform the + /// indexing "for real" when it gets incorporated into an instruction. + /// + /// This is observable in the fact that the following compiles: + /// + /// ``` + /// fn f(x: &mut [&mut [u32]], i: usize) { + /// x[i][x[i].len() - 1] += 1; + /// } + /// ``` + /// + /// However, we need to be careful to not let the user invalidate the + /// bound check with an expression like + /// + /// `(*x)[1][{ x = y; 4}]` /// - /// (*x)[1][{ x = y; 4}] + /// Here, the first bounds check would be invalidated when we evaluate the + /// second index expression. To make sure that this doesn't happen, we + /// create a fake borrow of `x` and hold it while we evaluate the second + /// index. /// - /// then the first bounds check is invalidated when we evaluate the second - /// index expression. Thus we create a fake borrow of `x` across the second - /// indexer, which will cause a borrow check error. + /// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its + /// scope. ForIndex, } From 865a5a7e164950cf728439d12efb762e29c46c2c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Mar 2025 20:02:01 +0200 Subject: [PATCH 171/333] mention that know-bug test directive takes arguments --- src/doc/rustc-dev-guide/src/tests/ui.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index c8536b0045cfd..728ea3de418a6 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -415,6 +415,14 @@ reasons, including: can alert the developer so they know that the associated issue has been fixed and can possibly be closed. +This directive takes comma-separated issue numbers as arguments, or `"unknown"`: + +- `//@ known-bug: #123, #456` (when the issues are on rust-lang/rust) +- `//@ known-bug: rust-lang/chalk#123456` + (allows arbitrary text before the `#`, which is useful when the issue is on another repo) +- `//@ known-bug: unknown` + (when there is no known issue yet; preferrably open one if it does not already exist) + Do not include [error annotations](#error-annotations) in a test with `known-bug`. The test should still include other normal directives and stdout/stderr files. From 1faf7ff9a434de8995e97e7372408489ce87050e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 29 Mar 2025 23:52:57 +0200 Subject: [PATCH 172/333] update rustc-{driver,interface} examples --- .../rustc-dev-guide/examples/rustc-driver-example.rs | 11 +++++------ .../examples/rustc-driver-interacting-with-the-ast.rs | 4 ++-- .../examples/rustc-interface-example.rs | 8 ++++---- .../examples/rustc-interface-getting-diagnostics.rs | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 35dd07dd13657..fb8b13ad154ce 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{Compilation, run_compiler}; +use rustc_driver::{run_compiler, Compilation}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; @@ -71,13 +71,12 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. - for id in tcx.hir_free_items(){ + for id in tcx.hir_free_items() { let item = &tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 2a43ba476e1ea..b0c62d5b4bbb0 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -71,7 +71,7 @@ impl rustc_driver::Callbacks for MyCallbacks { fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Iterate over the top-level items in the crate, looking for the main function. - for id in tcx.hir_free_items(){ + for id in tcx.hir_free_items() { let item = &tcx.hir_item(id); // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn { body, .. } = item.kind { diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 11125caec7040..360f70c8e865a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] @@ -67,10 +67,10 @@ fn main() { for id in tcx.hir_free_items() { let item = tcx.hir_item(id); match item.kind { - rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => { - let name = item.ident; + rustc_hir::ItemKind::Static(ident, ..) + | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); - println!("{name:?}:\t{ty:?}") + println!("{ident:?}:\t{ty:?}") } _ => (), } diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 9bb93ab495878..2512ba3c3f924 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -1,4 +1,4 @@ -// Tested with nightly-2025-03-08 +// Tested with nightly-2025-03-28 #![feature(rustc_private)] From 471a2a8b87d8b5ba03a43a2c067dd322c1f5e7af Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 30 Mar 2025 00:16:39 +0200 Subject: [PATCH 173/333] example assumes a static exists This was removed, likely by mistake, during a refactor. --- src/doc/rustc-dev-guide/examples/rustc-driver-example.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index fb8b13ad154ce..0e3450086ba5b 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -34,9 +34,9 @@ impl rustc_span::source_map::FileLoader for MyFileLoader { fn read_file(&self, path: &Path) -> io::Result { if path == Path::new("main.rs") { Ok(r#" +static MESSAGE: &str = "Hello, World!"; fn main() { - let message = "Hello, World!"; - println!("{message}"); + println!("{MESSAGE}"); } "# .to_string()) From 9302f4d94f97750e84a47eaf5ac180feaaaafa3a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 30 Mar 2025 00:31:44 +0200 Subject: [PATCH 174/333] add rustfmt settings file --- .../rustc-dev-guide/ci/date-check/src/main.rs | 155 ++++-------------- .../examples/rustc-driver-example.rs | 2 +- .../rustc-driver-interacting-with-the-ast.rs | 2 +- src/doc/rustc-dev-guide/rustfmt.toml | 7 + 4 files changed, 39 insertions(+), 127 deletions(-) create mode 100644 src/doc/rustc-dev-guide/rustfmt.toml diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs index 5ab3e6c8b65a8..9af69dbbf3f5c 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs @@ -1,11 +1,8 @@ -use std::{ - collections::BTreeMap, - convert::TryInto as _, - env, fmt, fs, - path::{Path, PathBuf}, - process, - str::FromStr, -}; +use std::collections::BTreeMap; +use std::convert::TryInto as _; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use std::{env, fmt, fs, process}; use chrono::{Datelike as _, Month, TimeZone as _, Utc}; use glob::glob; @@ -19,19 +16,13 @@ struct Date { impl Date { fn months_since(self, other: Date) -> Option { - let self_chrono = Utc - .with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0) - .unwrap(); - let other_chrono = Utc - .with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0) - .unwrap(); + let self_chrono = + Utc.with_ymd_and_hms(self.year.try_into().unwrap(), self.month, 1, 0, 0, 0).unwrap(); + let other_chrono = + Utc.with_ymd_and_hms(other.year.try_into().unwrap(), other.month, 1, 0, 0, 0).unwrap(); let duration_since = self_chrono.signed_duration_since(other_chrono); let months_since = duration_since.num_days() / 30; - if months_since < 0 { - None - } else { - Some(months_since.try_into().unwrap()) - } + if months_since < 0 { None } else { Some(months_since.try_into().unwrap()) } } } @@ -66,26 +57,18 @@ fn collect_dates_from_file(date_regex: &Regex, text: &str) -> Vec<(usize, Date)> date_regex .captures_iter(text) .filter_map(|cap| { - if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = ( - cap.name("m1"), - cap.name("y1"), - cap.name("m2"), - cap.name("y2"), - ) { + if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = + (cap.name("m1"), cap.name("y1"), cap.name("m2"), cap.name("y2")) + { let year = year.as_str().parse().expect("year"); - let month = Month::from_str(month.as_str()) - .expect("month") - .number_from_month(); + let month = Month::from_str(month.as_str()).expect("month").number_from_month(); Some((cap.get(0).expect("all").range(), Date { year, month })) } else { None } }) .map(|(byte_range, date)| { - line += text[end_of_last_cap..byte_range.end] - .chars() - .filter(|c| *c == '\n') - .count(); + line += text[end_of_last_cap..byte_range.end].chars().filter(|c| *c == '\n').count(); end_of_last_cap = byte_range.end; (line, date) }) @@ -138,10 +121,7 @@ fn main() { let root_dir_path = Path::new(&root_dir); let glob_pat = format!("{}/**/*.md", root_dir); let today_chrono = Utc::now().date_naive(); - let current_month = Date { - year: today_chrono.year_ce().1, - month: today_chrono.month(), - }; + let current_month = Date { year: today_chrono.year_ce().1, month: today_chrono.month() }; let dates_by_file = collect_dates(glob(&glob_pat).unwrap().map(Result::unwrap)); let dates_by_file: BTreeMap<_, _> = @@ -173,10 +153,7 @@ fn main() { println!(); for (path, dates) in dates_by_file { - println!( - "- {}", - path.strip_prefix(&root_dir_path).unwrap_or(&path).display(), - ); + println!("- {}", path.strip_prefix(&root_dir_path).unwrap_or(&path).display(),); for (line, date) in dates { println!(" - [ ] line {}: {}", line, date); } @@ -191,14 +168,8 @@ mod tests { #[test] fn test_months_since() { - let date1 = Date { - year: 2020, - month: 3, - }; - let date2 = Date { - year: 2021, - month: 1, - }; + let date1 = Date { year: 2020, month: 3 }; + let date2 = Date { year: 2021, month: 1 }; assert_eq!(date2.months_since(date1), Some(10)); } @@ -273,83 +244,17 @@ Test8 assert_eq!( collect_dates_from_file(&make_date_regex(), text), vec![ - ( - 3, - Date { - year: 2021, - month: 1, - } - ), - ( - 6, - Date { - year: 2021, - month: 2, - } - ), - ( - 9, - Date { - year: 2021, - month: 3, - } - ), - ( - 11, - Date { - year: 2021, - month: 4, - } - ), - ( - 17, - Date { - year: 2021, - month: 5, - } - ), - ( - 20, - Date { - year: 2021, - month: 1, - } - ), - ( - 23, - Date { - year: 2021, - month: 2, - } - ), - ( - 26, - Date { - year: 2021, - month: 3, - } - ), - ( - 28, - Date { - year: 2021, - month: 4, - } - ), - ( - 34, - Date { - year: 2021, - month: 5, - } - ), - ( - 38, - Date { - year: 2021, - month: 6, - } - ), + (3, Date { year: 2021, month: 1 }), + (6, Date { year: 2021, month: 2 }), + (9, Date { year: 2021, month: 3 }), + (11, Date { year: 2021, month: 4 }), + (17, Date { year: 2021, month: 5 }), + (20, Date { year: 2021, month: 1 }), + (23, Date { year: 2021, month: 2 }), + (26, Date { year: 2021, month: 3 }), + (28, Date { year: 2021, month: 4 }), + (34, Date { year: 2021, month: 5 }), + (38, Date { year: 2021, month: 6 }), ], ); } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 0e3450086ba5b..db6ac18578542 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{run_compiler, Compilation}; +use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index b0c62d5b4bbb0..c0d7f977d3500 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{run_compiler, Compilation}; +use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; diff --git a/src/doc/rustc-dev-guide/rustfmt.toml b/src/doc/rustc-dev-guide/rustfmt.toml new file mode 100644 index 0000000000000..b285329c78e61 --- /dev/null +++ b/src/doc/rustc-dev-guide/rustfmt.toml @@ -0,0 +1,7 @@ +# matches that of rust-lang/rust +style_edition = "2024" +use_small_heuristics = "Max" +merge_derives = false +group_imports = "StdExternalCrate" +imports_granularity = "Module" +use_field_init_shorthand = true From 2dfd2a2a242e920b7378328b87f901652d9d81be Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 30 Mar 2025 00:39:55 +0300 Subject: [PATCH 175/333] Remove attribute `#[rustc_error]` --- compiler/rustc_feature/src/builtin_attrs.rs | 6 +-- compiler/rustc_interface/messages.ftl | 6 --- compiler/rustc_interface/src/errors.rs | 14 ------- compiler/rustc_interface/src/passes.rs | 42 +++---------------- compiler/rustc_middle/src/util/bug.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- .../crates/hir-expand/src/inert_attr_macro.rs | 4 -- tests/incremental/delayed_span_bug.rs | 4 +- .../bound-lifetime-constrained.ok.stderr | 8 ---- .../bound-lifetime-constrained.rs | 5 +-- .../bound-lifetime-in-binding-only.ok.stderr | 8 ---- .../bound-lifetime-in-binding-only.rs | 5 +-- .../bound-lifetime-in-return-only.ok.stderr | 8 ---- .../bound-lifetime-in-return-only.rs | 5 +-- .../borrowck-report-with-custom-diagnostic.rs | 3 +- ...rowck-report-with-custom-diagnostic.stderr | 6 +-- tests/ui/borrowck/mut-borrow-outside-loop.rs | 4 +- tests/ui/codemap_tests/issue-11715.rs | 3 +- tests/ui/codemap_tests/issue-11715.stderr | 2 +- tests/ui/consts/async-block.rs | 5 +-- .../ui/consts/async-block.with_feature.stderr | 8 ---- .../allow-non-lint-warnings.rs | 10 +++-- ...llow-non-lint-warnings.without_flag.stderr | 10 +++-- .../feature-gate-rustc-attrs-1.rs | 1 - .../feature-gate-rustc-attrs-1.stderr | 13 +----- tests/ui/mir/issue-75053.rs | 5 +-- tests/ui/mir/issue-75053.stderr | 8 ---- tests/ui/proc-macro/no-macro-use-attr.rs | 5 +-- tests/ui/proc-macro/no-macro-use-attr.stderr | 8 +--- .../feature-gate.no_gate.stderr | 2 +- .../feature-gate.rs | 6 +-- .../feature-gate.with_gate.stderr | 8 ---- tests/ui/rustc-error.rs | 6 --- tests/ui/rustc-error.stderr | 8 ---- tests/ui/span/range-2.rs | 4 +- .../regionck-unboxed-closure-lifetimes.rs | 3 +- .../regionck-unboxed-closure-lifetimes.stderr | 2 +- tests/ui/suggestions/attribute-typos.rs | 4 +- tests/ui/suggestions/attribute-typos.stderr | 10 ++--- .../const-traits/feature-gate.gated.stderr | 8 ---- tests/ui/traits/const-traits/feature-gate.rs | 5 +-- tests/ui/treat-err-as-bug/span_delayed_bug.rs | 2 +- .../treat-err-as-bug/span_delayed_bug.stderr | 2 +- tests/ui/type-alias-impl-trait/issue-53096.rs | 6 +-- .../type-alias-impl-trait/issue-53096.stderr | 8 ---- tests/ui/type-alias-impl-trait/issue-60407.rs | 6 +-- .../type-alias-impl-trait/issue-60407.stderr | 8 ---- 47 files changed, 72 insertions(+), 236 deletions(-) delete mode 100644 tests/ui/associated-types/bound-lifetime-constrained.ok.stderr delete mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr delete mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr delete mode 100644 tests/ui/consts/async-block.with_feature.stderr delete mode 100644 tests/ui/mir/issue-75053.stderr delete mode 100644 tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr delete mode 100644 tests/ui/rustc-error.rs delete mode 100644 tests/ui/rustc-error.stderr delete mode 100644 tests/ui/traits/const-traits/feature-gate.gated.stderr delete mode 100644 tests/ui/type-alias-impl-trait/issue-53096.stderr delete mode 100644 tests/ui/type-alias-impl-trait/issue-60407.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 6fe65c88f712a..1e33e2e9393f7 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1087,9 +1087,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_error, Normal, - template!(Word, List: "delayed_bug_from_inside_query"), - WarnFollowingWordOnly, EncodeCrossCrate::Yes + TEST, rustc_delayed_bug_from_inside_query, Normal, + template!(Word), + WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_dump_user_args, Normal, template!(Word), diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index ffbe708ba8daa..4b9c71d71725c 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -50,11 +50,5 @@ interface_out_dir_error = interface_proc_macro_crate_panic_abort = building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic -interface_rustc_error_fatal = - fatal error triggered by #[rustc_error] - -interface_rustc_error_unexpected_annotation = - unexpected annotation used with `#[rustc_error(...)]`! - interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index ef0235b5577f1..6b39b4f18911c 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -73,20 +73,6 @@ pub struct TempsDirError; #[diag(interface_out_dir_error)] pub struct OutDirError; -#[derive(Diagnostic)] -#[diag(interface_rustc_error_fatal)] -pub struct RustcErrorFatal { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(interface_rustc_error_unexpected_annotation)] -pub struct RustcErrorUnexpectedAnnotation { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(interface_failed_writing_file)] pub struct FailedWritingFile<'a> { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2440f0639c8a6..93013c8b3f612 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1067,48 +1067,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { }); } -/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used -/// to write UI tests that actually test that compilation succeeds without reporting -/// an error. -fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { - let Some((def_id, _)) = tcx.entry_fn(()) else { return }; - for attr in tcx.get_attrs(def_id, sym::rustc_error) { - match attr.meta_item_list() { - // Check if there is a `#[rustc_error(delayed_bug_from_inside_query)]`. - Some(list) - if list.iter().any(|list_item| { - matches!( - list_item.ident().map(|i| i.name), - Some(sym::delayed_bug_from_inside_query) - ) - }) => - { - tcx.ensure_ok().trigger_delayed_bug(def_id); - } - - // Bare `#[rustc_error]`. - None => { - tcx.dcx().emit_fatal(errors::RustcErrorFatal { span: tcx.def_span(def_id) }); - } - - // Some other attribute. - Some(_) => { - tcx.dcx().emit_warn(errors::RustcErrorUnexpectedAnnotation { - span: tcx.def_span(def_id), - }); - } - } - } -} - /// Runs the codegen backend, after which the AST and analysis can /// be discarded. pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, ) -> Box { - // Hook for UI tests. - check_for_rustc_errors_attr(tcx); + // Hook for tests. + if let Some((def_id, _)) = tcx.entry_fn(()) + && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query) + { + tcx.ensure_ok().trigger_delayed_bug(def_id); + } // Don't run this test assertions when not doing codegen. Compiletest tries to build // build-fail tests in check mode first and expects it to not give an error in that case. diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index 7dda68b8393a1..c4357fae10463 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -49,7 +49,7 @@ fn opt_span_bug_fmt>( pub fn trigger_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) { tcx.dcx().span_delayed_bug( tcx.def_span(key), - "delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)]", + "delayed bug triggered by #[rustc_delayed_bug_from_inside_query]", ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712cd..409497c169e26 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1771,6 +1771,7 @@ symbols! { rustc_deallocator, rustc_def_path, rustc_default_body_unstable, + rustc_delayed_bug_from_inside_query, rustc_deny_explicit_impl, rustc_deprecated_safe_2024, rustc_diagnostic_item, @@ -1787,7 +1788,6 @@ symbols! { rustc_dump_user_args, rustc_dump_vtable, rustc_effective_visibility, - rustc_error, rustc_evaluate_where_clauses, rustc_expected_cgu_reuse, rustc_force_inline, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 9a7a1a01a09cd..4c4174e2680f5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -665,10 +665,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), - rustc_attr!( - TEST, rustc_error, Normal, - template!(Word, List: "delayed_bug_from_inside_query"), WarnFollowingWordOnly - ), rustc_attr!(TEST, rustc_dump_user_args, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing), rustc_attr!( diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs index 958e9dd07e2d5..1534aca5dddf2 100644 --- a/tests/incremental/delayed_span_bug.rs +++ b/tests/incremental/delayed_span_bug.rs @@ -1,8 +1,8 @@ //@ revisions: cfail1 cfail2 //@ should-ice -//@ error-pattern: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] +//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] #![feature(rustc_attrs)] -#[rustc_error(delayed_bug_from_inside_query)] +#[rustc_delayed_bug_from_inside_query] fn main() {} diff --git a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr b/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr deleted file mode 100644 index 9082044fe068b..0000000000000 --- a/tests/ui/associated-types/bound-lifetime-constrained.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-constrained.rs:48:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs index 1dc3b2f5c2b77..3a5a77f57f23d 100644 --- a/tests/ui/associated-types/bound-lifetime-constrained.rs +++ b/tests/ui/associated-types/bound-lifetime-constrained.rs @@ -1,7 +1,7 @@ //@ revisions: func object clause ok +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] trait Foo<'a> { type Item; @@ -44,5 +44,4 @@ fn clause2() where T: for<'a> Fn() -> <() as Foo<'a>>::Item { //[clause]~^ ERROR `Output` references lifetime `'a` } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr deleted file mode 100644 index 435e224bd8922..0000000000000 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-in-binding-only.rs:71:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs index e973e58b629fd..2401fe0ef1f7b 100644 --- a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs @@ -1,7 +1,7 @@ //@ revisions: angle paren ok elision +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] #![feature(unboxed_closures)] trait Foo { @@ -67,5 +67,4 @@ fn ok2 Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() { fn ok3() where for<'a> Parameterized<'a>: Foo { } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr deleted file mode 100644 index 1815a7be7ee81..0000000000000 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/bound-lifetime-in-return-only.rs:49:1 - | -LL | fn main() { } - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.rs b/tests/ui/associated-types/bound-lifetime-in-return-only.rs index bf3aa6149cce3..8a28f5b778610 100644 --- a/tests/ui/associated-types/bound-lifetime-in-return-only.rs +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.rs @@ -1,7 +1,7 @@ //@ revisions: sig local structure ok elision +//@[ok] check-pass #![allow(dead_code)] -#![feature(rustc_attrs)] #![feature(unboxed_closures)] trait Foo { @@ -45,5 +45,4 @@ fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) { fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) { } -#[rustc_error] -fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] +fn main() { } diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs index 6f323d9122753..9d323bf0324ee 100644 --- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs @@ -1,6 +1,5 @@ -#![feature(rustc_attrs)] #![allow(dead_code)] -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { // Original borrow ends at end of function let mut x = 1; let y = &mut x; diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr index db73d4c04acc8..444a74cbfcf59 100644 --- a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:7:13 | LL | let y = &mut x; | ------ mutable borrow occurs here @@ -11,7 +11,7 @@ LL | y.use_mut(); | - mutable borrow later used here error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:20:21 | LL | let y = &x; | -- immutable borrow occurs here @@ -23,7 +23,7 @@ LL | y.use_ref(); | - immutable borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17 + --> $DIR/borrowck-report-with-custom-diagnostic.rs:35:17 | LL | let y = &mut x; | ------ first mutable borrow occurs here diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.rs b/tests/ui/borrowck/mut-borrow-outside-loop.rs index c02bfbf873907..3cc362def38f3 100644 --- a/tests/ui/borrowck/mut-borrow-outside-loop.rs +++ b/tests/ui/borrowck/mut-borrow-outside-loop.rs @@ -1,6 +1,6 @@ // ensure borrowck messages are correct outside special case -#![feature(rustc_attrs)] -fn main() { #![rustc_error] // rust-lang/rust#49855 + +fn main() { let mut void = (); let first = &mut void; diff --git a/tests/ui/codemap_tests/issue-11715.rs b/tests/ui/codemap_tests/issue-11715.rs index 617d57ff75a48..d0daaf444b34d 100644 --- a/tests/ui/codemap_tests/issue-11715.rs +++ b/tests/ui/codemap_tests/issue-11715.rs @@ -1,5 +1,4 @@ -#![feature(rustc_attrs)] -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let mut x = "foo"; let y = &mut x; let z = &mut x; //~ ERROR cannot borrow diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr index 5d0cf718761c4..6b330560adb90 100644 --- a/tests/ui/codemap_tests/issue-11715.stderr +++ b/tests/ui/codemap_tests/issue-11715.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/issue-11715.rs:5:13 + --> $DIR/issue-11715.rs:4:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs index 40be4d195d4b4..1211a150f7d5a 100644 --- a/tests/ui/consts/async-block.rs +++ b/tests/ui/consts/async-block.rs @@ -2,8 +2,8 @@ //@ edition:2018 //@ revisions: with_feature without_feature +//@[with_feature] check-pass -#![feature(rustc_attrs)] #![cfg_attr(with_feature, feature(const_async_blocks))] use std::future::Future; @@ -15,5 +15,4 @@ const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 }; static _FUT: &(dyn Future + Sync) = &async {}; //[without_feature]~^ `async` block -#[rustc_error] -fn main() {} //[with_feature]~ fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr deleted file mode 100644 index 8228fa29edf17..0000000000000 --- a/tests/ui/consts/async-block.with_feature.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/async-block.rs:19:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs index 8980ef9c4220f..f928e1122894d 100644 --- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.rs @@ -13,14 +13,16 @@ //! - Original impl PR: . //! - RFC 507 "Release channels": //! . -#![feature(rustc_attrs)] //@ revisions: without_flag with_flag +//@ check-pass +//@ compile-flags: -Zunleash-the-miri-inside-of-you //@[with_flag] compile-flags: -Awarnings -//@ check-pass +fn non_constant() {} +const fn constant() { non_constant() } -#[rustc_error(warn)] fn main() {} -//[without_flag]~^ WARN unexpected annotation used with `#[rustc_error(...)]`! + +//[without_flag]~? WARN skipping const checks diff --git a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr index 3f33ccbd1c9f9..08ae11fc18a9a 100644 --- a/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr +++ b/tests/ui/diagnostic-flags/allow-non-lint-warnings.without_flag.stderr @@ -1,8 +1,10 @@ -warning: unexpected annotation used with `#[rustc_error(...)]`! - --> $DIR/allow-non-lint-warnings.rs:25:1 +warning: skipping const checks | -LL | fn main() {} - | ^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/allow-non-lint-warnings.rs:24:23 + | +LL | const fn constant() { non_constant() } + | ^^^^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs index 7ae4a8d911bad..025b4b52f12fe 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -1,7 +1,6 @@ // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable -#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable #[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 8c3a8eb2df875..0f760e0602d2f 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -7,18 +7,9 @@ LL | #[rustc_variance] = help: add `#![feature(rustc_attrs)]` 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 `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 - | -LL | #[rustc_error] - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` 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 `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable (note that the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized) - --> $DIR/feature-gate-rustc-attrs-1.rs:5:1 + --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 | LL | #[rustc_nonnull_optimization_guaranteed] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,6 +17,6 @@ LL | #[rustc_nonnull_optimization_guaranteed] = help: add `#![feature(rustc_attrs)]` 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 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs index 9b247fa543490..4bc481b82e53e 100644 --- a/tests/ui/mir/issue-75053.rs +++ b/tests/ui/mir/issue-75053.rs @@ -1,6 +1,7 @@ +//@ check-pass //@ compile-flags: -Z mir-opt-level=3 -#![feature(type_alias_impl_trait, rustc_attrs)] +#![feature(type_alias_impl_trait)] use std::marker::PhantomData; @@ -43,8 +44,6 @@ impl>>, U> MyIndex> for Scope { } } -#[rustc_error] fn main() { - //~^ ERROR let _pos: Phantom1> = Scope::new().my_index(); } diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr deleted file mode 100644 index 91032bc3797e5..0000000000000 --- a/tests/ui/mir/issue-75053.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-75053.rs:47:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs index d44f51bfd8d47..2520037813118 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.rs +++ b/tests/ui/proc-macro/no-macro-use-attr.rs @@ -1,10 +1,9 @@ +//@ check-pass //@ proc-macro: test-macros.rs -#![feature(rustc_attrs)] #![warn(unused_extern_crates)] extern crate test_macros; //~^ WARN unused extern crate -#[rustc_error] -fn main() {} //~ ERROR fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr index 3dda3cc7d5a5b..4913672450ab9 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.stderr +++ b/tests/ui/proc-macro/no-macro-use-attr.stderr @@ -10,11 +10,5 @@ note: the lint level is defined here LL | #![warn(unused_extern_crates)] | ^^^^^^^^^^^^^^^^^^^^ -error: fatal error triggered by #[rustc_error] - --> $DIR/no-macro-use-attr.rs:10:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error; 1 warning emitted +warning: 1 warning emitted diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr index 0858434962664..c5756269def66 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `structural_match` - --> $DIR/feature-gate.rs:29:6 + --> $DIR/feature-gate.rs:27:6 | LL | impl std::marker::StructuralPartialEq for Foo { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs index 711b07fee3b6f..694081654d58c 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs @@ -3,11 +3,10 @@ // used in a match. //@ revisions: with_gate no_gate - +//@[with_gate] check-pass // gate-test-structural_match #![allow(unused)] -#![feature(rustc_attrs)] #![cfg_attr(with_gate, feature(structural_match))] @@ -17,8 +16,7 @@ struct Foo { const FOO: Foo = Foo { x: 0 }; -#[rustc_error] -fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error] +fn main() { let y = Foo { x: 1 }; match y { FOO => { } diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr deleted file mode 100644 index 505b7d79cadb8..0000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:21:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/rustc-error.rs b/tests/ui/rustc-error.rs deleted file mode 100644 index 69d57948fb5e7..0000000000000 --- a/tests/ui/rustc-error.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_error] -fn main() { - //~^ ERROR fatal error triggered by #[rustc_error] -} diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr deleted file mode 100644 index 67451195b64f3..0000000000000 --- a/tests/ui/rustc-error.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/rustc-error.rs:4:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs index c4bb16f44bd1b..2e8252169b7e6 100644 --- a/tests/ui/span/range-2.rs +++ b/tests/ui/span/range-2.rs @@ -1,6 +1,6 @@ // Test range syntax - borrow errors. -#![feature(rustc_attrs)] -pub fn main() { #![rustc_error] // rust-lang/rust#49855 + +pub fn main() { let r = { let a = 42; let b = 42; diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs index 60ccaa872e731..fe6c353e8f8e2 100644 --- a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs @@ -1,7 +1,6 @@ -#![feature(rustc_attrs)] use std::ops::FnMut; -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let mut f; { let c = 1; diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr index 225f83b6e6662..bb6298211bc16 100644 --- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21 + --> $DIR/regionck-unboxed-closure-lifetimes.rs:7:21 | LL | let c = 1; | - binding `c` declared here diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs index 7c8231bbb24f8..4c2336e105e2a 100644 --- a/tests/ui/suggestions/attribute-typos.rs +++ b/tests/ui/suggestions/attribute-typos.rs @@ -4,8 +4,8 @@ fn foo() {} #[tests] //~ ERROR cannot find attribute `tests` in this scope fn bar() {} -#[rustc_err] -//~^ ERROR cannot find attribute `rustc_err` in this scope +#[rustc_dumm] +//~^ ERROR cannot find attribute `rustc_dumm` in this scope //~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler fn main() {} diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr index b871c9b45a56c..a1a01c0abd633 100644 --- a/tests/ui/suggestions/attribute-typos.stderr +++ b/tests/ui/suggestions/attribute-typos.stderr @@ -1,14 +1,14 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/attribute-typos.rs:7:3 | -LL | #[rustc_err] - | ^^^^^^^^^ +LL | #[rustc_dumm] + | ^^^^^^^^^^ -error: cannot find attribute `rustc_err` in this scope +error: cannot find attribute `rustc_dumm` in this scope --> $DIR/attribute-typos.rs:7:3 | -LL | #[rustc_err] - | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error` +LL | #[rustc_dumm] + | ^^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_dummy` error: cannot find attribute `tests` in this scope --> $DIR/attribute-typos.rs:4:3 diff --git a/tests/ui/traits/const-traits/feature-gate.gated.stderr b/tests/ui/traits/const-traits/feature-gate.gated.stderr deleted file mode 100644 index 12f9355e41d4e..0000000000000 --- a/tests/ui/traits/const-traits/feature-gate.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:22:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs index c36ec3538c364..921dfb054e305 100644 --- a/tests/ui/traits/const-traits/feature-gate.rs +++ b/tests/ui/traits/const-traits/feature-gate.rs @@ -1,8 +1,8 @@ //@ revisions: stock gated +//@[gated] check-pass // gate-test-const_trait_impl #![cfg_attr(gated, feature(const_trait_impl))] -#![feature(rustc_attrs)] struct S; #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder @@ -18,5 +18,4 @@ macro_rules! discard { ($ty:ty) => {} } discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental discard! { impl const T } //[stock]~ ERROR const trait impls are experimental -#[rustc_error] -fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] +fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.rs b/tests/ui/treat-err-as-bug/span_delayed_bug.rs index 296bdd7a12d9b..88a9d07c94cf1 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.rs +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.rs @@ -8,5 +8,5 @@ #![feature(rustc_attrs)] -#[rustc_error(delayed_bug_from_inside_query)] +#[rustc_delayed_bug_from_inside_query] fn main() {} diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr index aec1b89c7666e..1c8d279c14c46 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: delayed bug triggered by #[rustc_error(delayed_bug_from_inside_query)] +error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] --> $DIR/span_delayed_bug.rs:12:1 | LL | fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs index c24f1bf44fabc..60e455a6a07dd 100644 --- a/tests/ui/type-alias-impl-trait/issue-53096.rs +++ b/tests/ui/type-alias-impl-trait/issue-53096.rs @@ -1,4 +1,5 @@ -#![feature(rustc_attrs)] +//@ check-pass + #![feature(type_alias_impl_trait)] pub type Foo = impl Fn() -> usize; @@ -8,5 +9,4 @@ pub const fn bar() -> Foo { } const BAZR: Foo = bar(); -#[rustc_error] -fn main() {} //~ ERROR +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr deleted file mode 100644 index 53490896af798..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53096.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-53096.rs:12:1 - | -LL | fn main() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs index 5b8ff6b74de51..53280c28ecb1c 100644 --- a/tests/ui/type-alias-impl-trait/issue-60407.rs +++ b/tests/ui/type-alias-impl-trait/issue-60407.rs @@ -1,4 +1,6 @@ -#![feature(type_alias_impl_trait, rustc_attrs)] +//@ check-pass + +#![feature(type_alias_impl_trait)] pub type Debuggable = impl core::fmt::Debug; @@ -9,8 +11,6 @@ pub fn foo() -> Debuggable { static mut TEST: Option = None; -#[rustc_error] fn main() { - //~^ ERROR unsafe { TEST = Some(foo()) } } diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr deleted file mode 100644 index f517d5b65fa28..0000000000000 --- a/tests/ui/type-alias-impl-trait/issue-60407.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: fatal error triggered by #[rustc_error] - --> $DIR/issue-60407.rs:13:1 - | -LL | fn main() { - | ^^^^^^^^^ - -error: aborting due to 1 previous error - From 41fdd280ff1089d1618487d59ed49f83160d2513 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 22 Mar 2025 16:09:37 -0400 Subject: [PATCH 176/333] rustc_resolve: Test the order that preludes are resolved --- tests/ui/resolve/auxiliary/macro_helpers.rs | 16 ++++ tests/ui/resolve/prelude-order.rs | 89 +++++++++++++++++++++ tests/ui/resolve/prelude-order.stderr | 47 +++++++++++ 3 files changed, 152 insertions(+) create mode 100644 tests/ui/resolve/auxiliary/macro_helpers.rs create mode 100644 tests/ui/resolve/prelude-order.rs create mode 100644 tests/ui/resolve/prelude-order.stderr diff --git a/tests/ui/resolve/auxiliary/macro_helpers.rs b/tests/ui/resolve/auxiliary/macro_helpers.rs new file mode 100644 index 0000000000000..43aa336457de7 --- /dev/null +++ b/tests/ui/resolve/auxiliary/macro_helpers.rs @@ -0,0 +1,16 @@ +/* macro namespace. */ + +extern crate proc_macro; +use proc_macro::*; +use std::str::FromStr; + +const ERROR: &str = "fn helper() { \"helper\" }"; +// https://doc.rust-lang.org/nightly/std/prelude/v1/index.html#attributes +// NOTE: all the bang macros in std are currently unstable. +#[proc_macro_attribute] pub fn test // lang. + (_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::from_str("fn test_macro() { \"\" }").unwrap() } +// https://doc.rust-lang.org/nightly/reference/attributes.html#built-in-attributes-index +#[proc_macro_attribute] pub fn global_allocator // lang. + (_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::from_str("fn global_allocator_macro() { \"\" }").unwrap() } diff --git a/tests/ui/resolve/prelude-order.rs b/tests/ui/resolve/prelude-order.rs new file mode 100644 index 0000000000000..a3f194270d483 --- /dev/null +++ b/tests/ui/resolve/prelude-order.rs @@ -0,0 +1,89 @@ +//@ proc-macro:macro_helpers.rs +//@ compile-flags: --crate-type=lib + +/* There are 5 preludes and 3 namespaces. Test the order in which they are resolved. + * See https://doc.rust-lang.org/nightly/reference/names/preludes.html. + * + * Macros cannot be in the type or value namespace. + * Tools and extern crates cannot be in the macro or value namespace. + * + * Test the following truth tables: + +Type: +| ...... | tool | extern | macro | lang | libs | +| tool | N/A | mirror +| extern | extern | N/A | universe +| macro | N/A | N/A | N/A | +| lang | tool | extern | N/A | N/A | +| libs | tool | extern | N/A | X | N/A | + +Macro: +| ...... | tool | extern | macro | lang | libs | +| tool | N/A | mirror +| extern | N/A | N/A | universe +| macro | N/A | N/A | N/A | +| lang | N/A | N/A | macro | N/A | +| libs | N/A | N/A | macro | X | N/A | + +Value: N/A. Only libs has items in the value namespace. + +† ambiguous +X don't care (controlled namespace with no overlap) + +* Types are tested with `#[name::inner]`. Macros are tested with `#[name]`. +* WARNING: I have found in testing that attribute macros give ambiguity errors in some contexts +* instead of choosing a prelude. Have not been able to replicate. +* +* There should be 7 total tests. +* See `rustc_resolve::ident::visit_scopes` for more information, +* and for a definition of "controlled namespace". +*/ + +#![feature(register_tool)] + +/* tool prelude */ +#![register_tool(type_ns)] // extern prelude. type. +#![register_tool(i8)] // lang prelude. type. +#![register_tool(Sync)] // libs prelude. type. + +/* extern prelude */ +extern crate macro_helpers as type_ns; // tool prelude. type. +extern crate macro_helpers as usize; // lang prelude. type. +extern crate macro_helpers as Option; // libs prelude. type. + +/* macro_use prelude */ +#[macro_use] +extern crate macro_helpers as _; + +/* lang and libs implicitly in scope */ + +// tool/extern -> extern +#[type_ns::inner] //~ ERROR could not find `inner` in `type_ns` +fn t1() {} + +// tool/lang -> tool +#[i8::inner] // ok +fn t2() {} + +// tool/libs -> tool +#[Sync::not_real] // ok +fn t3() {} + +// extern/lang -> extern +#[usize::inner] //~ ERROR could not find `inner` in `usize` +fn e1() {} // NOTE: testing with `-> usize` isn't valid, crates aren't considered in that scope + // (unless they have generic arguments, for some reason.) + +// extern/libs -> extern +// https://github.com/rust-lang/rust/issues/139095 +fn e2() -> Option { None } //~ ERROR: expected type, found crate + +// macro/libs -> macro +#[test] //~ ERROR mismatched types +fn m1() {} + +// macro/lang -> macro +#[global_allocator] //~ ERROR mismatched types +fn m2() {} + +// lang/libs: no items that currently overlap, in either macro or type ns. diff --git a/tests/ui/resolve/prelude-order.stderr b/tests/ui/resolve/prelude-order.stderr new file mode 100644 index 0000000000000..1b9cc94285aa5 --- /dev/null +++ b/tests/ui/resolve/prelude-order.stderr @@ -0,0 +1,47 @@ +error[E0433]: failed to resolve: could not find `inner` in `type_ns` + --> $DIR/prelude-order.rs:61:12 + | +LL | #[type_ns::inner] + | ^^^^^ could not find `inner` in `type_ns` + +error[E0433]: failed to resolve: could not find `inner` in `usize` + --> $DIR/prelude-order.rs:73:10 + | +LL | #[usize::inner] + | ^^^^^ could not find `inner` in `usize` + +error[E0573]: expected type, found crate `Option` + --> $DIR/prelude-order.rs:79:12 + | +LL | fn e2() -> Option { None } + | ^^^^^^^^^^^ not a type + | +help: consider importing this enum instead + | +LL + use std::option::Option; + | + +error[E0308]: mismatched types + --> $DIR/prelude-order.rs:82:1 + | +LL | #[test] + | ^^^^^^^- help: try adding a return type: `-> &'static str` + | | + | expected `()`, found `&str` + | + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/prelude-order.rs:86:1 + | +LL | #[global_allocator] + | ^^^^^^^^^^^^^^^^^^^- help: try adding a return type: `-> &'static str` + | | + | expected `()`, found `&str` + | + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0433, E0573. +For more information about an error, try `rustc --explain E0308`. From 4f2baaa9c6b75d4267eea9e1096339d56d380615 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Mar 2025 18:57:04 +0000 Subject: [PATCH 177/333] Do not mix normalized and unnormalized caller bounds when constructing param-env for receiver_is_dispatchable --- .../src/traits/dyn_compatibility.rs | 35 ++++++++++++------- tests/ui/associated-types/issue-59324.stderr | 26 +++++++------- ...-do-not-mix-normalized-and-unnormalized.rs | 26 ++++++++++++++ 3 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 78a452439836f..fa6bbf1d6e57b 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -583,27 +583,36 @@ fn receiver_is_dispatchable<'tcx>( // create a modified param env, with `Self: Unsize` and `U: Trait` (and all of // its supertraits) added to caller bounds. `U: ?Sized` is already implied here. let param_env = { - let param_env = tcx.param_env(method.def_id); + // N.B. We generally want to emulate the construction of the `unnormalized_param_env` + // in the param-env query here. The fact that we don't just start with the clauses + // in the param-env of the method is because those are already normalized, and mixing + // normalized and unnormalized copies of predicates in `normalize_param_env_or_error` + // will cause ambiguity that the user can't really avoid. + // + // We leave out certain complexities of the param-env query here. Specifically, we: + // 1. Do not add `~const` bounds since there are no `dyn const Trait`s. + // 2. Do not add RPITIT self projection bounds for defaulted methods, since we + // are not constructing a param-env for "inside" of the body of the defaulted + // method, so we don't really care about projecting to a specific RPIT type, + // and because RPITITs are not dyn compatible (yet). + let mut predicates = tcx.predicates_of(method.def_id).instantiate_identity(tcx).predicates; // Self: Unsize let unsize_predicate = - ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]).upcast(tcx); + ty::TraitRef::new(tcx, unsize_did, [tcx.types.self_param, unsized_self_ty]); + predicates.push(unsize_predicate.upcast(tcx)); // U: Trait - let trait_predicate = { - let trait_def_id = method.trait_container(tcx).unwrap(); - let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| { - if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) } - }); - - ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx) - }; + let trait_def_id = method.trait_container(tcx).unwrap(); + let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| { + if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) } + }); + let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args); + predicates.push(trait_predicate.upcast(tcx)); normalize_param_env_or_error( tcx, - ty::ParamEnv::new(tcx.mk_clauses_from_iter( - param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]), - )), + ty::ParamEnv::new(tcx.mk_clauses(&predicates)), ObligationCause::dummy_with_span(tcx.def_span(method.def_id)), ) }; diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index f5e696b7ac1ce..f79afc89d10fb 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -36,11 +36,18 @@ LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/issue-59324.rs:24:29 | -help: consider further restricting type parameter `Bug` with trait `Foo` +LL | fn with_factory(factory: dyn ThriftService<()>) {} + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` | -LL | pub trait ThriftService: - | +++++ +help: this trait has no implementations, consider adding one + --> $DIR/issue-59324.rs:3:1 + | +LL | pub trait Foo: NotFoo { + | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:16:5 @@ -51,18 +58,11 @@ LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` - -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:24:29 | -LL | fn with_factory(factory: dyn ThriftService<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` - | -help: this trait has no implementations, consider adding one - --> $DIR/issue-59324.rs:3:1 +help: consider further restricting type parameter `Bug` with trait `Foo` | -LL | pub trait Foo: NotFoo { - | ^^^^^^^^^^^^^^^^^^^^^ +LL | pub trait ThriftService: + | +++++ error[E0277]: the trait bound `Bug: Foo` is not satisfied --> $DIR/issue-59324.rs:20:10 diff --git a/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs new file mode 100644 index 0000000000000..2bc70de2a340d --- /dev/null +++ b/tests/ui/self/dyn-dispatch-do-not-mix-normalized-and-unnormalized.rs @@ -0,0 +1,26 @@ +//@ check-pass + +// Regression test for . + +// Previously, we'd take the normalized param env's clauses which included +// `::Value = i32`, which comes from the supertraits of `TraitD` +// after normalizing `::Value = ::Scalar`. Since +// `normalize_param_env_or_error` ends up re-elaborating `PF: TraitD`, we'd +// end up with both versions of this predicate (normalized and unnormalized). +// Since these projections preds are not equal, we'd fail with ambiguity. + +trait TraitB {} + +trait TraitC: TraitB { + type Value; +} + +trait TraitD: TraitC { + type Scalar; +} + +trait TraitE { + fn apply>(&self); +} + +fn main() {} From cc5ee70b1a51bf30e85d261cc6e485eb3431bcac Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 30 Mar 2025 10:35:59 +0200 Subject: [PATCH 178/333] Simplify expansion for format_args!(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of calling new(), we can just use a struct expression directly. Before: Placeholder::new(…, …, …, …) After: Placeholder { position: …, flags: …, width: …, precision: …, } --- compiler/rustc_ast_lowering/src/format.rs | 28 +++++++++++------------ compiler/rustc_span/src/symbol.rs | 4 ++++ library/core/src/fmt/rt.rs | 8 +------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 343895984ca42..0de0319c66763 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -323,14 +323,12 @@ fn make_count<'hir>( /// Generates /// /// ```text -/// ::…, // alignment -/// …u32, // flags -/// , // width -/// , // precision -/// ) +/// , +/// width: , +/// } /// ``` fn make_format_spec<'hir>( ctx: &mut LoweringContext<'_, 'hir>, @@ -384,13 +382,13 @@ fn make_format_spec<'hir>( let flags = ctx.expr_u32(sp, flags); let precision = make_count(ctx, sp, precision, argmap); let width = make_count(ctx, sp, width, argmap); - let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( - sp, - hir::LangItem::FormatPlaceholder, - sym::new, - )); - let args = ctx.arena.alloc_from_iter([position, flags, precision, width]); - ctx.expr_call_mut(sp, format_placeholder_new, args) + let position = ctx.expr_field(Ident::new(sym::position, sp), ctx.arena.alloc(position), sp); + let flags = ctx.expr_field(Ident::new(sym::flags, sp), ctx.arena.alloc(flags), sp); + let precision = ctx.expr_field(Ident::new(sym::precision, sp), ctx.arena.alloc(precision), sp); + let width = ctx.expr_field(Ident::new(sym::width, sp), ctx.arena.alloc(width), sp); + let placeholder = ctx.arena.alloc(hir::QPath::LangItem(hir::LangItem::FormatPlaceholder, sp)); + let fields = ctx.arena.alloc_from_iter([position, flags, precision, width]); + ctx.expr(sp, hir::ExprKind::Struct(placeholder, fields, hir::StructTailExpr::None)) } fn expand_format_args<'hir>( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6807f96e712cd..cc4c9860bc270 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -986,6 +986,7 @@ symbols! { field_init_shorthand, file, file_options, + flags, float, float_to_int_unchecked, floorf128, @@ -1570,6 +1571,7 @@ symbols! { pointer_like, poll, poll_next, + position, post_dash_lto: "post-lto", postfix_match, powerpc_target_feature, @@ -1585,6 +1587,7 @@ symbols! { precise_capturing, precise_capturing_in_traits, precise_pointer_size_matching, + precision, pref_align_of, prefetch_read_data, prefetch_read_instruction, @@ -2274,6 +2277,7 @@ symbols! { wasm_target_feature, where_clause_attrs, while_let, + width, windows, windows_subsystem, with_negative_coherence, diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index d27f7e6e0d8e6..0b04ebccae2bd 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -20,8 +20,8 @@ pub struct Placeholder { pub width: Count, } +#[cfg(bootstrap)] impl Placeholder { - #[cfg(bootstrap)] #[inline] pub const fn new( position: usize, @@ -33,12 +33,6 @@ impl Placeholder { ) -> Self { Self { position, fill, align, flags, precision, width } } - - #[cfg(not(bootstrap))] - #[inline] - pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self { - Self { position, flags, precision, width } - } } #[cfg(bootstrap)] From 31face9f6087c2914ea995af969bb995629a5e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 30 Mar 2025 11:14:33 +0200 Subject: [PATCH 179/333] Revert "Auto merge of #129827 - bvanjoi:less-decoding, r=petrochenkov" Reverting because of a performance regression. This reverts commit d4812c8638173ec163825d56a72a33589483ec4c, reversing changes made to 5cc60728e7ee10eb2ae5f61f7d412d9805b22f0c. --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_middle/src/query/on_disk_cache.rs | 10 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 203 ++++++++++++------ .../nonterminal-token-hygiene.stdout | 20 +- 5 files changed, 158 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 34e4f2f26022a..dc453b1e747ca 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,7 +36,7 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey}; +use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; @@ -193,7 +193,7 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; +type SyntaxContextTable = LazyTable>>; type ExpnDataTable = LazyTable>>; type ExpnHashTable = LazyTable>>; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index ce6219c207fdb..14e3ce8bef6b2 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,7 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, }; use rustc_span::source_map::Spanned; use rustc_span::{ @@ -75,9 +75,9 @@ pub struct OnDiskCache { alloc_decoding_state: AllocDecodingState, // A map from syntax context ids to the position of their associated - // `SyntaxContextKey`. We use a `u32` instead of a `SyntaxContext` + // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext` // to represent the fact that we are storing *encoded* ids. When we decode - // a `SyntaxContextKey`, a new id will be allocated from the global `HygieneData`, + // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`, // which will almost certainly be different than the serialized id. syntax_contexts: FxHashMap, // A map from the `DefPathHash` of an `ExpnId` to the position @@ -305,7 +305,7 @@ impl OnDiskCache { let mut expn_data = UnhashMap::default(); let mut foreign_expn_data = UnhashMap::default(); - // Encode all hygiene data (`SyntaxContextKey` and `ExpnData`) from the current + // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current // session. hygiene_encode_context.encode( @@ -566,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { // We look up the position of the associated `SyntaxData` and decode it. let pos = syntax_contexts.get(&id).unwrap(); this.with_position(pos.to_usize(), |decoder| { - let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); + let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); data }) }) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 134f76d7248d9..19e2b57456327 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -111,7 +111,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextKey, + rustc_span::hygiene::SyntaxContextData, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index f94858856729c..4390085cd049a 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -24,6 +24,9 @@ // because getting it wrong can lead to nested `HygieneData::with` calls that // trigger runtime aborts. (Fortunately these are obvious and easy to fix.) +use std::cell::RefCell; +use std::collections::hash_map::Entry; +use std::collections::hash_set::Entry as SetEntry; use std::hash::Hash; use std::sync::Arc; use std::{fmt, iter, mem}; @@ -31,7 +34,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{Lock, WorkerLocal}; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -56,10 +59,10 @@ impl !PartialOrd for SyntaxContext {} /// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. /// The other fields are only for caching. -pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); +type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); #[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable)] -struct SyntaxContextData { +pub struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, @@ -91,21 +94,6 @@ impl SyntaxContextData { self.dollar_crate_name == kw::Empty } - fn new( - (parent, outer_expn, outer_transparency): SyntaxContextKey, - opaque: SyntaxContext, - opaque_and_semitransparent: SyntaxContext, - ) -> Self { - SyntaxContextData { - parent, - outer_expn, - outer_transparency, - opaque, - opaque_and_semitransparent, - dollar_crate_name: kw::DollarCrate, - } - } - fn key(&self) -> SyntaxContextKey { (self.parent, self.outer_expn, self.outer_transparency) } @@ -586,49 +574,67 @@ impl HygieneData { fn apply_mark_internal( &mut self, - parent: SyntaxContext, + ctxt: SyntaxContext, expn_id: ExpnId, transparency: Transparency, ) -> SyntaxContext { - debug_assert!(!self.syntax_context_data[parent.0 as usize].is_decode_placeholder()); - // Look into the cache first. - let key = (parent, expn_id, transparency); - if let Some(ctxt) = self.syntax_context_map.get(&key) { - return *ctxt; + let syntax_context_data = &mut self.syntax_context_data; + debug_assert!(!syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); + let mut opaque = syntax_context_data[ctxt.0 as usize].opaque; + let mut opaque_and_semitransparent = + syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent; + + if transparency >= Transparency::Opaque { + let parent = opaque; + opaque = *self + .syntax_context_map + .entry((parent, expn_id, transparency)) + .or_insert_with(|| { + let new_opaque = SyntaxContext::from_usize(syntax_context_data.len()); + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque: new_opaque, + opaque_and_semitransparent: new_opaque, + dollar_crate_name: kw::DollarCrate, + }); + new_opaque + }); + } + + if transparency >= Transparency::SemiTransparent { + let parent = opaque_and_semitransparent; + opaque_and_semitransparent = *self + .syntax_context_map + .entry((parent, expn_id, transparency)) + .or_insert_with(|| { + let new_opaque_and_semitransparent = + SyntaxContext::from_usize(syntax_context_data.len()); + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque, + opaque_and_semitransparent: new_opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + }); + new_opaque_and_semitransparent + }); } - // Reserve a new syntax context. - let ctxt = SyntaxContext::from_usize(self.syntax_context_data.len()); - self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); - self.syntax_context_map.insert(key, ctxt); - - // Opaque and semi-transparent versions of the parent. Note that they may be equal to the - // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, - // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques - // and semi-transparents. - let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; - let parent_opaque_and_semitransparent = - self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; - - // Evaluate opaque and semi-transparent versions of the new syntax context. - let (opaque, opaque_and_semitransparent) = match transparency { - Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), - Transparency::SemiTransparent => ( - parent_opaque, - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), - ), - Transparency::Opaque => ( - // Will be the same as `ctxt` if the expn chain contains only opaques. - self.apply_mark_internal(parent_opaque, expn_id, transparency), - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.apply_mark_internal(parent_opaque_and_semitransparent, expn_id, transparency), - ), - }; - // Fill the full data, now that we have it. - self.syntax_context_data[ctxt.as_u32() as usize] = - SyntaxContextData::new(key, opaque, opaque_and_semitransparent); - ctxt + let parent = ctxt; + *self.syntax_context_map.entry((parent, expn_id, transparency)).or_insert_with(|| { + syntax_context_data.push(SyntaxContextData { + outer_expn: expn_id, + outer_transparency: transparency, + parent, + opaque, + opaque_and_semitransparent, + dollar_crate_name: kw::DollarCrate, + }); + SyntaxContext::from_usize(syntax_context_data.len() - 1) + }) } } @@ -1259,7 +1265,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextData), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1317,6 +1323,9 @@ struct HygieneDecodeContextInner { /// Additional information used to assist in decoding hygiene data pub struct HygieneDecodeContext { inner: Lock, + + /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. + local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1387,10 +1396,10 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context SyntaxContextKey>( +pub fn decode_syntax_context SyntaxContextData>( d: &mut D, context: &HygieneDecodeContext, - decode_ctxt_key: F, + decode_data: F, ) -> SyntaxContext { let raw_id: u32 = Decodable::decode(d); if raw_id == 0 { @@ -1399,9 +1408,58 @@ pub fn decode_syntax_context SyntaxContext return SyntaxContext::root(); } + let pending_ctxt = { + let mut inner = context.inner.lock(); + + // Reminder: `HygieneDecodeContext` is per-crate, so there are no collisions between + // raw ids from different crate metadatas. + if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { + // This has already been decoded. + return ctxt; + } + + match inner.decoding.entry(raw_id) { + Entry::Occupied(ctxt_entry) => { + let pending_ctxt = *ctxt_entry.get(); + match context.local_in_progress.borrow_mut().entry(raw_id) { + // We're decoding this already on the current thread. Return here and let the + // function higher up the stack finish decoding to handle recursive cases. + // Hopefully having a `SyntaxContext` that refers to an incorrect data is ok + // during reminder of the decoding process, it's certainly not ok after the + // top level decoding function returns. + SetEntry::Occupied(..) => return pending_ctxt, + // Some other thread is currently decoding this. + // Race with it (alternatively we could wait here). + // We cannot return this value, unlike in the recursive case above, because it + // may expose a `SyntaxContext` pointing to incorrect data to arbitrary code. + SetEntry::Vacant(entry) => { + entry.insert(); + pending_ctxt + } + } + } + Entry::Vacant(entry) => { + // We are the first thread to start decoding. Mark the current thread as being progress. + context.local_in_progress.borrow_mut().insert(raw_id); + + // Allocate and store SyntaxContext id *before* calling the decoder function, + // as the SyntaxContextData may reference itself. + let new_ctxt = HygieneData::with(|hygiene_data| { + // Push a dummy SyntaxContextData to ensure that nobody else can get the + // same ID as us. This will be overwritten after call `decode_data`. + hygiene_data.syntax_context_data.push(SyntaxContextData::decode_placeholder()); + SyntaxContext::from_usize(hygiene_data.syntax_context_data.len() - 1) + }); + entry.insert(new_ctxt); + new_ctxt + } + } + }; + // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let ctxt_key = decode_ctxt_key(d, raw_id); + let ctxt_data = decode_data(d, raw_id); + let ctxt_key = ctxt_data.key(); let ctxt = HygieneData::with(|hygiene_data| { match hygiene_data.syntax_context_map.get(&ctxt_key) { @@ -1415,10 +1473,29 @@ pub fn decode_syntax_context SyntaxContext Some(&ctxt) => ctxt, // This is a completely new context. // Overwrite its placeholder data with our decoded data. - None => hygiene_data.apply_mark_internal(ctxt_key.0, ctxt_key.1, ctxt_key.2), + None => { + let ctxt_data_ref = + &mut hygiene_data.syntax_context_data[pending_ctxt.as_u32() as usize]; + let prev_ctxt_data = mem::replace(ctxt_data_ref, ctxt_data); + // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`. + // We don't care what the encoding crate set this to - we want to resolve it + // from the perspective of the current compilation session. + ctxt_data_ref.dollar_crate_name = kw::DollarCrate; + // Make sure nothing weird happened while `decode_data` was running. + if !prev_ctxt_data.is_decode_placeholder() { + // Another thread may have already inserted the decoded data, + // but the decoded data should match. + assert_eq!(prev_ctxt_data, *ctxt_data_ref); + } + hygiene_data.syntax_context_map.insert(ctxt_key, pending_ctxt); + pending_ctxt + } } }); + // Mark the context as completed + context.local_in_progress.borrow_mut().remove(&raw_id); + let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; if inner.remapped_ctxts.len() < new_len { @@ -1430,7 +1507,7 @@ pub fn decode_syntax_context SyntaxContext ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { @@ -1438,7 +1515,7 @@ fn for_all_ctxts_in( ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect() }); for (ctxt, data) in all_data.into_iter() { - f(ctxt.0, ctxt, &data.key()); + f(ctxt.0, ctxt, &data); } } diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 6fd6cb474693b..c80a33206fb4f 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#4), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#4), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), + span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#4), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), + span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#5), }, ] #![feature /* 0#0 */(prelude_import)] @@ -59,7 +59,7 @@ macro_rules! outer struct S /* 0#0 */; macro inner /* 0#3 */ { () => { print_bang! { struct S; } } } -struct S /* 0#5 */; +struct S /* 0#4 */; // OK, not a duplicate definition of `S` fn main /* 0#0 */() {} @@ -70,7 +70,7 @@ crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") -crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") @@ -83,9 +83,9 @@ SyntaxContexts: #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) #3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) -#4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) -#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#5: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) -#7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#7: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) +#8: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) */ From d035ca7db384e125d1a5110cefb3872386fa692f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 30 Mar 2025 11:19:07 +0200 Subject: [PATCH 180/333] Improve hir_pretty for struct expressions. Before: let a = StructWithSomeFields{ field_1: 1, field_2: 2, field_3: 3, field_4: 4, field_5: 5, field_6: 6,}; let a = StructWithSomeFields{ field_1: 1, field_2: 2, ..a}; After: let a = StructWithSomeFields { field_1: 1, field_2: 2, field_3: 3, field_4: 4, field_5: 5, field_6: 6 }; let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; --- compiler/rustc_hir_pretty/src/lib.rs | 14 ++++---------- tests/pretty/hir-lifetimes.pp | 6 +++--- tests/pretty/hir-struct-expr.pp | 28 ++++++++++++++++++++++++++++ tests/pretty/hir-struct-expr.rs | 24 ++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 tests/pretty/hir-struct-expr.pp create mode 100644 tests/pretty/hir-struct-expr.rs diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddaca89ccf82d..1c23761b2e5bf 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1193,7 +1193,8 @@ impl<'a> State<'a> { wth: hir::StructTailExpr<'_>, ) { self.print_qpath(qpath, true); - self.word("{"); + self.nbsp(); + self.word_space("{"); self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span); match wth { hir::StructTailExpr::Base(expr) => { @@ -1215,20 +1216,13 @@ impl<'a> State<'a> { self.word(".."); self.end(); } - hir::StructTailExpr::None => { - if !fields.is_empty() { - self.word(","); - } - } + hir::StructTailExpr::None => {} } - + self.space(); self.word("}"); } fn print_expr_field(&mut self, field: &hir::ExprField<'_>) { - if self.attrs(field.hir_id).is_empty() { - self.space(); - } self.cbox(INDENT_UNIT); self.print_attrs_as_outer(self.attrs(field.hir_id)); if !field.is_shorthand { diff --git a/tests/pretty/hir-lifetimes.pp b/tests/pretty/hir-lifetimes.pp index e545b0c8f5764..4d1ab9d383bf4 100644 --- a/tests/pretty/hir-lifetimes.pp +++ b/tests/pretty/hir-lifetimes.pp @@ -30,10 +30,10 @@ // FIXME: impl Traits printed as just `/*impl Trait*/`, ugh fn iter1<'a>(&self) - -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } + -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } fn iter2(&self) - -> /*impl Trait*/ { #[lang = "Range"]{ start: 0, end: 1,} } + -> /*impl Trait*/ { #[lang = "Range"] { start: 0, end: 1 } } } fn a(x: Foo<'_>) { } @@ -82,7 +82,7 @@ x: &'a u32, } -fn f() { { let _ = St{ x: &0,}; }; { let _ = St{ x: &0,}; }; } +fn f() { { let _ = St { x: &0 }; }; { let _ = St { x: &0 }; }; } struct Name<'a>(&'a str); diff --git a/tests/pretty/hir-struct-expr.pp b/tests/pretty/hir-struct-expr.pp new file mode 100644 index 0000000000000..f85d17542dffb --- /dev/null +++ b/tests/pretty/hir-struct-expr.pp @@ -0,0 +1,28 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-struct-expr.pp + +struct StructWithSomeFields { + field_1: i32, + field_2: i32, + field_3: i32, + field_4: i32, + field_5: i32, + field_6: i32, +} + +fn main() { + let a = + StructWithSomeFields { + field_1: 1, + field_2: 2, + field_3: 3, + field_4: 4, + field_5: 5, + field_6: 6 }; + let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; +} diff --git a/tests/pretty/hir-struct-expr.rs b/tests/pretty/hir-struct-expr.rs new file mode 100644 index 0000000000000..9580f5d557d32 --- /dev/null +++ b/tests/pretty/hir-struct-expr.rs @@ -0,0 +1,24 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-struct-expr.pp + +struct StructWithSomeFields { + field_1: i32, + field_2: i32, + field_3: i32, + field_4: i32, + field_5: i32, + field_6: i32, +} + +fn main() { + let a = StructWithSomeFields { + field_1: 1, + field_2: 2, + field_3: 3, + field_4: 4, + field_5: 5, + field_6: 6, + }; + let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a }; +} From db576c13607401e686181d428de61136011f4551 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 13:52:03 +0100 Subject: [PATCH 181/333] Expose `peel_casts` method as an util method inside `rustc_lint` --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/reference_casting.rs | 44 +--------------- compiler/rustc_lint/src/utils.rs | 55 ++++++++++++++++++++ 3 files changed, 57 insertions(+), 43 deletions(-) create mode 100644 compiler/rustc_lint/src/utils.rs diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a754001811..f6e624554567a 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -80,6 +80,7 @@ mod types; mod unit_bindings; mod unqualified_local_imports; mod unused; +mod utils; use async_closures::AsyncClosureUsage; use async_fn_in_trait::AsyncFnInTrait; diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 7c6656f91c99b..1d4d380cb685e 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -6,6 +6,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::lints::InvalidReferenceCastingDiag; +use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -235,46 +236,3 @@ fn is_cast_to_bigger_memory_layout<'tcx>( None } } - -fn peel_casts<'tcx>(cx: &LateContext<'tcx>, mut e: &'tcx Expr<'tcx>) -> (&'tcx Expr<'tcx>, bool) { - let mut gone_trough_unsafe_cell_raw_get = false; - - loop { - e = e.peel_blocks(); - // as ... - e = if let ExprKind::Cast(expr, _) = e.kind { - expr - // .cast(), .cast_mut() or .cast_const() - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) - ) - { - expr - // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && matches!( - cx.tcx.get_diagnostic_name(def_id), - Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) - ) - { - if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { - gone_trough_unsafe_cell_raw_get = true; - } - arg - } else { - let init = cx.expr_or_init(e); - if init.hir_id != e.hir_id { - init - } else { - break; - } - }; - } - - (e, gone_trough_unsafe_cell_raw_get) -} diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs new file mode 100644 index 0000000000000..64bfa428ae433 --- /dev/null +++ b/compiler/rustc_lint/src/utils.rs @@ -0,0 +1,55 @@ +use rustc_hir::{Expr, ExprKind}; +use rustc_span::sym; + +use crate::LateContext; + +/// Given an expression, peel all of casts (` as ...`, `.cast{,_mut,_const}()`, +/// `ptr::from_ref()`, ...) and init expressions. +/// +/// Returns the outermost expression and a boolean representing if one of the casts was +/// `UnsafeCell::raw_get()` +pub(crate) fn peel_casts<'tcx>( + cx: &LateContext<'tcx>, + mut e: &'tcx Expr<'tcx>, +) -> (&'tcx Expr<'tcx>, bool) { + let mut gone_trough_unsafe_cell_raw_get = false; + + loop { + e = e.peel_blocks(); + // as ... + e = if let ExprKind::Cast(expr, _) = e.kind { + expr + // .cast(), .cast_mut() or .cast_const() + } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const) + ) + { + expr + // ptr::from_ref(), UnsafeCell::raw_get() or mem::transmute<_, _>() + } else if let ExprKind::Call(path, [arg]) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && matches!( + cx.tcx.get_diagnostic_name(def_id), + Some(sym::ptr_from_ref | sym::unsafe_cell_raw_get | sym::transmute) + ) + { + if cx.tcx.is_diagnostic_item(sym::unsafe_cell_raw_get, def_id) { + gone_trough_unsafe_cell_raw_get = true; + } + arg + } else { + let init = cx.expr_or_init(e); + if init.hir_id != e.hir_id { + init + } else { + break; + } + }; + } + + (e, gone_trough_unsafe_cell_raw_get) +} From a20d2ef0d9f10d65080216e7e7a1ace57ee210e8 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 13:40:03 +0100 Subject: [PATCH 182/333] Improve explicitness of the impl of the `useless_ptr_null_checks` lint --- compiler/rustc_lint/messages.ftl | 18 +++++++++--------- compiler/rustc_lint/src/lints.rs | 10 +++++----- compiler/rustc_lint/src/ptr_nulls.rs | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d51865810b9a8..01e6a819cf38b 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -680,15 +680,6 @@ lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cann lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope .label = names from parent modules are not accessible without an explicit import -lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false - .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value - .label = expression has type `{$orig_ty}` - -lint_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false - -lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false - .label = expression has type `{$orig_ty}` - lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale @@ -978,6 +969,15 @@ lint_unused_result = unused result of type `{$ty}` lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result +lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false + .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value + .label = expression has type `{$orig_ty}` + +lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false + +lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false + .label = expression has type `{$orig_ty}` + lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type lint_variant_size_differences = diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0058630957291..774665e93c424 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -591,21 +591,21 @@ pub(crate) struct ExpectationNote { // ptr_nulls.rs #[derive(LintDiagnostic)] -pub(crate) enum PtrNullChecksDiag<'a> { - #[diag(lint_ptr_null_checks_fn_ptr)] - #[help(lint_help)] +pub(crate) enum UselessPtrNullChecksDiag<'a> { + #[diag(lint_useless_ptr_null_checks_fn_ptr)] + #[help] FnPtr { orig_ty: Ty<'a>, #[label] label: Span, }, - #[diag(lint_ptr_null_checks_ref)] + #[diag(lint_useless_ptr_null_checks_ref)] Ref { orig_ty: Ty<'a>, #[label] label: Span, }, - #[diag(lint_ptr_null_checks_fn_ret)] + #[diag(lint_useless_ptr_null_checks_fn_ret)] FnRet { fn_name: Ident }, } diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 1489f9de81991..9ace3a689ad96 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -3,7 +3,7 @@ use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::PtrNullChecksDiag; +use crate::lints::UselessPtrNullChecksDiag; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -38,10 +38,10 @@ declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]); /// a fn ptr, a reference, or a function call whose definition is /// annotated with `#![rustc_never_returns_null_ptr]`. /// If this situation is present, the function returns the appropriate diagnostic. -fn incorrect_check<'a, 'tcx: 'a>( +fn useless_check<'a, 'tcx: 'a>( cx: &'a LateContext<'tcx>, mut e: &'a Expr<'a>, -) -> Option> { +) -> Option> { let mut had_at_least_one_cast = false; loop { e = e.peel_blocks(); @@ -50,14 +50,14 @@ fn incorrect_check<'a, 'tcx: 'a>( && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { - return Some(PtrNullChecksDiag::FnRet { fn_name }); + return Some(UselessPtrNullChecksDiag::FnRet { fn_name }); } else if let ExprKind::Call(path, _args) = e.kind && let ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() && cx.tcx.has_attr(def_id, sym::rustc_never_returns_null_ptr) && let Some(fn_name) = cx.tcx.opt_item_ident(def_id) { - return Some(PtrNullChecksDiag::FnRet { fn_name }); + return Some(UselessPtrNullChecksDiag::FnRet { fn_name }); } e = if let ExprKind::Cast(expr, t) = e.kind && let TyKind::Ptr(_) = t.kind @@ -73,9 +73,9 @@ fn incorrect_check<'a, 'tcx: 'a>( } else if had_at_least_one_cast { let orig_ty = cx.typeck_results().expr_ty(e); return if orig_ty.is_fn() { - Some(PtrNullChecksDiag::FnPtr { orig_ty, label: e.span }) + Some(UselessPtrNullChecksDiag::FnPtr { orig_ty, label: e.span }) } else if orig_ty.is_ref() { - Some(PtrNullChecksDiag::Ref { orig_ty, label: e.span }) + Some(UselessPtrNullChecksDiag::Ref { orig_ty, label: e.span }) } else { None }; @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_const_is_null | sym::ptr_is_null) ) - && let Some(diag) = incorrect_check(cx, arg) => + && let Some(diag) = useless_check(cx, arg) => { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } @@ -110,18 +110,18 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_const_is_null | sym::ptr_is_null) ) - && let Some(diag) = incorrect_check(cx, receiver) => + && let Some(diag) = useless_check(cx, receiver) => { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { let to_check: &Expr<'_>; - let diag: PtrNullChecksDiag<'_>; - if let Some(ddiag) = incorrect_check(cx, left) { + let diag: UselessPtrNullChecksDiag<'_>; + if let Some(ddiag) = useless_check(cx, left) { to_check = right; diag = ddiag; - } else if let Some(ddiag) = incorrect_check(cx, right) { + } else if let Some(ddiag) = useless_check(cx, right) { to_check = left; diag = ddiag; } else { From ebae4c65a10a593b838d9c2f07f4c13e342ec03e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 30 Mar 2025 13:21:01 +0100 Subject: [PATCH 183/333] Fix partial clone link --- src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 067e287111843..c3c1c41e3f697 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -63,7 +63,7 @@ cd rust > **NOTE**: A shallow clone limits which `git` commands can be run. > If you intend to work on and contribute to the compiler, it is > generally recommended to fully clone the repository [as shown above](#get-the-source-code), -> or to perform a [partial clone](#shallow-clone-the-repository) instead. +> or to perform a [partial clone](#partial-clone-the-repository) instead. > > For example, `git bisect` and `git blame` require access to the commit history, > so they don't work if the repository was cloned with `--depth 1`. From b1bc7255bb16f2500d5bdcbc17c06c2acd91c7f0 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:25:27 +0200 Subject: [PATCH 184/333] Delete unreacheable `#[rustc_on_unimplemented]` --- library/alloc/src/vec/mod.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3782f9e95194c..633ef717e04dc 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3360,10 +3360,6 @@ impl Hash for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] impl, A: Allocator> Index for Vec { type Output = I::Output; @@ -3374,10 +3370,6 @@ impl, A: Allocator> Index for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] impl, A: Allocator> IndexMut for Vec { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { From 41bee761bb81888c09c0567377abdcacf564f6b9 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:25:47 +0200 Subject: [PATCH 185/333] use `diagnostic::on_unimplemented` instead --- library/core/src/iter/traits/accum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 5b7d95c2f65e6..12e2b8b393a88 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -10,7 +10,7 @@ use crate::num::Wrapping; /// [`sum()`]: Iterator::sum /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`", label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator`" )] @@ -31,7 +31,7 @@ pub trait Sum: Sized { /// [`product()`]: Iterator::product /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator", label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator`" )] From 66b1f3ba0c9bbd40e671078a320c6d99f415a055 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 14:42:17 +0000 Subject: [PATCH 186/333] Rustup to rustc 1.88.0-nightly (1799887bb 2025-03-29) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ab650c05d3572..ceff15b1180a7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-03-25" +channel = "nightly-2025-03-30" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From ba315abda789c9f59f2100102232bddb30b0d3d3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:01:39 +0000 Subject: [PATCH 187/333] Fix rustc test suite --- scripts/test_rustc_tests.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 5e96210d85898..95a4302b5e471 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -27,7 +27,6 @@ done git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed git checkout -- tests/ui/proc-macro/pretty-print-hack/ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs -rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # missing features # ================ @@ -136,7 +135,6 @@ rm -r tests/run-make/incr-add-rust-src-component # ============ rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort -rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation warning for -Cinline-threshold # bugs in the test suite # ====================== From 08f6747ac7428dcbc1e35732eac120d2659669b0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Mar 2025 15:48:52 +0000 Subject: [PATCH 188/333] Update tidy exceptions --- src/tools/tidy/src/deps.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1a6550691ee34..603653847e318 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -181,6 +181,8 @@ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ // tidy-alphabetical-start + ("cranelift-assembler-x64", "Apache-2.0 WITH LLVM-exception"), + ("cranelift-assembler-x64-meta", "Apache-2.0 WITH LLVM-exception"), ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"), ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), @@ -512,6 +514,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "bitflags", "bumpalo", "cfg-if", + "cranelift-assembler-x64", + "cranelift-assembler-x64-meta", "cranelift-bforest", "cranelift-bitset", "cranelift-codegen", From 59ca7679c7db634465b5f021060f143567824ac4 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sat, 29 Mar 2025 14:47:09 -0400 Subject: [PATCH 189/333] slice: Remove some uses of unsafe in first/last chunk methods Remove unsafe `split_at_unchecked` and `split_at_mut_unchecked` in some slice `split_first_chunk`/`split_last_chunk` methods. Replace those calls with the safe `split_at` and `split_at_checked` where applicable. Add codegen tests to check for no panics when calculating the last chunk index using `checked_sub` and `split_at` --- library/core/src/slice/mod.rs | 94 ++++++++++++--------------------- tests/codegen/slice-split-at.rs | 24 +++++++++ 2 files changed, 58 insertions(+), 60 deletions(-) create mode 100644 tests/codegen/slice-split-at.rs diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5bb7243c4491b..4e8be20643179 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -382,16 +382,11 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_unchecked(N) }; + let Some((first, tail)) = self.split_at_checked(N) else { return None }; - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) } /// Returns a mutable array reference to the first `N` items in the slice and the remaining @@ -419,17 +414,12 @@ impl [T] { pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (first, tail) = unsafe { self.split_at_mut_unchecked(N) }; + let Some((first, tail)) = self.split_at_mut_checked(N) else { return None }; - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) - } + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) } /// Returns an array reference to the last `N` items in the slice and the remaining slice. @@ -452,16 +442,12 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) } /// Returns a mutable array reference to the last `N` items in the slice and the remaining @@ -489,17 +475,13 @@ impl [T] { pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the split. - let (init, last) = unsafe { self.split_at_mut_unchecked(self.len() - N) }; + let Some(index) = self.len().checked_sub(N) else { return None }; + let (init, last) = self.split_at_mut(index); - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and enforce exclusive mutability of the chunk by the split. - Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) - } + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and enforce exclusive mutability of the chunk by the split. + Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) } /// Returns an array reference to the last `N` items in the slice. @@ -522,17 +504,13 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")] pub const fn last_chunk(&self) -> Option<&[T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at(index); - // SAFETY: We explicitly check for the correct number of elements, - // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) - } + // SAFETY: We explicitly check for the correct number of elements, + // and do not let the references outlive the slice. + Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) } /// Returns a mutable array reference to the last `N` items in the slice. @@ -556,18 +534,14 @@ impl [T] { #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { - if self.len() < N { - None - } else { - // SAFETY: We manually verified the bounds of the slice. - // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. - let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; - - // SAFETY: We explicitly check for the correct number of elements, - // do not let the reference outlive the slice, - // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) - } + // FIXME(const-hack): Without const traits, we need this instead of `get`. + let Some(index) = self.len().checked_sub(N) else { return None }; + let (_, last) = self.split_at_mut(index); + + // SAFETY: We explicitly check for the correct number of elements, + // do not let the reference outlive the slice, + // and require exclusive access to the entire slice to mutate the chunk. + Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) } /// Returns a reference to an element or subslice depending on the type of diff --git a/tests/codegen/slice-split-at.rs b/tests/codegen/slice-split-at.rs new file mode 100644 index 0000000000000..07018cf9c9171 --- /dev/null +++ b/tests/codegen/slice-split-at.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +// Check that no panic is generated in `split_at` when calculating the index for +// the tail chunk using `checked_sub`. +// +// Tests written for refactored implementations of: +// `<[T]>::{split_last_chunk, split_last_chunk_mut, last_chunk, last_chunk_mut}` + +// CHECK-LABEL: @split_at_last_chunk +#[no_mangle] +pub fn split_at_last_chunk(s: &[u8], chunk_size: usize) -> Option<(&[u8], &[u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at(index)) +} + +// CHECK-LABEL: @split_at_mut_last_chunk +#[no_mangle] +pub fn split_at_mut_last_chunk(s: &mut [u8], chunk_size: usize) -> Option<(&mut [u8], &mut [u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at_mut(index)) +} From 96a2f698444144efe2cb359102ca15a48d66ad6b Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 14:38:16 +0100 Subject: [PATCH 190/333] Uplift `clippy::invalid_null_ptr_usage` as `invalid_null_arguments` --- compiler/rustc_lint/messages.ftl | 4 + compiler/rustc_lint/src/lints.rs | 16 ++ compiler/rustc_lint/src/ptr_nulls.rs | 106 +++++++- compiler/rustc_lint/src/utils.rs | 2 +- tests/ui/lint/invalid_null_args.rs | 136 ++++++++++ tests/ui/lint/invalid_null_args.stderr | 330 +++++++++++++++++++++++++ 6 files changed, 590 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lint/invalid_null_args.rs create mode 100644 tests/ui/lint/invalid_null_args.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 01e6a819cf38b..f45caf96f9b63 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -456,6 +456,10 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable +lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused + .origin = null pointer originates from here + .doc = for more information, visit and + lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` .label = casting happened here diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 774665e93c424..4de998c087474 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -609,6 +609,22 @@ pub(crate) enum UselessPtrNullChecksDiag<'a> { FnRet { fn_name: Ident }, } +#[derive(LintDiagnostic)] +pub(crate) enum InvalidNullArgumentsDiag { + #[diag(lint_invalid_null_arguments)] + #[help(lint_doc)] + NullPtrInline { + #[label(lint_origin)] + null_span: Span, + }, + #[diag(lint_invalid_null_arguments)] + #[help(lint_doc)] + NullPtrThroughBinding { + #[note(lint_origin)] + null_span: Span, + }, +} + // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] #[diag(lint_for_loops_over_fallibles)] diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 9ace3a689ad96..826bce2c31506 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -1,9 +1,11 @@ use rustc_ast::LitKind; use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_middle::ty::RawPtr; use rustc_session::{declare_lint, declare_lint_pass}; -use rustc_span::sym; +use rustc_span::{Span, sym}; -use crate::lints::UselessPtrNullChecksDiag; +use crate::lints::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag}; +use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -31,7 +33,30 @@ declare_lint! { "useless checking of non-null-typed pointer" } -declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]); +declare_lint! { + /// The `invalid_null_arguments` lint checks for invalid usage of null pointers in arguments. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # use std::{slice, ptr}; + /// // Undefined behavior + /// # let _slice: &[u8] = + /// unsafe { slice::from_raw_parts(ptr::null(), 0) }; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Calling methods whos safety invariants requires non-null ptr with a null pointer + /// is [Undefined Behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)! + INVALID_NULL_ARGUMENTS, + Deny, + "invalid null pointer in arguments" +} + +declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS, INVALID_NULL_ARGUMENTS]); /// This function checks if the expression is from a series of consecutive casts, /// ie. `(my_fn as *const _ as *mut _).cast_mut()` and whether the original expression is either @@ -85,6 +110,25 @@ fn useless_check<'a, 'tcx: 'a>( } } +/// Checks if the given expression is a null pointer (modulo casting) +fn is_null_ptr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { + let (expr, _) = peel_casts(cx, expr); + + if let ExprKind::Call(path, []) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id) + { + (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut).then_some(expr.span) + } else if let ExprKind::Lit(spanned) = expr.kind + && let LitKind::Int(v, _) = spanned.node + { + (v == 0).then_some(expr.span) + } else { + None + } +} + impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { @@ -102,6 +146,62 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag) } + // Catching: + // (arg...) where `arg` is null-ptr and `path` is a fn that expect non-null-ptr + ExprKind::Call(path, args) + if let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && let Some(diag_name) = cx.tcx.get_diagnostic_name(def_id) => + { + // `arg` positions where null would cause U.B and whenever ZST are allowed. + // + // We should probably have a `rustc` attribute, but checking them is costly, + // maybe if we checked for null ptr first, it would be acceptable? + let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name { + sym::ptr_read + | sym::ptr_read_unaligned + | sym::ptr_read_volatile + | sym::ptr_replace + | sym::ptr_write + | sym::ptr_write_bytes + | sym::ptr_write_unaligned + | sym::ptr_write_volatile => (&[0], true), + sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false), + sym::ptr_copy + | sym::ptr_copy_nonoverlapping + | sym::ptr_swap + | sym::ptr_swap_nonoverlapping => (&[0, 1], true), + _ => return, + }; + + for &arg_idx in arg_indices { + if let Some(arg) = args.get(arg_idx) + && let Some(null_span) = is_null_ptr(cx, arg) + && let Some(ty) = cx.typeck_results().expr_ty_opt(arg) + && let RawPtr(ty, _mutbl) = ty.kind() + { + // If ZST are fine, don't lint on them + let typing_env = cx.typing_env(); + if are_zsts_allowed + && cx + .tcx + .layout_of(typing_env.as_query_input(*ty)) + .is_ok_and(|layout| layout.is_1zst()) + { + break; + } + + let diag = if arg.span.contains(null_span) { + InvalidNullArgumentsDiag::NullPtrInline { null_span } + } else { + InvalidNullArgumentsDiag::NullPtrThroughBinding { null_span } + }; + + cx.emit_span_lint(INVALID_NULL_ARGUMENTS, expr.span, diag) + } + } + } + // Catching: // (fn_ptr as * ).is_null() ExprKind::MethodCall(_, receiver, _, _) diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs index 64bfa428ae433..a7295d9c5326c 100644 --- a/compiler/rustc_lint/src/utils.rs +++ b/compiler/rustc_lint/src/utils.rs @@ -6,7 +6,7 @@ use crate::LateContext; /// Given an expression, peel all of casts (` as ...`, `.cast{,_mut,_const}()`, /// `ptr::from_ref()`, ...) and init expressions. /// -/// Returns the outermost expression and a boolean representing if one of the casts was +/// Returns the innermost expression and a boolean representing if one of the casts was /// `UnsafeCell::raw_get()` pub(crate) fn peel_casts<'tcx>( cx: &LateContext<'tcx>, diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs new file mode 100644 index 0000000000000..7948f0d86d09f --- /dev/null +++ b/tests/ui/lint/invalid_null_args.rs @@ -0,0 +1,136 @@ +// check-fail +// run-rustfix + +use std::ptr; +use std::mem; + +unsafe fn null_ptr() { + ptr::write( + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::null_mut() as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ); + + let null_ptr = ptr::null_mut(); + ptr::write( + //~^ ERROR calling this function with a null pointer is undefined behavior + null_ptr as *mut u32, + mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), + ); + + let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::copy::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::copy::(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::copy_nonoverlapping::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::copy_nonoverlapping::( + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::NonNull::dangling().as_ptr(), + ptr::null_mut(), + 0 + ); + + #[derive(Copy, Clone)] + struct A(usize); + let mut v = A(200); + + let _a: A = ptr::read(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::read_unaligned(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read_unaligned(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::read_volatile(ptr::null()); + //~^ ERROR calling this function with a null pointer is undefined behavior + let _a: A = ptr::read_volatile(ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + let _a: A = ptr::replace(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::swap::(ptr::null_mut(), &mut v); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::swap::(&mut v, ptr::null_mut()); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_unaligned(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_volatile(ptr::null_mut(), v); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::write_bytes::(ptr::null_mut(), 42, 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + // with indirections + let const_ptr = null_ptr as *const u8; + let _a: u8 = ptr::read(const_ptr); + //~^ ERROR calling this function with a null pointer is undefined behavior +} + +unsafe fn zst() { + struct Zst; // zero-sized type + + std::slice::from_raw_parts::<()>(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts::(ptr::null(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); + //~^ ERROR calling this function with a null pointer is undefined behavior + + ptr::read::<()>(ptr::null()); + ptr::read::(ptr::null()); + + ptr::write(ptr::null_mut(), ()); + ptr::write(ptr::null_mut(), Zst); + + ptr::copy(ptr::null::<()>(), ptr::null_mut::<()>(), 1); + ptr::copy(ptr::null::(), ptr::null_mut::(), 1); +} + +unsafe fn not_invalid() { + // Simplified false-positive from std quicksort implementation + + let mut a = ptr::null_mut(); + let mut b = (); + + loop { + if false { + break; + } + + a = &raw mut b; + } + + ptr::write(a, ()); +} + +fn main() {} diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr new file mode 100644 index 0000000000000..f95bc2afa829e --- /dev/null +++ b/tests/ui/lint/invalid_null_args.stderr @@ -0,0 +1,330 @@ +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:8:5 + | +LL | / ptr::write( +LL | | +LL | | ptr::null_mut() as *mut u32, + | | --------------- null pointer originates from here +LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), +LL | | ); + | |_____^ + | + = help: for more information, visit and + = note: `#[deny(invalid_null_arguments)]` on by default + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:15:5 + | +LL | / ptr::write( +LL | | +LL | | null_ptr as *mut u32, +LL | | mem::transmute::<[u8; 4], _>([0, 0, 0, 255]), +LL | | ); + | |_____^ + | + = help: for more information, visit and +note: null pointer originates from here + --> $DIR/invalid_null_args.rs:14:20 + | +LL | let null_ptr = ptr::null_mut(); + | ^^^^^^^^^^^^^^^ + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:21:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:23:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:25:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(0 as *mut _, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:27:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts(mem::transmute(0usize), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:30:23 + | +LL | let _: &[usize] = std::slice::from_raw_parts_mut(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:33:5 + | +LL | ptr::copy::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:35:5 + | +LL | ptr::copy::(ptr::NonNull::dangling().as_ptr(), ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:38:5 + | +LL | ptr::copy_nonoverlapping::(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:40:5 + | +LL | / ptr::copy_nonoverlapping::( +LL | | +LL | | ptr::NonNull::dangling().as_ptr(), +LL | | ptr::null_mut(), + | | --------------- null pointer originates from here +LL | | 0 +LL | | ); + | |_____^ + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:51:17 + | +LL | let _a: A = ptr::read(ptr::null()); + | ^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:53:17 + | +LL | let _a: A = ptr::read(ptr::null_mut()); + | ^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:56:17 + | +LL | let _a: A = ptr::read_unaligned(ptr::null()); + | ^^^^^^^^^^^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:58:17 + | +LL | let _a: A = ptr::read_unaligned(ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:61:17 + | +LL | let _a: A = ptr::read_volatile(ptr::null()); + | ^^^^^^^^^^^^^^^^^^^-----------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:63:17 + | +LL | let _a: A = ptr::read_volatile(ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:66:17 + | +LL | let _a: A = ptr::replace(ptr::null_mut(), v); + | ^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:69:5 + | +LL | ptr::swap::(ptr::null_mut(), &mut v); + | ^^^^^^^^^^^^^^^---------------^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:71:5 + | +LL | ptr::swap::(&mut v, ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:74:5 + | +LL | ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:76:5 + | +LL | ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:79:5 + | +LL | ptr::write(ptr::null_mut(), v); + | ^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:82:5 + | +LL | ptr::write_unaligned(ptr::null_mut(), v); + | ^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:85:5 + | +LL | ptr::write_volatile(ptr::null_mut(), v); + | ^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:88:5 + | +LL | ptr::write_bytes::(ptr::null_mut(), 42, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:93:18 + | +LL | let _a: u8 = ptr::read(const_ptr); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: for more information, visit and +note: null pointer originates from here + --> $DIR/invalid_null_args.rs:14:20 + | +LL | let null_ptr = ptr::null_mut(); + | ^^^^^^^^^^^^^^^ + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:100:5 + | +LL | std::slice::from_raw_parts::<()>(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:102:5 + | +LL | std::slice::from_raw_parts::(ptr::null(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:104:5 + | +LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused + --> $DIR/invalid_null_args.rs:106:5 + | +LL | std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ + | | + | null pointer originates from here + | + = help: for more information, visit and + +error: aborting due to 31 previous errors + From b738343a54bdaf009d928737e7c682c72aec475c Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 14:55:46 +0100 Subject: [PATCH 191/333] Drop `clippy::invalid_null_ptr_usage` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy_lints/src/deprecated_lints.rs | 2 + src/tools/clippy/clippy_lints/src/ptr.rs | 73 +--------- src/tools/clippy/tests/ui/crashes/ice-1782.rs | 2 +- .../tests/ui/invalid_null_ptr_usage.fixed | 66 --------- .../clippy/tests/ui/invalid_null_ptr_usage.rs | 66 --------- .../tests/ui/invalid_null_ptr_usage.stderr | 136 ------------------ .../ui/invalid_null_ptr_usage_no_std.fixed | 79 ---------- .../tests/ui/invalid_null_ptr_usage_no_std.rs | 79 ---------- .../ui/invalid_null_ptr_usage_no_std.stderr | 136 ------------------ src/tools/clippy/tests/ui/rename.fixed | 1 + src/tools/clippy/tests/ui/rename.rs | 1 + src/tools/clippy/tests/ui/rename.stderr | 30 ++-- 13 files changed, 24 insertions(+), 648 deletions(-) delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs delete mode 100644 src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 7fa23dad69817..39e4516370709 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -638,7 +638,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::precedence::PRECEDENCE_INFO, crate::precedence::PRECEDENCE_BITS_INFO, crate::ptr::CMP_NULL_INFO, - crate::ptr::INVALID_NULL_PTR_USAGE_INFO, crate::ptr::MUT_FROM_REF_INFO, crate::ptr::PTR_ARG_INFO, crate::ptr::PTR_EQ_INFO, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 0031da406f17f..de66ead4f4204 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -131,6 +131,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ ("clippy::clone_double_ref", "suspicious_double_ref_op"), #[clippy::version = ""] ("clippy::cmp_nan", "invalid_nan_comparisons"), + #[clippy::version = "CURRENT_RUSTC_VERSION"] + ("clippy::invalid_null_ptr_usage", "invalid_null_arguments"), #[clippy::version = "1.86.0"] ("clippy::double_neg", "double_negations"), #[clippy::version = ""] diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 55f1ece05593f..50ef56db167c1 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -125,29 +125,6 @@ declare_clippy_lint! { "fns that create mutable refs from immutable ref args" } -declare_clippy_lint! { - /// ### What it does - /// This lint checks for invalid usages of `ptr::null`. - /// - /// ### Why is this bad? - /// This causes undefined behavior. - /// - /// ### Example - /// ```ignore - /// // Undefined behavior - /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } - /// ``` - /// - /// Use instead: - /// ```ignore - /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } - /// ``` - #[clippy::version = "1.53.0"] - pub INVALID_NULL_PTR_USAGE, - correctness, - "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" -} - declare_clippy_lint! { /// ### What it does /// Use `std::ptr::eq` when applicable @@ -177,7 +154,7 @@ declare_clippy_lint! { "use `std::ptr::eq` when comparing raw pointers" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]); +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, PTR_EQ]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { @@ -301,54 +278,6 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { format!("{non_null_path_snippet}.is_null()"), Applicability::MachineApplicable, ); - } else { - check_invalid_ptr_usage(cx, expr); - } - } -} - -fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let ExprKind::Call(fun, args) = expr.kind - && let ExprKind::Path(ref qpath) = fun.kind - && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id() - && let Some(name) = cx.tcx.get_diagnostic_name(fun_def_id) - { - // TODO: `ptr_slice_from_raw_parts` and its mutable variant should probably still be linted - // conditionally based on how the return value is used, but not universally like the other - // functions since there are valid uses for null slice pointers. - // - // See: https://github.com/rust-lang/rust-clippy/pull/13452/files#r1773772034 - - // `arg` positions where null would cause U.B. - let arg_indices: &[_] = match name { - sym::ptr_read - | sym::ptr_read_unaligned - | sym::ptr_read_volatile - | sym::ptr_replace - | sym::ptr_write - | sym::ptr_write_bytes - | sym::ptr_write_unaligned - | sym::ptr_write_volatile - | sym::slice_from_raw_parts - | sym::slice_from_raw_parts_mut => &[0], - sym::ptr_copy | sym::ptr_copy_nonoverlapping | sym::ptr_swap | sym::ptr_swap_nonoverlapping => &[0, 1], - _ => return, - }; - - for &arg_idx in arg_indices { - if let Some(arg) = args.get(arg_idx).filter(|arg| is_null_path(cx, arg)) - && let Some(std_or_core) = std_or_core(cx) - { - span_lint_and_sugg( - cx, - INVALID_NULL_PTR_USAGE, - arg.span, - "pointer must be non-null", - "change this to", - format!("{std_or_core}::ptr::NonNull::dangling().as_ptr()"), - Applicability::MachineApplicable, - ); - } } } } diff --git a/src/tools/clippy/tests/ui/crashes/ice-1782.rs b/src/tools/clippy/tests/ui/crashes/ice-1782.rs index fefdc405cce2a..4a1886c08af6a 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-1782.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-1782.rs @@ -1,6 +1,6 @@ //@ check-pass -#![allow(dead_code, unused_variables)] +#![allow(dead_code, unused_variables, invalid_null_arguments)] #![allow(clippy::unnecessary_cast, clippy::missing_transmute_annotations)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed deleted file mode 100644 index ce78e89ee829c..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.fixed +++ /dev/null @@ -1,66 +0,0 @@ -fn main() { - unsafe { - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(std::mem::size_of::(), 0); - - let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_unaligned(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_volatile(std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::replace(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); - - std::ptr::swap::(std::ptr::NonNull::dangling().as_ptr(), &mut A); - //~^ invalid_null_ptr_usage - std::ptr::swap::(&mut A, std::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - std::ptr::swap_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), &mut A, 0); - //~^ invalid_null_ptr_usage - std::ptr::swap_nonoverlapping::(&mut A, std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::write(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_unaligned(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_volatile(std::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_bytes::(std::ptr::NonNull::dangling().as_ptr(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs deleted file mode 100644 index 361865fbd9601..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.rs +++ /dev/null @@ -1,66 +0,0 @@ -fn main() { - unsafe { - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(std::mem::size_of::(), 0); - - let _a: A = std::ptr::read(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_unaligned(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::read_volatile(std::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = std::ptr::replace(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); - - std::ptr::swap::(std::ptr::null_mut(), &mut A); - //~^ invalid_null_ptr_usage - std::ptr::swap::(&mut A, std::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); - //~^ invalid_null_ptr_usage - std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - std::ptr::write(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_unaligned(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_volatile(std::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr deleted file mode 100644 index 3f9d15b904018..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage.stderr +++ /dev/null @@ -1,136 +0,0 @@ -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:3:59 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - | - = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:5:59 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:8:63 - | -LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:11:33 - | -LL | std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:13:73 - | -LL | std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:16:48 - | -LL | std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:18:88 - | -LL | std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:24:36 - | -LL | let _a: A = std::ptr::read(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:26:36 - | -LL | let _a: A = std::ptr::read(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:29:46 - | -LL | let _a: A = std::ptr::read_unaligned(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:31:46 - | -LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:34:45 - | -LL | let _a: A = std::ptr::read_volatile(std::ptr::null()); - | ^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:36:45 - | -LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:39:39 - | -LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:44:29 - | -LL | std::ptr::swap::(std::ptr::null_mut(), &mut A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:46:37 - | -LL | std::ptr::swap::(&mut A, std::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:49:44 - | -LL | std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:51:52 - | -LL | std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:54:25 - | -LL | std::ptr::write(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:57:35 - | -LL | std::ptr::write_unaligned(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:60:34 - | -LL | std::ptr::write_volatile(std::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage.rs:63:40 - | -LL | std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `std::ptr::NonNull::dangling().as_ptr()` - -error: aborting due to 22 previous errors - diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed deleted file mode 100644 index df7ab166187de..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.fixed +++ /dev/null @@ -1,79 +0,0 @@ -#![no_std] -#![feature(lang_items)] - -use core::panic::PanicInfo; - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - loop {} -} - -fn main() { - unsafe { - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(core::mem::size_of::(), 0); - - let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); - - core::ptr::swap::(core::ptr::NonNull::dangling().as_ptr(), &mut A); - //~^ invalid_null_ptr_usage - core::ptr::swap::(&mut A, core::ptr::NonNull::dangling().as_ptr()); - //~^ invalid_null_ptr_usage - - core::ptr::swap_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0); - //~^ invalid_null_ptr_usage - core::ptr::swap_nonoverlapping::(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_bytes::(core::ptr::NonNull::dangling().as_ptr(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs deleted file mode 100644 index 38ddfff055353..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.rs +++ /dev/null @@ -1,79 +0,0 @@ -#![no_std] -#![feature(lang_items)] - -use core::panic::PanicInfo; - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} - -#[panic_handler] -fn panic(info: &PanicInfo) -> ! { - loop {} -} - -fn main() { - unsafe { - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0); - //~^ invalid_null_ptr_usage - let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - //~^ invalid_null_ptr_usage - core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - struct A; // zero sized struct - assert_eq!(core::mem::size_of::(), 0); - - let _a: A = core::ptr::read(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_unaligned(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::read_volatile(core::ptr::null()); - //~^ invalid_null_ptr_usage - let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - let _a: A = core::ptr::replace(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - let _slice: *const [usize] = core::ptr::slice_from_raw_parts(core::ptr::null_mut(), 0); // shouldn't lint - let _slice: *const [usize] = core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut(), 0); - - core::ptr::swap::(core::ptr::null_mut(), &mut A); - //~^ invalid_null_ptr_usage - core::ptr::swap::(&mut A, core::ptr::null_mut()); - //~^ invalid_null_ptr_usage - - core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); - //~^ invalid_null_ptr_usage - core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); - //~^ invalid_null_ptr_usage - - core::ptr::write(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_unaligned(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_volatile(core::ptr::null_mut(), A); - //~^ invalid_null_ptr_usage - - core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); - //~^ invalid_null_ptr_usage - } -} diff --git a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr b/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr deleted file mode 100644 index b5dd21ce6248f..0000000000000 --- a/src/tools/clippy/tests/ui/invalid_null_ptr_usage_no_std.stderr +++ /dev/null @@ -1,136 +0,0 @@ -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:16:60 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - | - = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:18:60 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts(core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:21:64 - | -LL | let _slice: &[usize] = core::slice::from_raw_parts_mut(core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:24:34 - | -LL | core::ptr::copy::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:26:75 - | -LL | core::ptr::copy::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:29:49 - | -LL | core::ptr::copy_nonoverlapping::(core::ptr::null(), core::ptr::NonNull::dangling().as_ptr(), 0); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:31:90 - | -LL | core::ptr::copy_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:37:37 - | -LL | let _a: A = core::ptr::read(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:39:37 - | -LL | let _a: A = core::ptr::read(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:42:47 - | -LL | let _a: A = core::ptr::read_unaligned(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:44:47 - | -LL | let _a: A = core::ptr::read_unaligned(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:47:46 - | -LL | let _a: A = core::ptr::read_volatile(core::ptr::null()); - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:49:46 - | -LL | let _a: A = core::ptr::read_volatile(core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:52:40 - | -LL | let _a: A = core::ptr::replace(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:57:30 - | -LL | core::ptr::swap::(core::ptr::null_mut(), &mut A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:59:38 - | -LL | core::ptr::swap::(&mut A, core::ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:62:45 - | -LL | core::ptr::swap_nonoverlapping::(core::ptr::null_mut(), &mut A, 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:64:53 - | -LL | core::ptr::swap_nonoverlapping::(&mut A, core::ptr::null_mut(), 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:67:26 - | -LL | core::ptr::write(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:70:36 - | -LL | core::ptr::write_unaligned(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:73:35 - | -LL | core::ptr::write_volatile(core::ptr::null_mut(), A); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: pointer must be non-null - --> tests/ui/invalid_null_ptr_usage_no_std.rs:76:41 - | -LL | core::ptr::write_bytes::(core::ptr::null_mut(), 42, 0); - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` - -error: aborting due to 22 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 501811fa491b3..7964047069689 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -119,6 +119,7 @@ #![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering` #![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref` #![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked` +#![warn(invalid_null_arguments)] //~ ERROR: lint `clippy::invalid_null_ptr_usage` #![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop` #![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg` #![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum` diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 7f4b8062e1b4b..aa7b905b4b818 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -119,6 +119,7 @@ #![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering` #![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref` #![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked` +#![warn(clippy::invalid_null_ptr_usage)] //~ ERROR: lint `clippy::invalid_null_ptr_usage` #![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop` #![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg` #![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum` diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index f24eaec3917ad..b3c88167c1115 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -343,71 +343,77 @@ error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_fro LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` -error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` +error: lint `clippy::invalid_null_ptr_usage` has been renamed to `invalid_null_arguments` --> tests/ui/rename.rs:122:9 | +LL | #![warn(clippy::invalid_null_ptr_usage)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_null_arguments` + +error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` + --> tests/ui/rename.rs:123:9 + | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:123:9 + --> tests/ui/rename.rs:124:9 | LL | #![warn(clippy::maybe_misused_cfg)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:124:9 + --> tests/ui/rename.rs:125:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:125:9 + --> tests/ui/rename.rs:126:9 | LL | #![warn(clippy::mismatched_target_os)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:126:9 + --> tests/ui/rename.rs:127:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:127:9 + --> tests/ui/rename.rs:128:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:128:9 + --> tests/ui/rename.rs:129:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:129:9 + --> tests/ui/rename.rs:130:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:130:9 + --> tests/ui/rename.rs:131:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:131:9 + --> tests/ui/rename.rs:132:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:132:9 + --> tests/ui/rename.rs:133:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` -error: aborting due to 68 previous errors +error: aborting due to 69 previous errors From aa8848040a160842d47a5a143e04da8ad9f27613 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 9 Mar 2025 22:23:31 +0100 Subject: [PATCH 192/333] Allow `invalid_null_arguments` in some tests --- tests/ui/precondition-checks/copy-nonoverlapping.rs | 2 ++ tests/ui/precondition-checks/copy.rs | 2 ++ tests/ui/precondition-checks/read_volatile.rs | 2 ++ tests/ui/precondition-checks/replace.rs | 2 ++ tests/ui/precondition-checks/slice-from-raw-parts-mut.rs | 2 ++ tests/ui/precondition-checks/slice-from-raw-parts.rs | 2 ++ tests/ui/precondition-checks/swap-nonoverlapping.rs | 2 ++ tests/ui/precondition-checks/write_volatile.rs | 2 ++ tests/ui/precondition-checks/zero-size-null.rs | 2 ++ 9 files changed, 18 insertions(+) diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs index 81018e4bff3e5..eacaa63e543af 100644 --- a/tests/ui/precondition-checks/copy-nonoverlapping.rs +++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs index 694853f950ab5..1fadd90bf70bd 100644 --- a/tests/ui/precondition-checks/copy.rs +++ b/tests/ui/precondition-checks/copy.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::copy requires //@ revisions: null_src null_dst misaligned_src misaligned_dst +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs index e14881d029037..ada8932c398ce 100644 --- a/tests/ui/precondition-checks/read_volatile.rs +++ b/tests/ui/precondition-checks/read_volatile.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs index 2808cee7b64b1..44afbd8174c03 100644 --- a/tests/ui/precondition-checks/replace.rs +++ b/tests/ui/precondition-checks/replace.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::replace requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs index 3801639e2551b..9b9ded69a83b6 100644 --- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs +++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires //@ revisions: null misaligned toolarge +#![allow(invalid_null_arguments)] + fn main() { unsafe { #[cfg(null)] diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs index a3690fa045eb7..96578c1eae58b 100644 --- a/tests/ui/precondition-checks/slice-from-raw-parts.rs +++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires //@ revisions: null misaligned toolarge +#![allow(invalid_null_arguments)] + fn main() { unsafe { #[cfg(null)] diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs index 52e4a3c870be5..ea1f6f36ad787 100644 --- a/tests/ui/precondition-checks/swap-nonoverlapping.rs +++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs index ac0b89b5ecf2a..0d5ecb014b3d9 100644 --- a/tests/ui/precondition-checks/write_volatile.rs +++ b/tests/ui/precondition-checks/write_volatile.rs @@ -3,6 +3,8 @@ //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires //@ revisions: null misaligned +#![allow(invalid_null_arguments)] + use std::ptr; fn main() { diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs index 43a81175f9448..55d768fc9e58e 100644 --- a/tests/ui/precondition-checks/zero-size-null.rs +++ b/tests/ui/precondition-checks/zero-size-null.rs @@ -7,8 +7,10 @@ use std::ptr; fn main() { unsafe { + #[expect(invalid_null_arguments)] // false-positive, copy of 0 ptr::copy_nonoverlapping::(ptr::null(), ptr::null_mut(), 0); ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123); + #[expect(invalid_null_arguments)] // false-positive, copy of 0 ptr::copy::(ptr::null(), ptr::null_mut(), 0); ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123); ptr::swap::<()>(ptr::null_mut(), ptr::null_mut()); From f3cbc3992e1428e92c608410614c3e7b7a64b815 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:13:47 +0200 Subject: [PATCH 193/333] Remove duplicate c-variadic.md --- .../src/library-features/c-variadic.md | 26 ------------------- src/tools/tidy/src/unstable_book.rs | 12 ++++----- 2 files changed, 5 insertions(+), 33 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/c-variadic.md diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md deleted file mode 100644 index 77762116e6b1c..0000000000000 --- a/src/doc/unstable-book/src/library-features/c-variadic.md +++ /dev/null @@ -1,26 +0,0 @@ -# `c_variadic` - -The tracking issue for this feature is: [#44930] - -[#44930]: https://github.com/rust-lang/rust/issues/44930 - ------------------------- - -The `c_variadic` library feature exposes the `VaList` structure, -Rust's analogue of C's `va_list` type. - -## Examples - -```rust -#![feature(c_variadic)] - -use std::ffi::VaList; - -pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize { - let mut sum = 0; - for _ in 0..n { - sum += args.arg::(); - } - sum -} -``` diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 8be25b98df0df..d19de081807d2 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -93,14 +93,12 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { // Check for Unstable Book sections that don't have a corresponding unstable feature for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names { - if !unstable_lang_feature_names.contains(&feature_name) { - tidy_error!( - bad, - "The Unstable Book has a 'library feature' section '{}' which doesn't \ + tidy_error!( + bad, + "The Unstable Book has a 'library feature' section '{}' which doesn't \ correspond to an unstable library feature", - feature_name - ); - } + feature_name + ); } // Check for Unstable Book sections that don't have a corresponding unstable feature. From 14e4f9f245c615cd379397908abc52c795b65d04 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:19:18 +0200 Subject: [PATCH 194/333] Suggest switching underscores for dashes --- src/tools/tidy/src/unstable_book.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index d19de081807d2..a2453a6c96057 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -72,6 +72,19 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) - collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path)) } +/// Would switching underscores for dashes work? +fn maybe_suggest_dashes(names: &BTreeSet, feature_name: &str, bad: &mut bool) { + let with_dashes = feature_name.replace('_', "-"); + if names.contains(&with_dashes) { + tidy_error!( + bad, + "the file `{}.md` contains underscores; use dashes instead: `{}.md`", + feature_name, + with_dashes, + ); + } +} + pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { let lang_features = features.lang; let lib_features = features @@ -99,6 +112,7 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { correspond to an unstable library feature", feature_name ); + maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad); } // Check for Unstable Book sections that don't have a corresponding unstable feature. @@ -110,7 +124,8 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { "The Unstable Book has a 'language feature' section '{}' which doesn't \ correspond to an unstable language feature", feature_name - ) + ); + maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad); } // List unstable features that don't have Unstable Book sections. From 39a491ada3309f47a0c8bdc41748461d00b4f735 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 30 Mar 2025 23:20:04 +0200 Subject: [PATCH 195/333] unstable book: document import_trait_associated_functions --- .../import-trait-associated-functions.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/import-trait-associated-functions.md diff --git a/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md new file mode 100644 index 0000000000000..0ae5915361e51 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/import-trait-associated-functions.md @@ -0,0 +1,22 @@ +# import_trait_associated_functions + +The tracking issue for this feature is: [#134691] + +[#134691]: https://github.com/rust-lang/rust/issues/134691 + +------------------------ + +This feature allows importing associated functions and constants from traits and then using them like regular items. + +```rust +#![feature(import_trait_associated_functions)] + +use std::ops::Add::add; + +fn main() { + let numbers = vec![1, 2, 3, 4, 5, 6]; + let sum = numbers.into_iter().reduce(add); // instead of `.reduce(Add:add)` + + assert_eq!(sum, Some(21)); +} +``` From 8a3ee9755245eccae6327c3f4cc658fe12615b18 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sun, 30 Mar 2025 15:45:44 -0700 Subject: [PATCH 196/333] Apply suggestions from code review Co-authored-by: Mark Rousskov Co-authored-by: alexey semenyuk --- RELEASES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 3047a0c366a42..0948eb85192e5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5,7 +5,7 @@ Version 1.86.0 (2025-04-03) Language -------- -- [Stabilize the ability to upcast a trait object to one of its supertraits.](https://github.com/rust-lang/rust/pull/134367) +- [Stabilize upcasting trait objects to supertraits.](https://github.com/rust-lang/rust/pull/134367) - [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090) - [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397) - Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604) @@ -104,8 +104,9 @@ Compatibility Notes - [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951) Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail. - [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300) -- The future incompatibility lint `cenum_impl_drop_cast` [has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. +- [The future incompatibility lint `cenum_impl_drop_cast` has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`. - [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037) + To compile for pre-SSE2 32-bit x86, use a "i586" target instead. @@ -117,7 +118,7 @@ significant improvements to the performance or internals of rustc and related tools. - [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807) -The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. + The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster. Version 1.85.1 (2025-03-18) From 897acc3e5d3622927118924fa920c8be0ef6f154 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Mar 2025 21:39:12 +0000 Subject: [PATCH 197/333] Encode synthetic by-move coroutine body with a different DefPathData --- compiler/rustc_hir/src/def.rs | 2 +- compiler/rustc_hir/src/definitions.rs | 15 +++++++++++++-- compiler/rustc_middle/src/ty/context.rs | 6 +++--- compiler/rustc_middle/src/ty/print/mod.rs | 7 +++++-- .../rustc_query_system/src/dep_graph/graph.rs | 7 ++++--- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 1 + compiler/rustc_symbol_mangling/src/legacy.rs | 5 ++++- compiler/rustc_symbol_mangling/src/v0.rs | 1 + tests/coverage/async_closure.cov-map | 12 ++++++------ tests/coverage/async_closure.coverage | 2 +- ...-written-closure-synthetic-closure-conflict.rs | 15 +++++++++++++++ ...foo-{closure#0}-{synthetic#0}.built.after.mir} | 4 ++-- .../async_closure_fake_read_for_by_move.rs | 2 +- ...#0}-{closure#0}-{synthetic#0}.built.after.mir} | 4 ++-- ...#0}-{closure#1}-{synthetic#0}.built.after.mir} | 4 ++-- tests/mir-opt/async_closure_shims.rs | 4 ++-- tests/ui/stable-mir-print/async-closure.stdout | 2 +- 17 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 tests/incremental/user-written-closure-synthetic-closure-conflict.rs rename tests/mir-opt/{async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir => async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir} (85%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir => async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir} (80%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir => async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir} (80%) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 5f8941d4754e6..dc00b52a59360 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -294,7 +294,7 @@ impl DefKind { DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, DefKind::Closure => DefPathData::Closure, - DefKind::SyntheticCoroutineBody => DefPathData::Closure, + DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody, } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 61f5efd9978c3..c52954aa96fc8 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -291,6 +291,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// A synthetic body for a coroutine's by-move body. + SyntheticCoroutineBody, } impl Definitions { @@ -415,8 +417,16 @@ impl DefPathData { ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst - | OpaqueTy => None, + Impl + | ForeignMod + | CrateRoot + | Use + | GlobalAsm + | Closure + | Ctor + | AnonConst + | OpaqueTy + | SyntheticCoroutineBody => None, } } @@ -441,6 +451,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, + SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 08d4c1f9cf2f3..618a65a018644 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1930,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> { // As a consequence, this LocalDefId is always re-created before it is needed by the incr. // comp. engine itself. // - // This call also writes to the value of `source_span` and `expn_that_defined` queries. + // This call also writes to the value of the `source_span` query. // This is fine because: - // - those queries are `eval_always` so we won't miss their result changing; - // - this write will have happened before these queries are called. + // - that query is `eval_always` so we won't miss its result changing; + // - this write will have happened before that query is called. let def_id = self.untracked.definitions.write().create_def(parent, data); // This function modifies `self.definitions` using a side-effect. diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index dc2040aa5cf85..5904deaaaad83 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { DefPathData::Closure => { - // FIXME(async_closures): This is somewhat ugly. - // We need to additionally print the `kind` field of a closure if + // We need to additionally print the `kind` field of a coroutine if // it is desugared from a coroutine-closure. if let Some(hir::CoroutineKind::Desugared( _, @@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized { // Closures' own generics are only captures, don't print them. } } + DefPathData::SyntheticCoroutineBody => { + // Synthetic coroutine bodies have no distinct generics, since like + // closures they're all just internal state of the coroutine. + } // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 495f34733f704..127dcd825da56 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -66,6 +66,7 @@ pub struct MarkFrame<'a> { parent: Option<&'a MarkFrame<'a>>, } +#[derive(Debug)] pub(super) enum DepNodeColor { Red, Green(DepNodeIndex), @@ -909,7 +910,7 @@ impl DepGraphData { self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame); if node_index.is_some() { - debug!("managed to MARK dependency {dep_dep_node:?} as green",); + debug!("managed to MARK dependency {dep_dep_node:?} as green"); return Some(()); } } @@ -930,7 +931,7 @@ impl DepGraphData { return Some(()); } Some(DepNodeColor::Red) => { - debug!("dependency {dep_dep_node:?} was red after forcing",); + debug!("dependency {dep_dep_node:?} was red after forcing"); return None; } None => {} @@ -950,7 +951,7 @@ impl DepGraphData { // invalid state will not be persisted to the // incremental compilation cache because of // compilation errors being present. - debug!("dependency {dep_dep_node:?} resulted in compilation error",); + debug!("dependency {dep_dep_node:?} resulted in compilation error"); return None; } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index e088417d72e35..d56ca9c245386 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::Ctor => "c", hir::definitions::DefPathData::AnonConst => "k", hir::definitions::DefPathData::OpaqueTy => "i", + hir::definitions::DefPathData::SyntheticCoroutineBody => "s", hir::definitions::DefPathData::CrateRoot | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 88754f1f15b46..2802e8918073f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>( loop { let key = tcx.def_key(ty_def_id); match key.disambiguated_data.data { - DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => { + DefPathData::TypeNs(_) + | DefPathData::ValueNs(_) + | DefPathData::Closure + | DefPathData::SyntheticCoroutineBody => { instance_ty = tcx.type_of(ty_def_id).instantiate_identity(); debug!(?instance_ty); break; diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d824a23279b1b..99d44bcd7eb80 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { DefPathData::Ctor => 'c', DefPathData::AnonConst => 'k', DefPathData::OpaqueTy => 'i', + DefPathData::SyntheticCoroutineBody => 's', // These should never show up as `path_append` arguments. DefPathData::CrateRoot diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 9144a938a9e24..0e1d987783075 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -38,21 +38,21 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) Highest counter ID seen: c0 -Function name: async_closure::main::{closure#0}::{closure#0}:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] +Function name: async_closure::main::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) +- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) Highest counter ID seen: c0 -Function name: async_closure::main::{closure#0}::{closure#1}:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Function name: async_closure::main::{closure#0}::{closure#0}:: +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36) Highest counter ID seen: c0 diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index 7fbea26581258..10a8ea14504b3 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -14,7 +14,7 @@ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ - | async_closure::main::{closure#0}::{closure#1}::: + | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ LL| 1| executor::block_on(async_closure()); diff --git a/tests/incremental/user-written-closure-synthetic-closure-conflict.rs b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs new file mode 100644 index 0000000000000..618604d06b173 --- /dev/null +++ b/tests/incremental/user-written-closure-synthetic-closure-conflict.rs @@ -0,0 +1,15 @@ +//@ revisions: rpass1 rpass2 +//@ edition: 2024 + +#![allow(unused)] + +fn main() { + #[cfg(rpass1)] + async || {}; + + #[cfg(rpass2)] + || { + || (); + || (); + }; +} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir similarity index 85% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index bd0baddb1f892..9070c95bca4d4 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `foo::{closure#0}::{closure#1}` after built +// MIR for `foo::{closure#0}::{synthetic#0}` after built -fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () +fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs index 3c5aec94bbfe5..e78671f5e9d56 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.rs +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs @@ -7,7 +7,7 @@ enum Foo { } // EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir fn foo(f: &Foo) { let x = async move || match f { Foo::Bar if true => {} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir similarity index 80% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir index a9e08d2e8f60f..c5f538e5ecd83 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built +// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built -fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir similarity index 80% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir index 4452ae7812e36..e295f9b3cf120 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built +// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built -fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index cd2e83e939abe..93cc7834a643f 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -42,11 +42,11 @@ async fn call_normal_mut>(f: &mut impl FnMut(i32) -> F) { // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir pub fn main() { block_on(async { let b = 2i32; diff --git a/tests/ui/stable-mir-print/async-closure.stdout b/tests/ui/stable-mir-print/async-closure.stdout index 21df1fd395403..12e7a5530ace6 100644 --- a/tests/ui/stable-mir-print/async-closure.stdout +++ b/tests/ui/stable-mir-print/async-closure.stdout @@ -56,7 +56,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo unreachable; } } -fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { +fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { let mut _0: Poll<()>; let _3: i32; let mut _4: &i32; From 73d33ed1bafdf3c0b32e936492eb6a9cdd9b080c Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 31 Mar 2025 01:26:55 +0200 Subject: [PATCH 198/333] Remove mention of `exhaustive_patterns` from `never` docs --- library/core/src/primitive_docs.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 89c856fe10746..ba4c849837e74 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -127,15 +127,13 @@ mod prim_bool {} /// [`Result`] which we can unpack like this: /// /// ``` -/// #![feature(exhaustive_patterns)] /// use std::str::FromStr; /// let Ok(s) = String::from_str("hello"); /// ``` /// -/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns` -/// feature is present this means we can exhaustively match on [`Result`] by just taking the -/// [`Ok`] variant. This illustrates another behavior of `!` - it can be used to "delete" certain -/// enum variants from generic types like `Result`. +/// Since the [`Err`] variant contains a `!`, it can never occur. This means we can exhaustively +/// match on [`Result`] by just taking the [`Ok`] variant. This illustrates another behavior +/// of `!` - it can be used to "delete" certain enum variants from generic types like `Result`. /// /// ## Infinite loops /// From 0666b740e5fd06f682a9a8d539b6ea3bb1d56538 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:49:58 +0000 Subject: [PATCH 199/333] Simplify find_commandline_library --- compiler/rustc_metadata/src/locator.rs | 44 ++++++++++---------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index d5dd5059aacc6..038236827489f 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -728,37 +728,25 @@ impl<'a> CrateLocator<'a> { let Some(file) = loc_orig.file_name().and_then(|s| s.to_str()) else { return Err(CrateError::ExternLocationNotFile(self.crate_name, loc_orig.clone())); }; - // FnMut cannot return reference to captured value, so references - // must be taken outside the closure. - let rlibs = &mut rlibs; - let rmetas = &mut rmetas; - let dylibs = &mut dylibs; - let type_via_filename = (|| { - if file.starts_with("lib") { - if file.ends_with(".rlib") { - return Some(rlibs); - } - if file.ends_with(".rmeta") { - return Some(rmetas); - } - } - let dll_prefix = self.target.dll_prefix.as_ref(); - let dll_suffix = self.target.dll_suffix.as_ref(); - if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { - return Some(dylibs); - } - None - })(); - match type_via_filename { - Some(type_via_filename) => { - type_via_filename.insert(loc_canon.clone(), PathKind::ExternFlag); + if file.starts_with("lib") { + if file.ends_with(".rlib") { + rlibs.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; } - None => { - self.crate_rejections - .via_filename - .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); + if file.ends_with(".rmeta") { + rmetas.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; } } + let dll_prefix = self.target.dll_prefix.as_ref(); + let dll_suffix = self.target.dll_suffix.as_ref(); + if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { + dylibs.insert(loc_canon.clone(), PathKind::ExternFlag); + continue; + } + self.crate_rejections + .via_filename + .push(CrateMismatch { path: loc_orig.clone(), got: String::new() }); } // Extract the dylib/rlib/rmeta triple. From 9800eb2cabd962ff1899e94841b15ca9dc874528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 20 Feb 2025 21:23:10 +0100 Subject: [PATCH 200/333] Add `-Zembed-metadata` CLI option --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b44be1710edf7..4592e01443880 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -787,6 +787,7 @@ fn test_unstable_options_tracking_hash() { tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(embed_metadata, false); tracked!(embed_source, true); tracked!(emit_thin_lto, false); tracked!(emscripten_wasm_eh, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4cc666b3e37d2..cd5e2c4173e7b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2175,6 +2175,8 @@ options! { them only if an error has not been emitted"), ehcont_guard: bool = (false, parse_bool, [TRACKED], "generate Windows EHCont Guard tables"), + embed_metadata: bool = (true, parse_bool, [TRACKED], + "embed metadata in rlibs and dylibs (default: yes)"), embed_source: bool = (false, parse_bool, [TRACKED], "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], From a5057b786b1f6fd04c4b590ea7eb160e36c281db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 20 Feb 2025 21:34:11 +0100 Subject: [PATCH 201/333] Add documentation of the option into the unstable book --- src/doc/unstable-book/src/compiler-flags/embed-metadata.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/embed-metadata.md diff --git a/src/doc/unstable-book/src/compiler-flags/embed-metadata.md b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md new file mode 100644 index 0000000000000..a2a790ee76af3 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/embed-metadata.md @@ -0,0 +1,3 @@ +## `embed-metadata` + +This option instructs `rustc` to include the full metadata in `rlib` and `dylib` crate types. The default value is `yes` (enabled). If disabled (`no`), only stub metadata will be stored in these files, to reduce their size on disk. When using `-Zembed-metadata=no`, you will probably want to use `--emit=metadata` to produce the full metadata into a separate `.rmeta` file. From 4dca28cfa27661e0d87f9de23761445cac62d2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 28 Mar 2025 17:58:23 +0100 Subject: [PATCH 202/333] Store only a metadata stub into `rlibs` and `dylibs` with `-Zembed-metadata=no` --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- .../rustc_codegen_ssa/src/back/metadata.rs | 4 +- compiler/rustc_metadata/src/fs.rs | 26 ++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 91 +++++++++++++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 6 ++ 5 files changed, 101 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b59d73a9aae09..7d41108724175 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -294,7 +294,7 @@ fn link_rlib<'a>( let (metadata, metadata_position) = create_wrapper_file( sess, ".rmeta".to_string(), - codegen_results.metadata.raw_data(), + codegen_results.metadata.stub_or_full(), ); let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME); match metadata_position { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 68b453ff42425..ac9ac9bbb31f6 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -540,8 +540,8 @@ pub fn create_compressed_metadata_file( symbol_name: &str, ) -> Vec { let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec(); - packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap(); - packed_metadata.extend(metadata.raw_data()); + packed_metadata.write_all(&(metadata.stub_or_full().len() as u64).to_le_bytes()).unwrap(); + packed_metadata.extend(metadata.stub_or_full()); let Some(mut file) = create_object_file(sess) else { if sess.target.is_like_wasm { diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 4450d050c8e1f..c4e1e0f1d1a99 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -3,7 +3,7 @@ use std::{fs, io}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{OutFileName, OutputType}; +use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; use rustc_session::{MetadataKind, Session}; use tempfile::Builder as TempFileBuilder; @@ -50,7 +50,14 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { .tempdir_in(out_filename.parent().unwrap_or_else(|| Path::new(""))) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailedCreateTempdir { err })); let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); - let metadata_filename = metadata_tmpdir.as_ref().join(METADATA_FILENAME); + let metadata_filename = metadata_tmpdir.as_ref().join("full.rmeta"); + let metadata_stub_filename = if !tcx.sess.opts.unstable_opts.embed_metadata + && !tcx.crate_types().contains(&CrateType::ProcMacro) + { + Some(metadata_tmpdir.as_ref().join("stub.rmeta")) + } else { + None + }; // Always create a file at `metadata_filename`, even if we have nothing to write to it. // This simplifies the creation of the output `out_filename` when requested. @@ -60,9 +67,15 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); }); + if let Some(metadata_stub_filename) = &metadata_stub_filename { + std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| { + tcx.dcx() + .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err }); + }); + } } MetadataKind::Uncompressed | MetadataKind::Compressed => { - encode_metadata(tcx, &metadata_filename); + encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref()) } }; @@ -100,9 +113,10 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { // Load metadata back to memory: codegen may need to include it in object files. let metadata = - EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { - tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); - }); + EncodedMetadata::from_path(metadata_filename, metadata_stub_filename, metadata_tmpdir) + .unwrap_or_else(|err| { + tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); + }); let need_metadata_module = metadata_kind == MetadataKind::Compressed; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ab3d432bdf81..386d3d3156a1c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -701,6 +701,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), is_proc_macro_crate: proc_macro_data.is_some(), + is_stub: false, }, extra_filename: tcx.sess.opts.cg.extra_filename.clone(), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), @@ -2231,8 +2232,12 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { // generated regardless of trailing bytes that end up in it. pub struct EncodedMetadata { - // The declaration order matters because `mmap` should be dropped before `_temp_dir`. - mmap: Option, + // The declaration order matters because `full_metadata` should be dropped + // before `_temp_dir`. + full_metadata: Option, + // This is an optional stub metadata containing only the crate header. + // The header should be very small, so we load it directly into memory. + stub_metadata: Option>, // We need to carry MaybeTempDir to avoid deleting the temporary // directory while accessing the Mmap. _temp_dir: Option, @@ -2240,33 +2245,50 @@ pub struct EncodedMetadata { impl EncodedMetadata { #[inline] - pub fn from_path(path: PathBuf, temp_dir: Option) -> std::io::Result { + pub fn from_path( + path: PathBuf, + stub_path: Option, + temp_dir: Option, + ) -> std::io::Result { let file = std::fs::File::open(&path)?; let file_metadata = file.metadata()?; if file_metadata.len() == 0 { - return Ok(Self { mmap: None, _temp_dir: None }); + return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None }); } - let mmap = unsafe { Some(Mmap::map(file)?) }; - Ok(Self { mmap, _temp_dir: temp_dir }) + let full_mmap = unsafe { Some(Mmap::map(file)?) }; + + let stub = + if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None }; + + Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir }) + } + + #[inline] + pub fn full(&self) -> &[u8] { + &self.full_metadata.as_deref().unwrap_or_default() } #[inline] - pub fn raw_data(&self) -> &[u8] { - self.mmap.as_deref().unwrap_or_default() + pub fn stub_or_full(&self) -> &[u8] { + self.stub_metadata.as_deref().unwrap_or(self.full()) } } impl Encodable for EncodedMetadata { fn encode(&self, s: &mut S) { - let slice = self.raw_data(); + self.stub_metadata.encode(s); + + let slice = self.full(); slice.encode(s) } } impl Decodable for EncodedMetadata { fn decode(d: &mut D) -> Self { + let stub = >>::decode(d); + let len = d.read_usize(); - let mmap = if len > 0 { + let full_metadata = if len > 0 { let mut mmap = MmapMut::map_anon(len).unwrap(); mmap.copy_from_slice(d.read_raw_bytes(len)); Some(mmap.make_read_only().unwrap()) @@ -2274,11 +2296,11 @@ impl Decodable for EncodedMetadata { None }; - Self { mmap, _temp_dir: None } + Self { full_metadata, stub_metadata: stub, _temp_dir: None } } } -pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { +pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); // Since encoding metadata is not in a query, and nothing is cached, @@ -2292,6 +2314,42 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE)); } + with_encode_metadata_header(tcx, path, |ecx| { + // Encode all the entries and extra information in the crate, + // culminating in the `CrateRoot` which points to all of it. + let root = ecx.encode_crate_root(); + + // Flush buffer to ensure backing file has the correct size. + ecx.opaque.flush(); + // Record metadata size for self-profiling + tcx.prof.artifact_size( + "crate_metadata", + "crate_metadata", + ecx.opaque.file().metadata().unwrap().len(), + ); + + root.position.get() + }); + + if let Some(ref_path) = ref_path { + with_encode_metadata_header(tcx, ref_path, |ecx| { + let header: LazyValue = ecx.lazy(CrateHeader { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + hash: tcx.crate_hash(LOCAL_CRATE), + is_proc_macro_crate: false, + is_stub: true, + }); + header.position.get() + }); + } +} + +fn with_encode_metadata_header( + tcx: TyCtxt<'_>, + path: &Path, + f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize, +) { let mut encoder = opaque::FileEncoder::new(path) .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); @@ -2326,9 +2384,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { // Encode the rustc version string in a predictable location. rustc_version(tcx.sess.cfg_version).encode(&mut ecx); - // Encode all the entries and extra information in the crate, - // culminating in the `CrateRoot` which points to all of it. - let root = ecx.encode_crate_root(); + let root_position = f(&mut ecx); // Make sure we report any errors from writing to the file. // If we forget this, compilation can succeed with an incomplete rmeta file, @@ -2338,12 +2394,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) { } let file = ecx.opaque.file(); - if let Err(err) = encode_root_position(file, root.position.get()) { + if let Err(err) = encode_root_position(file, root_position) { tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); } - - // Record metadata size for self-profiling - tcx.prof.artifact_size("crate_metadata", "crate_metadata", file.metadata().unwrap().len()); } fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747ca..bbdc986ef7a26 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -221,6 +221,12 @@ pub(crate) struct CrateHeader { /// This is separate from [`ProcMacroData`] to avoid having to update [`METADATA_VERSION`] every /// time ProcMacroData changes. pub(crate) is_proc_macro_crate: bool, + /// Whether this crate metadata section is just a stub. + /// Stubs do not contain the full metadata (it will be typically stored + /// in a separate rmeta file). + /// + /// This is used inside rlibs and dylibs when using `-Zembed-metadata=no`. + pub(crate) is_stub: bool, } /// Serialized `.rmeta` data for a crate. From 674a7adf9bd765354f58c50f3632f3410a6ac9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 11:45:22 +0100 Subject: [PATCH 203/333] Add an error when full metadata was not found --- compiler/rustc_metadata/messages.ftl | 4 ++++ compiler/rustc_metadata/src/errors.rs | 9 +++++++++ compiler/rustc_metadata/src/locator.rs | 23 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 9adbcabcf4506..d997ba198aca8 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -97,6 +97,10 @@ metadata_found_staticlib = found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} .help = please recompile that crate using --crate-type lib +metadata_full_metadata_not_found = + only metadata stub found for `{$flavor}` dependency `{$crate_name}` + please provide path to the corresponding .rmeta file with full metadata + metadata_global_alloc_required = no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 0c54628598c48..c45daeda85dbc 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -525,6 +525,15 @@ impl Diagnostic<'_, G> for MultipleCandidates { } } +#[derive(Diagnostic)] +#[diag(metadata_full_metadata_not_found)] +pub(crate) struct FullMetadataNotFound { + #[primary_span] + pub span: Span, + pub flavor: CrateFlavor, + pub crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_symbol_conflicts_current, code = E0519)] pub struct SymbolConflictsCurrent { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 038236827489f..112954eca0dfe 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -654,7 +654,24 @@ impl<'a> CrateLocator<'a> { continue; } } - *slot = Some((hash, metadata, lib.clone())); + + // We error eagerly here. If we're locating a rlib, then in theory the full metadata + // could still be in a (later resolved) dylib. In practice, if the rlib and dylib + // were produced in a way where one has full metadata and the other hasn't, it would + // mean that they were compiled using different compiler flags and probably also have + // a different SVH value. + if metadata.get_header().is_stub { + // `is_stub` should never be true for .rmeta files. + assert_ne!(flavor, CrateFlavor::Rmeta); + + // Because rmeta files are resolved before rlib/dylib files, if this is a stub and + // we haven't found a slot already, it means that the full metadata is missing. + if slot.is_none() { + return Err(CrateError::FullMetadataNotFound(self.crate_name, flavor)); + } + } else { + *slot = Some((hash, metadata, lib.clone())); + } ret = Some((lib, kind)); } @@ -916,6 +933,7 @@ pub(crate) enum CrateError { ExternLocationNotExist(Symbol, PathBuf), ExternLocationNotFile(Symbol, PathBuf), MultipleCandidates(Symbol, CrateFlavor, Vec), + FullMetadataNotFound(Symbol, CrateFlavor), SymbolConflictsCurrent(Symbol), StableCrateIdCollision(Symbol, Symbol), DlOpen(String, String), @@ -966,6 +984,9 @@ impl CrateError { CrateError::MultipleCandidates(crate_name, flavor, candidates) => { dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); } + CrateError::FullMetadataNotFound(crate_name, flavor) => { + dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor }); + } CrateError::SymbolConflictsCurrent(root_name) => { dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); } From 5a71da56d88b52a89b24dd64dad4421994a7a39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 14 Mar 2025 11:45:25 +0100 Subject: [PATCH 204/333] Add tests --- tests/run-make/embed-metadata/dep1.rs | 1 + tests/run-make/embed-metadata/foo.rs | 5 ++ tests/run-make/embed-metadata/rmake.rs | 86 ++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 tests/run-make/embed-metadata/dep1.rs create mode 100644 tests/run-make/embed-metadata/foo.rs create mode 100644 tests/run-make/embed-metadata/rmake.rs diff --git a/tests/run-make/embed-metadata/dep1.rs b/tests/run-make/embed-metadata/dep1.rs new file mode 100644 index 0000000000000..be70c3933e098 --- /dev/null +++ b/tests/run-make/embed-metadata/dep1.rs @@ -0,0 +1 @@ +pub fn func_dep1() {} diff --git a/tests/run-make/embed-metadata/foo.rs b/tests/run-make/embed-metadata/foo.rs new file mode 100644 index 0000000000000..0cc9cede86082 --- /dev/null +++ b/tests/run-make/embed-metadata/foo.rs @@ -0,0 +1,5 @@ +extern crate dep1; + +fn main() { + dep1::func_dep1(); +} diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs new file mode 100644 index 0000000000000..acefb18648440 --- /dev/null +++ b/tests/run-make/embed-metadata/rmake.rs @@ -0,0 +1,86 @@ +// Tests the -Zembed-metadata compiler flag. +// Tracking issue: https://github.com/rust-lang/rust/issues/139165 + +use run_make_support::rfs::{create_dir, remove_file, rename}; +use run_make_support::{Rustc, dynamic_lib_name, path, run_in_tmpdir, rust_lib_name, rustc}; + +#[derive(Debug, Copy, Clone)] +enum LibraryKind { + Rlib, + Dylib, +} + +impl LibraryKind { + fn crate_type(&self) -> &str { + match self { + LibraryKind::Rlib => "rlib", + LibraryKind::Dylib => "dylib", + } + } + + fn add_extern(&self, rustc: &mut Rustc, dep_name: &str, dep_path: &str) { + let dep_path = match self { + LibraryKind::Dylib => format!("{dep_path}/{}", dynamic_lib_name(dep_name)), + LibraryKind::Rlib => format!("{dep_path}/{}", rust_lib_name(dep_name)), + }; + rustc.extern_(dep_name, dep_path); + } +} + +fn main() { + // The compiler takes different paths based on if --extern is passed or not, so we test all + // combinations (`rlib`/`dylib` x `--extern`/`no --extern`). + for kind in [LibraryKind::Rlib, LibraryKind::Dylib] { + eprintln!("Testing library kind {kind:?}"); + lookup_rmeta_in_lib_dir(kind); + lookup_rmeta_through_extern(kind); + lookup_rmeta_missing(kind); + } +} + +// Lookup .rmeta file in the same directory as a rlib/dylib with stub metadata. +fn lookup_rmeta_in_lib_dir(kind: LibraryKind) { + run_in_tmpdir(|| { + build_dep_rustc(kind).run(); + rustc().input("foo.rs").run(); + }); +} + +// Lookup .rmeta file when specifying the dependency using --extern. +fn lookup_rmeta_through_extern(kind: LibraryKind) { + run_in_tmpdir(|| { + // Generate libdep1.rlib and libdep1.rmeta in deps + create_dir("deps"); + build_dep_rustc(kind).out_dir("deps").run(); + + let mut rustc = rustc(); + kind.add_extern(&mut rustc, "dep1", "deps"); + rustc.extern_("dep1", path("deps").join("libdep1.rmeta")); + rustc.input("foo.rs").run(); + }); +} + +// Check the error message when the .rmeta file is missing. +fn lookup_rmeta_missing(kind: LibraryKind) { + run_in_tmpdir(|| { + create_dir("deps"); + build_dep_rustc(kind).out_dir("deps").run(); + + let mut rustc = rustc(); + kind.add_extern(&mut rustc, "dep1", "deps"); + rustc.input("foo.rs").run_fail().assert_stderr_contains("only metadata stub found"); + }); +} + +fn build_dep_rustc(kind: LibraryKind) -> Rustc { + let mut dep_rustc = rustc(); + dep_rustc + .arg("-Zembed-metadata=no") + .crate_type(kind.crate_type()) + .input("dep1.rs") + .emit("metadata,link"); + if matches!(kind, LibraryKind::Dylib) { + dep_rustc.arg("-Cprefer-dynamic"); + } + dep_rustc +} From 53f4397bd9c6b83936725fcf8d640be231c6facd Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 31 Mar 2025 11:01:46 +0100 Subject: [PATCH 205/333] Remove Amanieu from the libs review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 217da9935383c..3e7a441c45324 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1161,7 +1161,6 @@ compiler = [ ] libs = [ "@Mark-Simulacrum", - "@Amanieu", "@Noratrieb", "@workingjubilee", "@joboet", From 4e99dca8c35b37fcf097e7bd3c2b00abb7a64dfb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 31 Mar 2025 15:37:16 +0200 Subject: [PATCH 206/333] Remove fragile equal-pointers-unequal/*/print3.rs tests. --- .../equal-pointers-unequal/as-cast/print3.rs | 23 ----------------- .../exposed-provenance/print3.rs | 25 ------------------- .../strict-provenance/print3.rs | 25 ------------------- 3 files changed, 73 deletions(-) delete mode 100644 tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs delete mode 100644 tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs delete mode 100644 tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs deleted file mode 100644 index eda83e999a528..0000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -fn main() { - let a = { - let v = 0; - &v as *const _ as usize - }; - let b = { - let v = 0; - &v as *const _ as usize - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs deleted file mode 100644 index c7f46318aaef7..0000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).expose_provenance() - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs deleted file mode 100644 index a02ff30918daf..0000000000000 --- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #107975 -//@ compile-flags: -Copt-level=2 -//@ run-pass - -// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499 - -use std::ptr; - -fn main() { - let a: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - let b: usize = { - let v = 0; - ptr::from_ref(&v).addr() - }; - - assert_ne!(a, b); - assert_ne!(a, b); - let c = a; - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false"); - println!("{a} {b}"); - assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true"); -} From dea947212795fb4fcdef2b2351008d08be3fb854 Mon Sep 17 00:00:00 2001 From: reez12g Date: Sun, 30 Mar 2025 17:53:19 +0900 Subject: [PATCH 207/333] Add tests for LLVM 20 slice bounds check optimization --- .../slice-last-elements-optimization.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/codegen/slice-last-elements-optimization.rs diff --git a/tests/codegen/slice-last-elements-optimization.rs b/tests/codegen/slice-last-elements-optimization.rs new file mode 100644 index 0000000000000..b90f91d7b17b9 --- /dev/null +++ b/tests/codegen/slice-last-elements-optimization.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +//@ min-llvm-version: 20 +#![crate_type = "lib"] + +// This test verifies that LLVM 20 properly optimizes the bounds check +// when accessing the last few elements of a slice with proper conditions. +// Previously, this would generate an unreachable branch to +// slice_start_index_len_fail even when the bounds check was provably safe. + +// CHECK-LABEL: @last_four_initial( +#[no_mangle] +pub fn last_four_initial(s: &[u8]) -> &[u8] { + // Previously this would generate a branch to slice_start_index_len_fail + // that is unreachable. The LLVM 20 fix should eliminate this branch. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + let start = if s.len() <= 4 { 0 } else { s.len() - 4 }; + &s[start..] +} + +// CHECK-LABEL: @last_four_optimized( +#[no_mangle] +pub fn last_four_optimized(s: &[u8]) -> &[u8] { + // This version was already correctly optimized before the fix in LLVM 20. + // CHECK-NOT: slice_start_index_len_fail + // CHECK-NOT: unreachable + if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] } +} + +// Just to verify we're correctly checking for the right thing +// CHECK-LABEL: @test_bounds_check_happens( +#[no_mangle] +pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] { + // CHECK: slice_start_index_len_fail + &s[i..] +} From 1238a20d38d976ccd4ccecf1b9e2cab039ab6d63 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 31 Mar 2025 17:58:05 +0200 Subject: [PATCH 208/333] Expose `LintLevelsBuilder` with crate root builder --- compiler/rustc_lint/src/levels.rs | 13 +++++++++++++ compiler/rustc_lint/src/lib.rs | 1 + 2 files changed, 14 insertions(+) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 8718fb807ecf5..313d8f6ba8ff4 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -450,6 +450,19 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { builder } + pub fn crate_root( + sess: &'s Session, + features: &'s Features, + lint_added_lints: bool, + store: &'s LintStore, + registered_tools: &'s RegisteredTools, + crate_attrs: &[ast::Attribute], + ) -> Self { + let mut builder = Self::new(sess, features, lint_added_lints, store, registered_tools); + builder.add(crate_attrs, true, None); + builder + } + fn process_command_line(&mut self) { self.provider.cur = self .provider diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a754001811..0c875a4b1bc05 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -129,6 +129,7 @@ pub use context::{ }; pub use early::{EarlyCheckNode, check_ast_node}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; +pub use levels::LintLevelsBuilder; pub use passes::{EarlyLintPass, LateLintPass}; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{ From 69cb0a9e15393bf9dea483725a2cfdba74dff47d Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 31 Mar 2025 18:00:28 +0200 Subject: [PATCH 209/333] Expose `registered_tools` directly without `TyCtxt`-query --- compiler/rustc_resolve/src/lib.rs | 2 ++ compiler/rustc_resolve/src/macros.rs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 78153fd417407..6ef26d7d53a64 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -88,6 +88,8 @@ mod late; mod macros; pub mod rustdoc; +pub use macros::registered_tools_ast; + rustc_fluent_macro::fluent_messages! { "../messages.ftl" } #[derive(Debug)] diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 3637854f1204f..49156f2d856c5 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -10,7 +10,7 @@ use rustc_ast::{self as ast, Crate, NodeId, attr}; use rustc_ast_pretty::pprust; use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr}; use rustc_data_structures::intern::Interned; -use rustc_errors::{Applicability, StashKey}; +use rustc_errors::{Applicability, DiagCtxtHandle, StashKey}; use rustc_expand::base::{ DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind, }; @@ -124,14 +124,21 @@ fn fast_print_path(path: &ast::Path) -> Symbol { } pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { - let mut registered_tools = RegisteredTools::default(); let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow(); + registered_tools_ast(tcx.dcx(), pre_configured_attrs) +} + +pub fn registered_tools_ast( + dcx: DiagCtxtHandle<'_>, + pre_configured_attrs: &[ast::Attribute], +) -> RegisteredTools { + let mut registered_tools = RegisteredTools::default(); for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) { for meta_item_inner in attr.meta_item_list().unwrap_or_default() { match meta_item_inner.ident() { Some(ident) => { if let Some(old_ident) = registered_tools.replace(ident) { - tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered { + dcx.emit_err(errors::ToolWasAlreadyRegistered { span: ident.span, tool: ident, old_ident_span: old_ident.span, @@ -139,7 +146,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } } None => { - tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers { + dcx.emit_err(errors::ToolOnlyAcceptsIdentifiers { span: meta_item_inner.span(), tool: sym::register_tool, }); From 3ef1a3f1c5775357c6192584a42bb6469c1f51b8 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 31 Mar 2025 16:10:02 +0000 Subject: [PATCH 210/333] Remove ChrisDenton from on vacation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 217da9935383c..47a8c588ad9e5 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1124,7 +1124,6 @@ warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", - "ChrisDenton", "saethlin", ] From 753968162a423d5a63ca86ef509d4aaf18ac1f9a Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 31 Mar 2025 16:42:01 +0000 Subject: [PATCH 211/333] Fix invalid link --- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ac98cbc8d6cba..0ffaef82f1c8e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -953,7 +953,7 @@ impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { /// environment. `ParamEnv` is the type that represents this information. See the /// [dev guide chapter][param_env_guide] for more information. /// -/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html +/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(HashStable, TypeVisitable, TypeFoldable)] pub struct ParamEnv<'tcx> { @@ -977,7 +977,7 @@ impl<'tcx> ParamEnv<'tcx> { /// to use an empty environment. See the [dev guide section][param_env_guide] /// for information on what a `ParamEnv` is and how to acquire one. /// - /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html + /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html #[inline] pub fn empty() -> Self { Self::new(ListWithCachedTypeInfo::empty()) From ebca98fa2ff11cf1fc4d753a12db4b1c0bddeda9 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 31 Mar 2025 16:39:25 +0200 Subject: [PATCH 212/333] Remove cjgillot from automated review assignment --- triagebot.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index ebbcfa4516b99..865429cf5fa0c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1115,7 +1115,6 @@ compiler_leads = [ ] compiler = [ "@BoxyUwU", - "@cjgillot", "@compiler-errors", "@davidtwco", "@estebank", @@ -1171,7 +1170,7 @@ codegen = [ "@workingjubilee", ] query-system = [ - "@cjgillot", + "@oli-obk", ] incremental = [ "@wesleywiser", From b14a0ce7f6b9b72d3495fc9b0d632fd14400dcec Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 31 Mar 2025 14:34:14 -0400 Subject: [PATCH 213/333] PassWrapper: adapt for llvm/llvm-project@94122d58fc77079a291a3d008914006cb509d9db We also have to remove the LLVM argument in cast-target-abi.rs for LLVM 21. I'm not really sure what the best approach here is since that test already uses revisions. We could also fork the test into a copy for LLVM 19-20 and another for LLVM 21, but what I did for now was drop the lint-abort-on-error flag to LLVM figuring that some coverage was better than none, but I'm happy to change this if that was a bad direction. The above also applies for ffi-out-of-bounds-loads.rs. r? dianqk @rustbot label llvm-main --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 13 +++++++++---- tests/codegen/cast-target-abi.rs | 2 +- tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 86f1bcc46eea1..257bdc01993fb 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -855,10 +855,15 @@ extern "C" LLVMRustResult LLVMRustOptimize( } if (LintIR) { - PipelineStartEPCallbacks.push_back( - [](ModulePassManager &MPM, OptimizationLevel Level) { - MPM.addPass(createModuleToFunctionPassAdaptor(LintPass())); - }); + PipelineStartEPCallbacks.push_back([](ModulePassManager &MPM, + OptimizationLevel Level) { +#if LLVM_VERSION_GE(21, 0) + MPM.addPass( + createModuleToFunctionPassAdaptor(LintPass(/*AbortOnError=*/true))); +#else + MPM.addPass(createModuleToFunctionPassAdaptor(LintPass())); +#endif + }); } if (InstrumentCoverage) { diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 186198bc631eb..e1a7ad718a067 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -2,7 +2,7 @@ //@ add-core-stubs //@ revisions:aarch64 loongarch64 powerpc64 sparc64 x86_64 //@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu //@[aarch64] needs-llvm-components: arm diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 404f6237849e6..73bc7ef6b77d6 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ revisions: linux apple //@ min-llvm-version: 19 -//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir -Cllvm-args=-lint-abort-on-error +//@ compile-flags: -Copt-level=0 -Cno-prepopulate-passes -Zlint-llvm-ir //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 From a6a6d01bbc93da72474983d355e7442abbd162e8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 09:47:46 +1100 Subject: [PATCH 214/333] Use `sym::dummy` in one more place. It makes it clearer that the symbol is unused and doesn't matter. --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 63ea8c4ced13c..f7343b93281f5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1091,7 +1091,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { )); } Scope::BuiltinAttrs => { - let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty)); + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy)); if filter_fn(res) { suggestions.extend( BUILTIN_ATTRIBUTES diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index e7a8dee27f568..9959e98e3dd75 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1440,7 +1440,8 @@ pub fn decode_syntax_context SyntaxContext } } Entry::Vacant(entry) => { - // We are the first thread to start decoding. Mark the current thread as being progress. + // We are the first thread to start decoding. Mark the current thread as being + // progress. context.local_in_progress.borrow_mut().insert(raw_id); // Allocate and store SyntaxContext id *before* calling the decoder function, From 9fb0defa520c82ccf79af7961ee926dba77b4e96 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 13:23:13 +1100 Subject: [PATCH 215/333] Tweak `check_doc_keyword`. To use one `kw::Empty` instead of two. It's a little more direct this way, and avoids `kw::Empty` being used for both "no string" and "empty string". --- compiler/rustc_passes/src/check_attr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ada3151c3b8c1..3019c5c0dae80 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1041,11 +1041,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { s <= kw::Union || s == sym::SelfTy } - let doc_keyword = meta.value_str().unwrap_or(kw::Empty); - if doc_keyword == kw::Empty { - self.doc_attr_str_error(meta, "keyword"); - return; - } + let doc_keyword = match meta.value_str() { + Some(value) if value != kw::Empty => value, + _ => return self.doc_attr_str_error(meta, "keyword"), + }; + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, From 929749d8018b3a5afde968cff6da11b8460dd52d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 13:33:38 +1100 Subject: [PATCH 216/333] Improve `is_doc_keyword`. This is part of the implementation of `#[doc(keyword = "match")]` attributes used by `std` to provide documentation for keywords. `is_doc_keyword` currently does a crude keyword range test that's intended to catch all keywords but misses `kw::Yeet`. This commit changes it to use `Symbol` methods, including the new `is_weak` method (required for `union`). `Symbol` methods are much less prone to falling out of date if new keywords are added. --- compiler/rustc_passes/src/check_attr.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3019c5c0dae80..cfc0369c5989b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; -use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; @@ -1038,7 +1038,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we // can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the // `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`. - s <= kw::Union || s == sym::SelfTy + s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy } let doc_keyword = match meta.value_str() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 47dd80c432ead..c6e570e524f59 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -131,7 +131,7 @@ symbols! { // tidy-alphabetical-end // Weak keywords, have special meaning only in specific contexts. - // Matching predicates: none + // Matching predicates: `is_weak` // tidy-alphabetical-start Auto: "auto", Builtin: "builtin", @@ -2725,6 +2725,10 @@ impl Symbol { || self.is_unused_keyword_conditional(edition) } + pub fn is_weak(self) -> bool { + self >= kw::Auto && self <= kw::Yeet + } + /// A keyword or reserved identifier that can be used as a path segment. pub fn is_path_segment_keyword(self) -> bool { self == kw::Super From 27850631638e74bd017d963a35c53e7f81f42e4d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 22:56:13 +1100 Subject: [PATCH 217/333] Avoid `kw::Empty` use for `AuxParamsAttr`. By changing two of the fields to use `Option` instead of `Ident`. As a result, `None` now means "no identifier", which is much clearer than using an empty identifier. --- .../src/significant_drop_tightening.rs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index e9db7c9d031a9..76874cc342066 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -79,10 +79,11 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr { continue; } + let first_bind_ident = apa.first_bind_ident.unwrap(); span_lint_and_then( cx, SIGNIFICANT_DROP_TIGHTENING, - apa.first_bind_ident.span, + first_bind_ident.span, "temporary with significant `Drop` can be early dropped", |diag| { match apa.counter { @@ -91,13 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { 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 apa.last_bind_ident == Ident::empty() { - format!("\n{indent}{init_method}.{usage_method};") - } else { + let stmt = if let Some(last_bind_ident) = apa.last_bind_ident { format!( "\n{indent}let {} = {init_method}.{usage_method};", - snippet(cx, apa.last_bind_ident.span, ".."), + snippet(cx, last_bind_ident.span, ".."), ) + } else { + format!("\n{indent}{init_method}.{usage_method};") }; diag.multipart_suggestion_verbose( @@ -113,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { format!( "\n{}drop({});", " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)), - apa.first_bind_ident + first_bind_ident ), Applicability::MaybeIncorrect, ); @@ -124,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { apa.first_block_span, format!( "temporary `{}` is currently being dropped at the end of its contained scope", - apa.first_bind_ident + first_bind_ident ), ); }, @@ -283,7 +284,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { let mut apa = AuxParamsAttr { first_block_hir_id: self.ap.curr_block_hir_id, first_block_span: self.ap.curr_block_span, - first_bind_ident: ident, + first_bind_ident: Some(ident), first_method_span: { let expr_or_init = expr_or_init(self.cx, expr); if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind { @@ -307,7 +308,7 @@ 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 = ident; + apa.last_bind_ident = Some(ident); } if let Some(local_init) = local.init && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind @@ -373,7 +374,7 @@ struct AuxParamsAttr { first_block_span: Span, /// The binding or variable that references the initial construction of the type marked with /// `#[has_significant_drop]`. - first_bind_ident: Ident, + first_bind_ident: Option, /// Similar to `init_bind_ident` but encompasses the right-hand method call. first_method_span: Span, /// Similar to `init_bind_ident` but encompasses the whole contained statement. @@ -381,7 +382,7 @@ 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: Ident, + last_bind_ident: Option, /// Similar to `last_bind_span` but encompasses the right-hand method call. last_method_span: Span, /// Similar to `last_bind_span` but encompasses the whole contained statement. @@ -395,10 +396,10 @@ impl Default for AuxParamsAttr { has_expensive_expr_after_last_attr: false, first_block_hir_id: HirId::INVALID, first_block_span: DUMMY_SP, - first_bind_ident: Ident::empty(), + first_bind_ident: None, first_method_span: DUMMY_SP, first_stmt_span: DUMMY_SP, - last_bind_ident: Ident::empty(), + last_bind_ident: None, last_method_span: DUMMY_SP, last_stmt_span: DUMMY_SP, } @@ -413,7 +414,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> { } } -fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool { +fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option, lcx: &LateContext<'_>) -> bool { if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind && let Res::Def(DefKind::Fn, did) = fun_path.res @@ -422,6 +423,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_ let has_ident = |local_expr: &hir::Expr<'_>| { if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind && let [first_arg_ps, ..] = arg_path.segments + && let Some(first_bind_ident) = first_bind_ident && &first_arg_ps.ident == first_bind_ident { true From 7feac15ca7f601b7ef0dd63e9113103f720f5405 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 16 Apr 2023 11:50:15 +0000 Subject: [PATCH 218/333] rustdoc-json: Add test for #[automatically_derived] attribute --- tests/rustdoc-json/attrs/automatically_derived.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/rustdoc-json/attrs/automatically_derived.rs diff --git a/tests/rustdoc-json/attrs/automatically_derived.rs b/tests/rustdoc-json/attrs/automatically_derived.rs new file mode 100644 index 0000000000000..4e1ab3d145e5d --- /dev/null +++ b/tests/rustdoc-json/attrs/automatically_derived.rs @@ -0,0 +1,13 @@ +#[derive(Default)] +pub struct Derive; + +pub struct Manual; + +impl Default for Manual { + fn default() -> Self { + Self + } +} + +//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Derive" && @.inner.impl.trait.path == "Default")].attrs' '["#[automatically_derived]"]' +//@ is '$.index[?(@.inner.impl.for.resolved_path.path == "Manual" && @.inner.impl.trait.path == "Default")].attrs' '[]' From e2d5033bce2085fb2baaf5e887d11959928def74 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Mar 2025 20:46:48 +0000 Subject: [PATCH 219/333] Feed HIR for by-move coroutine body def, since the inliner tries to read its attrs --- .../src/coroutine/by_move_body.rs | 2 ++ tests/crashes/134335.rs | 12 -------- .../by-move-body-inlined-attrs.rs | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) delete mode 100644 tests/crashes/134335.rs create mode 100644 tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 89a306c610477..dd0e07f2218eb 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -219,6 +219,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); + // Feed HIR because we try to access this body's attrs in the inliner. + body_def.feed_hir(); // Inherited from the by-ref coroutine. body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id)); diff --git a/tests/crashes/134335.rs b/tests/crashes/134335.rs deleted file mode 100644 index bee6686ff3fa8..0000000000000 --- a/tests/crashes/134335.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #134335 -//@compile-flags: -Zunstable-options --edition=2024 --crate-type=lib -pub async fn async_closure(x: &mut i32) { - let c = async move || { - *x += 1; - }; - call_once(c).await; -} - -fn call_once(f: impl FnOnce() -> T) -> T { - f() -} diff --git a/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs new file mode 100644 index 0000000000000..ecfc06d2bad0c --- /dev/null +++ b/tests/ui/async-await/async-closures/by-move-body-inlined-attrs.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ compile-flags: -Zinline-mir -Zvalidate-mir +//@ edition: 2024 + +// See comment below. + +use std::future::Future; +use std::pin::pin; +use std::task::{Context, Waker}; + +fn call_once(f: impl FnOnce() -> T) -> T { f() } + +fn main() { + let x = async || {}; + // We first inline `call_once<{async closure}>`. + // + // This gives us a future whose type is the "FnOnce" flavor of the async closure's + // child coroutine. The body of this coroutine is synthetic, which we synthesize in + // the by-move body query. + let fut = pin!(call_once(x)); + // We then try to inline that body in this poll call. + // + // The inliner does some inlinability checks; one of these checks involves checking + // the body for the `#[rustc_no_mir_inline]` attribute. Since the synthetic body had + // no HIR synthesized, but it's still a local def id, we end up ICEing in the + // `local_def_id_to_hir_id` call when trying to read its attrs. + fut.poll(&mut Context::from_waker(Waker::noop())); +} From 654b7b541300c2d3d497031728b637ab4e457916 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 27 Mar 2025 16:12:00 +0100 Subject: [PATCH 220/333] increment depth of nested obligations --- .../src/traits/effects.rs | 8 --- .../src/traits/fulfill.rs | 56 ++++++++++++------- .../src/traits/select/confirmation.rs | 12 +--- tests/ui/infinite/infinite-autoderef.stderr | 4 +- tests/ui/occurs-check-2.rs | 2 +- tests/ui/occurs-check-2.stderr | 6 +- tests/ui/occurs-check-3.stderr | 4 +- tests/ui/occurs-check.stderr | 4 +- .../mutual-recursion-issue-75860.stderr | 2 +- ...ype-alias-impl-trait-with-cycle-error-1.rs | 3 +- ...alias-impl-trait-with-cycle-error-1.stderr | 11 ++-- ...ype-alias-impl-trait-with-cycle-error-2.rs | 4 +- ...alias-impl-trait-with-cycle-error-2.stderr | 11 ++-- ...ype-alias-impl-trait-with-cycle-error-3.rs | 4 +- ...alias-impl-trait-with-cycle-error-3.stderr | 11 ++-- 15 files changed, 70 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 3c127416cbf7c..b8e15088853c3 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -106,10 +106,6 @@ fn match_candidate<'tcx>( more_nested(selcx, &mut nested); - for nested in &mut nested { - nested.set_depth_from_parent(obligation.recursion_depth); - } - Ok(nested) } @@ -378,10 +374,6 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>( }), ); - for nested in &mut nested { - nested.set_depth_from_parent(obligation.recursion_depth); - } - Ok(nested) } _ => Err(EvaluationFailure::NoSolution), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e39f8e673dbac..e98a240a53f52 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -225,9 +225,15 @@ struct FulfillProcessor<'a, 'tcx> { selcx: SelectionContext<'a, 'tcx>, } -fn mk_pending<'tcx>(os: PredicateObligations<'tcx>) -> PendingPredicateObligations<'tcx> { +fn mk_pending<'tcx>( + parent: &PredicateObligation<'tcx>, + os: PredicateObligations<'tcx>, +) -> PendingPredicateObligations<'tcx> { os.into_iter() - .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) + .map(|mut o| { + o.set_depth_from_parent(parent.recursion_depth); + PendingPredicateObligation { obligation: o, stalled_on: vec![] } + }) .collect() } @@ -341,7 +347,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ); if predicate != obligation.predicate { obligations.push(obligation.with(infcx.tcx, predicate)); - return ProcessResult::Changed(mk_pending(obligations)); + return ProcessResult::Changed(mk_pending(obligation, obligations)); } } let binder = obligation.predicate.kind(); @@ -385,7 +391,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let mut obligations = PredicateObligations::with_capacity(1); obligations.push(obligation.with(infcx.tcx, pred)); - ProcessResult::Changed(mk_pending(obligations)) + ProcessResult::Changed(mk_pending(obligation, obligations)) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, ty::PredicateKind::NormalizesTo(..) => { @@ -410,6 +416,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let host_obligation = obligation.with(infcx.tcx, data); self.process_host_obligation( + obligation, host_obligation, &mut pending_obligation.stalled_on, ) @@ -486,7 +493,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // `>::Output` when this is an `Expr` representing // `lhs + rhs`. ty::ConstKind::Expr(_) => { - return ProcessResult::Changed(mk_pending(PredicateObligations::new())); + return ProcessResult::Changed(mk_pending( + obligation, + PredicateObligations::new(), + )); } ty::ConstKind::Placeholder(_) => { bug!("placeholder const {:?} in old solver", ct) @@ -503,7 +513,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ct_ty, ty, ) { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Ok(inf_ok) => ProcessResult::Changed(mk_pending( + obligation, + inf_ok.into_obligations(), + )), Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty }, )), @@ -537,7 +550,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()]; ProcessResult::Unchanged } - Some(os) => ProcessResult::Changed(mk_pending(os)), + Some(os) => ProcessResult::Changed(mk_pending(obligation, os)), } } @@ -553,11 +566,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; ProcessResult::Unchanged } - Ok(Ok(mut ok)) => { - for subobligation in &mut ok.obligations { - subobligation.set_depth_from_parent(obligation.recursion_depth); - } - ProcessResult::Changed(mk_pending(ok.obligations)) + Ok(Ok(ok)) => { + ProcessResult::Changed(mk_pending(obligation, ok.obligations)) } Ok(Err(err)) => { let expected_found = if subtype.a_is_expected { @@ -582,7 +592,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]; ProcessResult::Unchanged } - Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), + Ok(Ok(ok)) => { + ProcessResult::Changed(mk_pending(obligation, ok.obligations)) + } Ok(Err(err)) => { let expected_found = ExpectedFound::new(coerce.b, coerce.a); ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err)) @@ -645,6 +657,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ) { return ProcessResult::Changed(mk_pending( + obligation, new_obligations.into_obligations(), )); } @@ -659,6 +672,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { .eq(DefineOpaqueTypes::Yes, c1, c2) { return ProcessResult::Changed(mk_pending( + obligation, new_obligations.into_obligations(), )); } @@ -704,9 +718,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { c1, c2, ) { - Ok(inf_ok) => { - ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) - } + Ok(inf_ok) => ProcessResult::Changed(mk_pending( + obligation, + inf_ok.into_obligations(), + )), Err(err) => { ProcessResult::Error(FulfillmentErrorCode::ConstEquate( ExpectedFound::new(c1, c2), @@ -790,7 +805,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { match self.selcx.poly_select(&trait_obligation) { Ok(Some(impl_source)) => { debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth); - ProcessResult::Changed(mk_pending(impl_source.nested_obligations())) + ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations())) } Ok(None) => { debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth); @@ -854,7 +869,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) { - ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)), + ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)), ProjectAndUnifyResult::FailedNormalization => { stalled_on.clear(); stalled_on.extend(args_infer_vars( @@ -868,7 +883,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { let mut obligations = PredicateObligations::with_capacity(1); obligations.push(project_obligation.with(tcx, project_obligation.predicate)); - ProcessResult::Changed(mk_pending(obligations)) + ProcessResult::Changed(mk_pending(obligation, obligations)) } ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProcessResult::Error(FulfillmentErrorCode::Project(e)) @@ -878,11 +893,12 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { fn process_host_obligation( &mut self, + obligation: &PredicateObligation<'tcx>, host_obligation: HostEffectObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) { - Ok(nested) => ProcessResult::Changed(mk_pending(nested)), + Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)), Err(effects::EvaluationFailure::Ambiguous) => { stalled_on.clear(); stalled_on.extend(args_infer_vars( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 630241725fdb2..2cb7d2d893135 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -39,7 +39,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { - let mut impl_src = match candidate { + Ok(match candidate { SizedCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); ImplSource::Builtin(BuiltinImplSource::Misc, data) @@ -139,15 +139,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BikeshedGuaranteedNoDropCandidate => { self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation) } - }; - - // The obligations returned by confirmation are recursively evaluated - // so we need to make sure they have the correct depth. - for subobligation in impl_src.borrow_nested_obligations_mut() { - subobligation.set_depth_from_parent(obligation.recursion_depth); - } - - Ok(impl_src) + }) } fn confirm_projection_candidate( diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 7d09af9a7d4af..7770cc8a72047 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/infinite-autoderef.rs:16:13 + --> $DIR/infinite-autoderef.rs:16:22 | LL | x = Box::new(x); - | ^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs index 1ec460a873527..9289a8e870a18 100644 --- a/tests/ui/occurs-check-2.rs +++ b/tests/ui/occurs-check-2.rs @@ -4,6 +4,6 @@ fn main() { let g; g = f; - f = Box::new(g); //~^ ERROR overflow assigning `Box<_>` to `_` + f = Box::new(g); } diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr index 54307a6c5474f..5f296967f30d8 100644 --- a/tests/ui/occurs-check-2.stderr +++ b/tests/ui/occurs-check-2.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check-2.rs:7:9 + --> $DIR/occurs-check-2.rs:6:9 | -LL | f = Box::new(g); - | ^^^^^^^^^^^ +LL | g = f; + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr index 77b67ec1a62c6..eb05c94957c98 100644 --- a/tests/ui/occurs-check-3.stderr +++ b/tests/ui/occurs-check-3.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Clam<_>` to `_` - --> $DIR/occurs-check-3.rs:6:9 + --> $DIR/occurs-check-3.rs:6:17 | LL | c = Clam::A(c); - | ^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr index 30468d68cbd05..ea7c541abc135 100644 --- a/tests/ui/occurs-check.stderr +++ b/tests/ui/occurs-check.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check.rs:3:9 + --> $DIR/occurs-check.rs:3:18 | LL | f = Box::new(f); - | ^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr index 272c56301bc84..9e8eb1adb1111 100644 --- a/tests/ui/traits/mutual-recursion-issue-75860.stderr +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow assigning `_` to `Option<_>` --> $DIR/mutual-recursion-issue-75860.rs:9:33 | LL | let left = |o_a: Option<_>| o_a.unwrap(); - | ^^^ + | ^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs index 19986247d40df..53b7667aa9f1d 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.rs @@ -1,9 +1,10 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 type Foo = impl Fn() -> Foo; +#[define_opaque(Foo)] fn crash(x: Foo) -> Foo { + //~^ ERROR overflow evaluating the requirement `>::Output == Foo` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr index ad96a0eeb87de..ee8922b673e2f 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12 +error[E0275]: overflow evaluating the requirement `>::Output == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21 | -LL | type Foo = impl Fn() -> Foo; - | ^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs index 761cc83af5106..d0c62d290698e 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 pub trait Bar { type Item; } type Foo = impl Bar; - +#[define_opaque(Foo)] fn crash(x: Foo) -> Foo { + //~^ ERROR overflow evaluating the requirement `>::Item == Foo` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr index e5bb8163a8113..40bd6517c06d8 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12 +error[E0275]: overflow evaluating the requirement `>::Item == Foo` + --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:9:21 | -LL | type Foo = impl Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash(x: Foo) -> Foo { + | ^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs index 52942afd63922..de3d23b83a293 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.rs @@ -1,9 +1,9 @@ #![feature(type_alias_impl_trait)] -//@ known-bug: #109268 type Foo<'a> = impl Fn() -> Foo<'a>; - +#[define_opaque(Foo)] fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + //~^ ERROR overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` x } diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr index 157310bf62366..f9e26fde1bda8 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr @@ -1,10 +1,9 @@ -error: unconstrained opaque type - --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16 +error[E0275]: overflow evaluating the requirement ` as FnOnce<()>>::Output == Foo<'a>` + --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:5:40 | -LL | type Foo<'a> = impl Fn() -> Foo<'a>; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same crate +LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> { + | ^^^^^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0275`. From 2feb91181882e525e698c4543063f4d0296fcf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 28 Mar 2025 15:52:15 +0100 Subject: [PATCH 221/333] io: Avoid marking buffer as uninit when copying to `BufWriter` --- library/std/src/io/copy.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 8d733325b3be7..15e962924ac71 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -248,8 +248,11 @@ impl BufferedWriterSpec for BufWriter { Err(e) => return Err(e), } } else { + // All the bytes that were already in the buffer are initialized, + // treat them as such when the buffer is flushed. + init += buf.len(); + self.flush_buf()?; - init = 0; } } } From 878786848fdbe29325e9172d0ab86ed964eca7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Fri, 28 Mar 2025 15:52:56 +0100 Subject: [PATCH 222/333] io: Avoid Avoid marking bytes as uninit in `BufReader::peek` --- library/std/src/io/buffered/bufreader/buffer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 9fd2472ebdfdb..574288e579e0b 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -123,7 +123,6 @@ impl Buffer { /// Remove bytes that have already been read from the buffer. pub fn backshift(&mut self) { self.buf.copy_within(self.pos.., 0); - self.initialized -= self.pos; self.filled -= self.pos; self.pos = 0; } From e80a3e22328641b43a5ea66bfafdfe5950686779 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 29 Mar 2025 18:34:44 +1100 Subject: [PATCH 223/333] coverage: Tweak tests/coverage/assert-ne.rs This test is intended to demonstrate that a particular macro-argument span doesn't get lost during span-refinement, but it turns out that span-extraction currently doesn't yield any MIR spans for this position. This patch therefore tweaks the test to add a function call in that position, so that it still remains relevant to span refinement. --- tests/coverage/assert-ne.coverage | 2 +- tests/coverage/assert-ne.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/coverage/assert-ne.coverage b/tests/coverage/assert-ne.coverage index 236a8fd138588..fc43d4a8e06a0 100644 --- a/tests/coverage/assert-ne.coverage +++ b/tests/coverage/assert-ne.coverage @@ -7,7 +7,7 @@ LL| | LL| 1|fn main() { LL| 1| assert_ne!( - LL| 1| Foo(5), // Make sure this expression's span isn't lost. + LL| 1| black_box(Foo(5)), // Make sure this expression's span isn't lost. LL| 1| if black_box(false) { LL| 0| Foo(0) // LL| | } else { diff --git a/tests/coverage/assert-ne.rs b/tests/coverage/assert-ne.rs index 8a8fe0898048d..9d9fcb71ba7f9 100644 --- a/tests/coverage/assert-ne.rs +++ b/tests/coverage/assert-ne.rs @@ -7,7 +7,7 @@ struct Foo(u32); fn main() { assert_ne!( - Foo(5), // Make sure this expression's span isn't lost. + black_box(Foo(5)), // Make sure this expression's span isn't lost. if black_box(false) { Foo(0) // } else { From 577272eedeaace00aa695135b3b8fee3768536a5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 29 Mar 2025 21:33:01 +1100 Subject: [PATCH 224/333] coverage: Shrink call spans to just the function name This is a way to shrink call spans that doesn't involve mixing different spans, and avoids overlap with argument spans. This patch also removes some low-value comments that were causing rustfmt to ignore the match arms. --- .../src/coverage/spans/from_mir.rs | 18 ++++----- tests/coverage/assert-ne.cov-map | 4 +- tests/coverage/attr/off-on-sandwich.cov-map | 12 +++--- tests/coverage/branch/if.cov-map | 4 +- tests/coverage/branch/lazy-boolean.cov-map | 8 ++-- tests/coverage/branch/let-else.cov-map | 4 +- tests/coverage/branch/match-arms.cov-map | 28 ++++++------- tests/coverage/condition/conditions.cov-map | 10 +++-- tests/coverage/coroutine.cov-map | 4 +- tests/coverage/holes.cov-map | 18 ++++----- tests/coverage/inline-dead.cov-map | 4 +- tests/coverage/loop-break.cov-map | 4 +- tests/coverage/mcdc/non_control_flow.cov-map | 10 +++-- tests/coverage/no_cov_crate.cov-map | 8 ++-- tests/coverage/sort_groups.cov-map | 4 +- tests/coverage/try_error_result.cov-map | 40 +++++++++---------- tests/coverage/try_error_result.coverage | 2 +- tests/coverage/unicode.cov-map | 6 +-- tests/coverage/unicode.coverage | 2 +- tests/coverage/unreachable.cov-map | 12 +++--- ...ch_match_arms.main.InstrumentCoverage.diff | 8 ++-- ...ment_coverage.main.InstrumentCoverage.diff | 2 +- 22 files changed, 106 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 1faa2171c0b02..804cd8ab3f7d3 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -120,22 +120,20 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { // an `if condition { block }` has a span that includes the executed block, if true, // but for coverage, the code region executed, up to *and* through the SwitchInt, // actually stops before the if's block.) - TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG + TerminatorKind::Unreachable | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::SwitchInt { .. } - // For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`. | TerminatorKind::FalseEdge { .. } | TerminatorKind::Goto { .. } => None, // Call `func` operand can have a more specific span when part of a chain of calls - TerminatorKind::Call { ref func, .. } - | TerminatorKind::TailCall { ref func, .. } => { + TerminatorKind::Call { ref func, .. } | TerminatorKind::TailCall { ref func, .. } => { let mut span = terminator.source_info.span; - if let mir::Operand::Constant(box constant) = func { - if constant.span.lo() > span.lo() { - span = span.with_lo(constant.span.lo()); - } + if let mir::Operand::Constant(constant) = func + && span.contains(constant.span) + { + span = constant.span; } Some(span) } @@ -147,9 +145,7 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { | TerminatorKind::Yield { .. } | TerminatorKind::CoroutineDrop | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::InlineAsm { .. } => { - Some(terminator.source_info.span) - } + | TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span), } } diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map index b432e63c168ce..27d4b0382dec7 100644 --- a/tests/coverage/assert-ne.cov-map +++ b/tests/coverage/assert-ne.cov-map @@ -1,12 +1,12 @@ Function name: assert_ne::main -Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 1c, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 01, 09, 04, 01, 08, 01, 03, 15, 05, 04, 0d, 00, 13, 02, 02, 0d, 00, 13, 06, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 21) - Code(Counter(1)) at (prev + 4, 13) to (start + 0, 19) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index ef6f5a9dc4285..c55c5897d8bab 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -1,30 +1,30 @@ Function name: off_on_sandwich::dense_a::dense_b -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 12, 01, 07, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 05, 02, 10, 01, 07, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 18) +- Code(Counter(0)) at (prev + 16, 5) to (start + 2, 16) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c -Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 17, 01, 0b, 09, 00, 0a] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 22, 09, 02, 15, 01, 0b, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 23) +- Code(Counter(0)) at (prev + 34, 9) to (start + 2, 21) - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d -Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 1b, 01, 07, 0d, 00, 0e] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 25, 0d, 02, 19, 01, 07, 0d, 00, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 27) +- Code(Counter(0)) at (prev + 37, 13) to (start + 2, 25) - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index a6b865318c662..392ace1683a75 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -23,7 +23,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 11, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -40,7 +40,7 @@ Number of file 0 mappings: 18 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) -- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 17) +- Code(Counter(1)) at (prev + 1, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 8) to (start + 0, 10) diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index 622f30e2b56f6..ff285a038fb87 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -34,7 +34,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::chain -Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] +Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -69,7 +69,7 @@ Number of file 0 mappings: 19 true = c3 false = (c2 - c3) - Code(Counter(3)) at (prev + 0, 40) to (start + 0, 45) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(4), false: Expression(4, Sub) } at (prev + 0, 13) to (start + 0, 18) @@ -91,7 +91,7 @@ Number of file 0 mappings: 19 Highest counter ID seen: c6 Function name: lazy_boolean::nested_mixed -Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 11, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] +Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -127,7 +127,7 @@ Number of file 0 mappings: 19 false = ((c1 + c2) - c3) - Code(Expression(6, Sub)) at (prev + 0, 44) to (start + 0, 51) = ((c1 + c2) - c3) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 16) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(4), false: Expression(8, Sub) } at (prev + 0, 14) to (start + 0, 19) diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 215d71599e4c0..811b9838e3f51 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,5 +1,5 @@ Function name: let_else::let_else -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -13,7 +13,7 @@ Number of file 0 mappings: 7 = (c0 - c1) - Code(Counter(0)) at (prev + 0, 19) to (start + 0, 24) - Code(Counter(1)) at (prev + 1, 9) to (start + 1, 15) -- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11) +- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index d5b4d04d40192..caa18820cf8e7 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -1,5 +1,5 @@ Function name: match_arms::guards -Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 29, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 29, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 29, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 29, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 18, 01, 03, 05, 01, 02] +Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -14,29 +14,29 @@ Number of expressions: 8 Number of file 0 mappings: 12 - Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16) - Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c1 false = (c5 - c1) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(2), false: Expression(1, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c2 false = (c6 - c2) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(3), false: Expression(2, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c3 false = (c7 - c3) -- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 41) +- Code(Counter(4)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(4), false: Expression(3, Sub) } at (prev + 0, 23) to (start + 0, 27) true = c4 false = (c8 - c4) -- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 24) +- Code(Expression(4, Sub)) at (prev + 1, 14) to (start + 0, 21) = (c0 - (((c1 + c2) + c3) + c4)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c8 Function name: match_arms::match_arms -Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 21, 09, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 02, 01, 11, 00, 21, 01, 03, 05, 01, 02] +Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -46,16 +46,16 @@ Number of expressions: 3 Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) -- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 33) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33) -- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 33) +- Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 32) +- Code(Expression(0, Sub)) at (prev + 1, 17) to (start + 0, 32) = (c0 - ((c1 + c2) + c3)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c3 Function name: match_arms::or_patterns -Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2e, 01, 03, 05, 01, 02] +Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -68,12 +68,12 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) -- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 46) +- Code(Expression(0, Add)) at (prev + 0, 36) to (start + 0, 45) = (c1 + c2) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) - Code(Expression(1, Sub)) at (prev + 0, 30) to (start + 0, 31) = (c0 - ((c1 + c2) + c3)) -- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 46) +- Code(Expression(3, Sub)) at (prev + 0, 36) to (start + 0, 45) = (c0 - (c1 + c2)) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index 417637f2d2e37..c34075a0bcfca 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -109,15 +109,17 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: conditions::func_call -Raw bytes (37): 0x[01, 01, 02, 01, 05, 05, 09, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (47): 0x[01, 01, 02, 01, 05, 05, 09, 07, 01, 25, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 20, 05, 02, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 06, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 10) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index c6f2d415056d9..297dde3b2b0f9 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -13,7 +13,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: coroutine::main -Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -21,7 +21,7 @@ Number of expressions: 2 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) -- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 46) +- Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45) - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45) - Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53) = (c0 - c1) diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 3deacbc8e1287..8ff291d2d7d3d 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -8,20 +8,20 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: holes::main -Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18) -- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 17) +- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17) -- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) -- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 7, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 6, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13) diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 49cdc514fedbb..65cefe76c29aa 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -8,14 +8,14 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: inline_dead::live:: -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0d, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 13) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index f13e82da15143..fccc4d64395b6 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -1,12 +1,12 @@ Function name: loop_break::main -Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 27, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 05, 01, 05, 01, 03, 01, 00, 0b, 05, 02, 0c, 00, 21, 01, 01, 0d, 00, 12, 02, 01, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 11) -- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 39) +- Code(Counter(1)) at (prev + 2, 12) to (start + 0, 33) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index c282d53c5ac25..959d21901de8e 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -113,15 +113,17 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: non_control_flow::func_call -Raw bytes (50): 0x[01, 01, 02, 01, 05, 05, 09, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 02, 01, 05, 05, 09, 08, 01, 29, 01, 00, 20, 01, 01, 05, 00, 08, 01, 00, 09, 00, 0a, 28, 03, 02, 00, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 06, 02, 00, 00, 00, 0e, 00, 0f, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) -Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) -- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +Number of file 0 mappings: 8 +- Code(Counter(0)) at (prev + 41, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 8) +- Code(Counter(0)) at (prev + 0, 9) to (start + 0, 10) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 9) to (start + 0, 15) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index 04171fdb79b6b..244b0099544b5 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -35,22 +35,22 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer -Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 23, 01, 0c, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 33, 05, 02, 22, 01, 0c, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 35) +- Code(Counter(0)) at (prev + 51, 5) to (start + 2, 34) - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered -Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 17, 01, 0b, 05, 00, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 41, 05, 02, 16, 01, 0b, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 23) +- Code(Counter(0)) at (prev + 65, 5) to (start + 2, 22) - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) Highest counter ID seen: c0 diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 69e1342229609..898d68171c500 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -55,13 +55,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: sort_groups::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 1c, 05, 04, 24, 02, 06, 02, 02, 05, 00, 06, 01, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 28) - Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c1) diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 35b2c36a57519..a4a8e21d8c315 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -41,13 +41,13 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: try_error_result::main -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0a, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 12) +- Code(Counter(0)) at (prev + 113, 1) to (start + 2, 10) - Code(Counter(1)) at (prev + 3, 5) to (start + 0, 6) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) @@ -55,7 +55,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: try_error_result::test1 -Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 29, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] +Raw bytes (67): 0x[01, 01, 04, 07, 05, 01, 09, 05, 01, 05, 09, 0b, 01, 0d, 01, 02, 17, 05, 07, 09, 00, 0e, 09, 02, 09, 04, 1a, 02, 06, 0d, 00, 11, 02, 00, 29, 00, 2a, 00, 01, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0a, 04, 0d, 00, 11, 00, 00, 2a, 00, 2b, 0e, 03, 05, 00, 0b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -67,13 +67,13 @@ Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 13, 1) to (start + 2, 23) - Code(Counter(1)) at (prev + 7, 9) to (start + 0, 14) - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 41) +- Code(Expression(0, Sub)) at (prev + 6, 13) to (start + 0, 17) = ((c0 + c2) - c1) - Code(Expression(0, Sub)) at (prev + 0, 41) to (start + 0, 42) = ((c0 + c2) - c1) -- Code(Zero) at (prev + 1, 13) to (start + 0, 42) +- Code(Zero) at (prev + 1, 13) to (start + 0, 17) - Code(Zero) at (prev + 0, 42) to (start + 0, 43) -- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 42) +- Code(Expression(2, Sub)) at (prev + 4, 13) to (start + 0, 17) = (c1 - c0) - Code(Zero) at (prev + 0, 42) to (start + 0, 43) - Code(Expression(3, Sub)) at (prev + 3, 5) to (start + 0, 11) @@ -82,7 +82,7 @@ Number of file 0 mappings: 11 Highest counter ID seen: c2 Function name: try_error_result::test2 -Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 35, 15, 04, 11, 00, 12, 1e, 02, 11, 04, 12, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 41, 19, 00, 41, 00, 42, 26, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 41, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 60, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 42, 29, 00, 42, 00, 43, 66, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 36, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] +Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 54 @@ -144,56 +144,56 @@ Number of file 0 mappings: 40 - Code(Counter(0)) at (prev + 61, 1) to (start + 3, 23) - Code(Counter(1)) at (prev + 8, 9) to (start + 0, 14) - Code(Counter(2)) at (prev + 2, 9) to (start + 4, 26) -- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 47) +- Code(Counter(3)) at (prev + 6, 13) to (start + 0, 31) - Code(Counter(4)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 53) +- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 3, 28) = (c3 - c4) - Code(Counter(5)) at (prev + 4, 17) to (start + 0, 18) -- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 4, 18) +- Code(Expression(7, Sub)) at (prev + 2, 17) to (start + 3, 39) = (c3 - (c4 + c5)) - Code(Expression(12, Sub)) at (prev + 5, 17) to (start + 0, 20) = (c3 - (((c4 + c5) + c6) + c7)) -- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 65) +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 41) = (c3 - (c4 + c5)) - Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 95) +- Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c3 - ((c4 + c5) + c6)) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) - Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c3 - (((c4 + c5) + c6) + c7)) - Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c16 - (c8 + c9)) -- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 65) +- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 41) - Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66) -- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 96) +- Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c16 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) - Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c16 - (c8 + c9)) - Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20) = (c2 - ((c3 + c10) + c11)) -- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 66) +- Code(Expression(24, Sub)) at (prev + 0, 23) to (start + 0, 41) = (c2 - c3) - Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67) -- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 97) +- Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72) = (c2 - (c3 + c10)) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) - Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c2 - ((c3 + c10) + c11)) - Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c17 - (c12 + c13)) -- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(17)) at (prev + 0, 23) to (start + 1, 29) - Code(Counter(12)) at (prev + 1, 54) to (start + 0, 55) -- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) - Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32) = (c17 - (c12 + c13)) - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c18 - (c14 + c15)) -- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 54) +- Code(Counter(18)) at (prev + 0, 23) to (start + 1, 29) - Code(Counter(14)) at (prev + 2, 17) to (start + 0, 18) -- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 47) +- Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c18 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) - Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32) diff --git a/tests/coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 7100248f7df85..7a89c0452ac4f 100644 --- a/tests/coverage/try_error_result.coverage +++ b/tests/coverage/try_error_result.coverage @@ -86,7 +86,7 @@ LL| 1| . LL| 1| expect_err( LL| 1| "call should fail" - LL| 1| ); + LL| | ); LL| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; ^0 ^0 ^0 LL| 0| assert_eq!(val, 57); diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index 7b9dc0b9bc887..29d40a055130e 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -1,5 +1,5 @@ Function name: unicode::main -Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 25, 09, 00, 29, 00, 46, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02] +Raw bytes (53): 0x[01, 01, 02, 05, 01, 01, 0d, 09, 01, 0e, 01, 00, 0b, 02, 01, 09, 00, 0c, 05, 00, 10, 00, 1b, 02, 00, 1c, 00, 28, 01, 02, 08, 00, 23, 09, 00, 29, 00, 44, 0d, 00, 47, 02, 06, 06, 02, 05, 00, 06, 01, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -12,8 +12,8 @@ Number of file 0 mappings: 9 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 27) - Code(Expression(0, Sub)) at (prev + 0, 28) to (start + 0, 40) = (c1 - c0) -- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 37) -- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 70) +- Code(Counter(0)) at (prev + 2, 8) to (start + 0, 35) +- Code(Counter(2)) at (prev + 0, 41) to (start + 0, 68) - Code(Counter(3)) at (prev + 0, 71) to (start + 2, 6) - Code(Expression(1, Sub)) at (prev + 2, 5) to (start + 0, 6) = (c0 - c3) diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage index 84c5f05a8c4e2..443499545500e 100644 --- a/tests/coverage/unicode.coverage +++ b/tests/coverage/unicode.coverage @@ -15,7 +15,7 @@ LL| 33| for _İ in 'А'..='Я' { /* Я */ } ^32 ^32 LL| | - LL| 1| if 申し訳ございません() && 申し訳ございません() { + LL| 1| if 申し訳ございません() && 申し訳ございません() { ^0 LL| 0| println!("true"); LL| 1| } diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 97961bc741452..0bc18bfcbd315 100644 --- a/tests/coverage/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -1,27 +1,27 @@ Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 47] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 27, 00, 45] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 14, 39) to (start + 0, 71) +- Code(Zero) at (prev + 14, 39) to (start + 0, 69) Highest counter ID seen: (none) Function name: unreachable::unreachable_function (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 25] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 10, 01, 01, 23] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 16, 1) to (start + 1, 37) +- Code(Zero) at (prev + 16, 1) to (start + 1, 35) Highest counter ID seen: (none) Function name: unreachable::unreachable_intrinsic (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2c] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 01, 2a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 21, 1) to (start + 1, 44) +- Code(Zero) at (prev + 21, 1) to (start + 1, 42) Highest counter ID seen: (none) diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 8e1cdb7182b10..542b70bcee966 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -27,10 +27,10 @@ } + coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); -+ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); -+ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); -+ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:32 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:32 (#0); ++ coverage Code { bcb: bcb4 } => $DIR/branch_match_arms.rs:18:17: 18:32 (#0); ++ coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:32 (#0); + coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); + bb0: { diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index 1a71cb8dea7f1..30de92f3b8683 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -8,7 +8,7 @@ let mut _3: !; + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:17 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0); + coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0); From 62a533ce7801ac35344f3ebaa983e90dbeba447a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 25 Mar 2025 20:34:32 +1100 Subject: [PATCH 225/333] coverage: Instead of splitting, just discard any span that overlaps a hole --- .../rustc_mir_transform/src/coverage/spans.rs | 62 +++++-------------- compiler/rustc_mir_transform/src/lib.rs | 1 + tests/coverage/async_block.cov-map | 8 +-- tests/coverage/async_block.coverage | 2 +- tests/coverage/async_closure.cov-map | 14 +++-- tests/coverage/async_closure.coverage | 4 +- tests/coverage/closure.cov-map | 12 ++-- tests/coverage/closure.coverage | 22 +++---- tests/coverage/holes.cov-map | 6 +- tests/coverage/holes.coverage | 20 +++--- 10 files changed, 63 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 8befe9c5d8dd8..b1f613432a8b6 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::iter; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; @@ -83,9 +84,7 @@ pub(super) fn extract_refined_covspans( // Split the covspans into separate buckets that don't overlap any holes. let buckets = divide_spans_into_buckets(covspans, &holes); - for mut covspans in buckets { - // Make sure each individual bucket is internally sorted. - covspans.sort_by(compare_covspans); + for covspans in buckets { let _span = debug_span!("processing bucket", ?covspans).entered(); let mut covspans = remove_unwanted_overlapping_spans(covspans); @@ -161,50 +160,37 @@ fn split_visible_macro_spans(covspans: &mut Vec) { } /// Uses the holes to divide the given covspans into buckets, such that: -/// - No span in any hole overlaps a bucket (truncating the spans if necessary). +/// - No span in any hole overlaps a bucket (discarding spans if necessary). /// - The spans in each bucket are strictly after all spans in previous buckets, /// and strictly before all spans in subsequent buckets. /// -/// The resulting buckets are sorted relative to each other, but might not be -/// internally sorted. +/// The lists of covspans and holes must be sorted. +/// The resulting buckets are sorted relative to each other, and each bucket's +/// contents are sorted. #[instrument(level = "debug")] fn divide_spans_into_buckets(input_covspans: Vec, holes: &[Hole]) -> Vec> { debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())); - // Now we're ready to start carving holes out of the initial coverage spans, - // and grouping them in buckets separated by the holes. + // Now we're ready to start grouping spans into buckets separated by holes. let mut input_covspans = VecDeque::from(input_covspans); - let mut fragments = vec![]; // For each hole: // - Identify the spans that are entirely or partly before the hole. - // - Put those spans in a corresponding bucket, truncated to the start of the hole. - // - If one of those spans also extends after the hole, put the rest of it - // in a "fragments" vector that is processed by the next hole. + // - Discard any that overlap with the hole. + // - Add the remaining identified spans to the corresponding bucket. let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); for (hole, bucket) in holes.iter().zip(&mut buckets) { - let fragments_from_prev = std::mem::take(&mut fragments); - - // Only inspect spans that precede or overlap this hole, - // leaving the rest to be inspected by later holes. - // (This relies on the spans and holes both being sorted.) - let relevant_input_covspans = - drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()); - - for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) { - let (before, after) = covspan.split_around_hole_span(hole.span); - bucket.extend(before); - fragments.extend(after); - } + bucket.extend( + drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi()) + .filter(|c| !c.span.overlaps(hole.span)), + ); } - // After finding the spans before each hole, any remaining fragments/spans - // form their own final bucket, after the final hole. + // Any remaining spans form their own final bucket, after the final hole. // (If there were no holes, this will just be all of the initial spans.) - fragments.extend(input_covspans); - buckets.push(fragments); + buckets.push(Vec::from(input_covspans)); buckets } @@ -215,7 +201,7 @@ fn drain_front_while<'a, T>( queue: &'a mut VecDeque, mut pred_fn: impl FnMut(&T) -> bool, ) -> impl Iterator { - std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) + iter::from_fn(move || queue.pop_front_if(|x| pred_fn(x))) } /// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines" @@ -258,22 +244,6 @@ struct Covspan { } impl Covspan { - /// Splits this covspan into 0-2 parts: - /// - The part that is strictly before the hole span, if any. - /// - The part that is strictly after the hole span, if any. - fn split_around_hole_span(&self, hole_span: Span) -> (Option, Option) { - let before = try { - let span = self.span.trim_end(hole_span)?; - Self { span, ..*self } - }; - let after = try { - let span = self.span.trim_start(hole_span)?; - Self { span, ..*self } - }; - - (before, after) - } - /// If `self` and `other` can be merged (i.e. they have the same BCB), /// mutates `self.span` to also include `other.span` and returns true. /// diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 205d388f4fb50..c372b77ad2575 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -12,6 +12,7 @@ #![feature(map_try_insert)] #![feature(never_type)] #![feature(try_blocks)] +#![feature(vec_deque_pop_if)] #![feature(yeet_expr)] // tidy-alphabetical-end diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index 5eb69e668ca5d..d9196f446f137 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,5 +1,5 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 00, 14, 01, 16, 02, 07, 0a, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 05, 01, 06, 01, 07, 01, 00, 0b, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 13, 02, 01, 0d, 00, 13, 02, 07, 09, 00, 22, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 @@ -9,11 +9,11 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 10) = (c1 - c0) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 19) -- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 1, 22) +- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19) = (c1 - c0) -- Code(Expression(0, Sub)) at (prev + 7, 10) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 7, 9) to (start + 0, 34) = (c1 - c0) -- Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: async_block::main::{closure#0} diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 9e3294492cd03..4e00024aebd2e 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -15,6 +15,6 @@ LL| 12| } LL| 16| }; LL| 16| executor::block_on(future); - LL| 16| } + LL| | } LL| 1|} diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 0e1d987783075..a4ef0ceeb6df6 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -30,21 +30,23 @@ Number of file 0 mappings: 2 Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35) +- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36) Highest counter ID seen: c0 Function name: async_closure::main::{closure#0}::{closure#0}:: diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index 10a8ea14504b3..5aed131de2e5e 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -9,13 +9,15 @@ LL| | LL| 1|pub fn main() { LL| 2| let async_closure = async || {}; - ^1 ------------------ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; ------------------ | async_closure::main::{closure#0}: | LL| 1| let async_closure = async || {}; + ------------------ + | async_closure::main::{closure#0}::{closure#0}::: + | LL| 1| let async_closure = async || {}; ------------------ LL| 1| executor::block_on(async_closure()); LL| 1| executor::block_on(call_once(async_closure)); diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index fa20c8cf6d789..2d784ba09b60a 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -1,15 +1,15 @@ Function name: closure::main -Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0f, 0d, 01, 16, 0e, 06, 0a, 01, 10, 05, 13, 0d, 01, 1a, 0e, 06, 0a, 01, 10, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] +Raw bytes (126): 0x[01, 01, 01, 01, 05, 18, 01, 09, 01, 0d, 1b, 01, 1a, 05, 02, 0a, 01, 0c, 05, 11, 1b, 01, 1e, 05, 02, 0a, 01, 0c, 05, 0c, 16, 01, 16, 05, 0d, 18, 01, 19, 09, 01, 1e, 01, 04, 09, 00, 29, 01, 01, 09, 00, 2d, 01, 01, 09, 00, 24, 01, 05, 09, 00, 24, 01, 02, 09, 00, 21, 01, 04, 09, 00, 21, 01, 04, 09, 00, 28, 01, 09, 09, 00, 32, 01, 04, 09, 00, 33, 01, 07, 09, 00, 4b, 01, 08, 09, 00, 48, 01, 0a, 09, 00, 47, 01, 08, 09, 00, 44, 01, 0a, 08, 00, 10, 05, 00, 11, 04, 06, 02, 04, 05, 00, 06, 01, 01, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 24 -- Code(Counter(0)) at (prev + 9, 1) to (start + 15, 13) -- Code(Counter(0)) at (prev + 22, 14) to (start + 6, 10) -- Code(Counter(0)) at (prev + 16, 5) to (start + 19, 13) -- Code(Counter(0)) at (prev + 26, 14) to (start + 6, 10) -- Code(Counter(0)) at (prev + 16, 5) to (start + 12, 22) +- Code(Counter(0)) at (prev + 9, 1) to (start + 13, 27) +- Code(Counter(0)) at (prev + 26, 5) to (start + 2, 10) +- Code(Counter(0)) at (prev + 12, 5) to (start + 17, 27) +- Code(Counter(0)) at (prev + 30, 5) to (start + 2, 10) +- Code(Counter(0)) at (prev + 12, 5) to (start + 12, 22) - Code(Counter(0)) at (prev + 22, 5) to (start + 13, 24) - Code(Counter(0)) at (prev + 25, 9) to (start + 1, 30) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 41) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 3eac52eb72363..2deeb9806c4d4 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -20,18 +20,18 @@ LL| 1| some_string LL| 1| . LL| 1| unwrap_or_else - LL| 1| ( - LL| 1| || + LL| | ( + LL| | || LL| 0| { LL| 0| let mut countdown = 0; LL| 0| if is_false { LL| 0| countdown = 10; LL| 0| } LL| 0| "alt string 1".to_owned() - LL| 1| } - LL| 1| ) - LL| 1| ); - LL| 1| + LL| 0| } + LL| | ) + LL| | ); + LL| | LL| 1| some_string = Some(String::from("the string content")); LL| 1| let LL| 1| a @@ -62,8 +62,8 @@ LL| 1| some_string LL| 1| . LL| 1| unwrap_or_else - LL| 1| ( - LL| 1| || + LL| | ( + LL| | || LL| 1| { LL| 1| let mut countdown = 0; LL| 1| if is_false { @@ -71,9 +71,9 @@ LL| 1| } LL| 1| "alt string 3".to_owned() LL| 1| } - LL| 1| ) - LL| 1| ); - LL| 1| + LL| | ) + LL| | ); + LL| | LL| 1| some_string = None; LL| 1| let LL| 1| a diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 8ff291d2d7d3d..6e2d243e8dd23 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -8,7 +8,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: holes::main -Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 11, 01, 05, 05, 00, 11, 01, 07, 09, 00, 11, 01, 09, 05, 00, 11, 01, 04, 05, 00, 11, 01, 07, 05, 00, 11, 01, 06, 05, 00, 11, 01, 04, 05, 00, 11, 01, 04, 05, 00, 11, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 06, 27, 01, 13, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 @@ -24,8 +24,8 @@ Number of file 0 mappings: 13 - Code(Counter(0)) at (prev + 4, 5) to (start + 0, 17) - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) -- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13) -- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2) +- Code(Counter(0)) at (prev + 10, 5) to (start + 6, 39) +- Code(Counter(0)) at (prev + 19, 5) to (start + 1, 2) Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage index 1b45c12156ae7..a6a02f1b9d081 100644 --- a/tests/coverage/holes.coverage +++ b/tests/coverage/holes.coverage @@ -84,18 +84,18 @@ LL| 1| // `nested_filter::OnlyBodies` or equivalent. LL| 1| #[rustfmt::skip] LL| 1| let _const_block_inside_anon_const = - LL| 1| [ - LL| 1| 0 - LL| 1| ; - LL| 1| 7 - LL| 1| + - LL| 1| const + LL| | [ + LL| | 0 + LL| | ; + LL| | 7 + LL| | + + LL| | const LL| | { LL| | 3 - LL| 1| } - LL| 1| ] - LL| 1| ; - LL| 1| + LL| | } + LL| | ] + LL| | ; + LL| | LL| 1| black_box(()); LL| 1|} From 26cea8a2863a3aa0fd169d8561ce77036ef6983e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 25 Mar 2025 22:02:22 +1100 Subject: [PATCH 226/333] coverage: Don't split bang-macro spans, just truncate them --- .../src/coverage/mappings.rs | 2 +- .../rustc_mir_transform/src/coverage/spans.rs | 45 ++++++------------- tests/coverage/abort.cov-map | 4 +- tests/coverage/assert_not.cov-map | 10 ++--- tests/coverage/bad_counter_ids.cov-map | 16 +++---- tests/coverage/branch/guard.cov-map | 4 +- tests/coverage/branch/if-let.cov-map | 4 +- tests/coverage/branch/if.cov-map | 16 +++---- tests/coverage/branch/lazy-boolean.cov-map | 16 +++---- tests/coverage/branch/let-else.cov-map | 4 +- tests/coverage/branch/match-arms.cov-map | 12 ++--- tests/coverage/branch/match-trivial.cov-map | 8 ++-- tests/coverage/branch/while.cov-map | 16 +++---- tests/coverage/closure_macro.cov-map | 6 +-- tests/coverage/closure_macro_async.cov-map | 6 +-- tests/coverage/coroutine.cov-map | 6 +-- tests/coverage/inline.cov-map | 4 +- tests/coverage/issue-83601.cov-map | 6 +-- tests/coverage/issue-84561.cov-map | 34 +++++++------- tests/coverage/issue-84561.coverage | 42 ++++++++--------- tests/coverage/loops_branches.cov-map | 12 ++--- tests/coverage/macro_name_span.cov-map | 4 +- tests/coverage/panic_unwind.cov-map | 4 +- tests/coverage/try_error_result.cov-map | 12 ++--- tests/coverage/yield.cov-map | 10 ++--- 25 files changed, 143 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index d83c0d40a7e54..73bd2d0705e17 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -96,7 +96,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( } } else { // Extract coverage spans from MIR statements/terminators as normal. - extract_refined_covspans(mir_body, hir_info, graph, &mut code_mappings); + extract_refined_covspans(tcx, mir_body, hir_info, graph, &mut code_mappings); } branch_pairs.extend(extract_branch_pairs(mir_body, hir_info, graph)); diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b1f613432a8b6..f57a158e3e4a7 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -3,6 +3,7 @@ use std::iter; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; +use rustc_middle::ty::TyCtxt; use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::{debug, debug_span, instrument}; @@ -12,8 +13,9 @@ use crate::coverage::{ExtractedHirInfo, mappings, unexpand}; mod from_mir; -pub(super) fn extract_refined_covspans( - mir_body: &mir::Body<'_>, +pub(super) fn extract_refined_covspans<'tcx>( + tcx: TyCtxt<'tcx>, + mir_body: &mir::Body<'tcx>, hir_info: &ExtractedHirInfo, graph: &CoverageGraph, code_mappings: &mut impl Extend, @@ -51,7 +53,7 @@ pub(super) fn extract_refined_covspans( // First, perform the passes that need macro information. covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb)); remove_unwanted_expansion_spans(&mut covspans); - split_visible_macro_spans(&mut covspans); + shrink_visible_macro_spans(tcx, &mut covspans); // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`. let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::>(); @@ -128,35 +130,16 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec) { } /// When a span corresponds to a macro invocation that is visible from the -/// function body, split it into two parts. The first part covers just the -/// macro name plus `!`, and the second part covers the rest of the macro -/// invocation. This seems to give better results for code that uses macros. -fn split_visible_macro_spans(covspans: &mut Vec) { - let mut extra_spans = vec![]; - - covspans.retain(|covspan| { - let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else { - return true; - }; - - let split_len = visible_macro.as_str().len() as u32 + 1; - let (before, after) = covspan.span.split_at(split_len); - if !covspan.span.contains(before) || !covspan.span.contains(after) { - // Something is unexpectedly wrong with the split point. - // The debug assertion in `split_at` will have already caught this, - // but in release builds it's safer to do nothing and maybe get a - // bug report for unexpected coverage, rather than risk an ICE. - return true; +/// function body, truncate it to just the macro name plus `!`. +/// This seems to give better results for code that uses macros. +fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec) { + let source_map = tcx.sess.source_map(); + + for covspan in covspans { + if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) { + covspan.span = source_map.span_through_char(covspan.span, '!'); } - - extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb)); - extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb)); - false // Discard the original covspan that we just split. - }); - - // The newly-split spans are added at the end, so any previous sorting - // is not preserved. - covspans.extend(extra_spans); + } } /// Uses the holes to divide the given covspans into buckets, such that: diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 84fae4a595a71..26536caeba52c 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -34,14 +34,14 @@ Number of file 0 mappings: 13 Highest counter ID seen: c4 Function name: abort::might_abort -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 3, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 526110ebbb764..3aef4274edc34 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -1,13 +1,13 @@ Function name: assert_not::main -Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 01, 02, 05, 00, 14, 01, 01, 05, 00, 14, 01, 01, 05, 00, 16, 01, 01, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 11, 01, 02, 05, 00, 13, 01, 01, 05, 00, 13, 01, 01, 05, 00, 15, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18) -- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 20) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 20) -- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 22) +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 17) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 19) +- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 21) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index baac0073fcbec..f08a70a899d09 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,10 +1,10 @@ Function name: bad_counter_ids::eq_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 0f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 15) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -20,12 +20,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 01, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 0f, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 15) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -41,12 +41,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 0f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 15) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 @@ -62,12 +62,12 @@ Number of file 0 mappings: 3 Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 1f, 01, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1a, 01, 02, 0f, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 15) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map index 55f45daa9c93d..46533df00f715 100644 --- a/tests/coverage/branch/guard.cov-map +++ b/tests/coverage/branch/guard.cov-map @@ -1,5 +1,5 @@ Function name: guard::branch_match_guard -Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 10, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] +Raw bytes (89): 0x[01, 01, 08, 05, 0d, 09, 05, 05, 0f, 0d, 11, 17, 1b, 01, 05, 1f, 11, 09, 0d, 0d, 01, 0c, 01, 01, 0e, 02, 03, 0b, 00, 0c, 06, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 05, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 02, 00, 14, 00, 19, 20, 11, 0a, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 12, 03, 0e, 02, 0a, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(4) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 13 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Expression(0, Sub)) at (prev + 3, 11) to (start + 0, 12) = (c1 - c3) - Code(Expression(1, Sub)) at (prev + 1, 20) to (start + 2, 10) diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map index db45df2a5cd00..7f6b174615a9b 100644 --- a/tests/coverage/branch/if-let.cov-map +++ b/tests/coverage/branch/if-let.cov-map @@ -1,11 +1,11 @@ Function name: if_let::if_let -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 1b, 02, 00, 1c, 02, 06, 05, 02, 0c, 02, 06, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 12) to (start + 0, 19) true = (c0 - c1) false = c1 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 392ace1683a75..1d40f032aa87c 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -1,5 +1,5 @@ Function name: if::branch_and -Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (54): 0x[01, 01, 03, 01, 05, 05, 09, 01, 09, 08, 01, 2b, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 09, 06, 00, 0d, 00, 0e, 09, 00, 0f, 02, 06, 0a, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -7,7 +7,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -23,7 +23,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: if::branch_not -Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (116): 0x[01, 01, 07, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 01, 11, 01, 11, 12, 01, 0c, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 05, 01, 09, 00, 10, 02, 01, 05, 00, 06, 01, 01, 08, 00, 0a, 20, 0a, 09, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 09, 02, 05, 00, 06, 01, 01, 08, 00, 0b, 20, 0d, 12, 00, 08, 00, 0b, 0d, 00, 0c, 02, 06, 12, 02, 05, 00, 06, 01, 01, 08, 00, 0c, 20, 1a, 11, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 11, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -35,7 +35,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Counter(0), rhs = Counter(4) - expression 6 operands: lhs = Counter(0), rhs = Counter(4) Number of file 0 mappings: 18 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -68,7 +68,7 @@ Number of file 0 mappings: 18 Highest counter ID seen: c4 Function name: if::branch_not_as -Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 10, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (90): 0x[01, 01, 05, 01, 05, 01, 09, 01, 09, 01, 0d, 01, 0d, 0e, 01, 1d, 01, 01, 0e, 01, 03, 08, 00, 14, 20, 02, 05, 00, 08, 00, 14, 02, 00, 15, 02, 06, 05, 02, 05, 00, 06, 01, 01, 08, 00, 15, 20, 09, 0a, 00, 08, 00, 15, 09, 00, 16, 02, 06, 0a, 02, 05, 00, 06, 01, 01, 08, 00, 16, 20, 12, 0d, 00, 08, 00, 16, 12, 00, 17, 02, 06, 0d, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -78,7 +78,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(0), rhs = Counter(3) - expression 4 operands: lhs = Counter(0), rhs = Counter(3) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 0, 8) to (start + 0, 20) true = (c0 - c1) @@ -104,7 +104,7 @@ Number of file 0 mappings: 14 Highest counter ID seen: c3 Function name: if::branch_or -Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 10, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (60): 0x[01, 01, 06, 01, 05, 01, 17, 05, 09, 05, 09, 01, 17, 05, 09, 08, 01, 35, 01, 01, 0e, 01, 03, 08, 00, 09, 20, 05, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 09, 12, 00, 0d, 00, 0e, 17, 00, 0f, 02, 06, 12, 02, 0c, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -115,7 +115,7 @@ Number of expressions: 6 - expression 4 operands: lhs = Counter(0), rhs = Expression(5, Add) - expression 5 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 8) to (start + 0, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index ff285a038fb87..5d4fc57eb8f75 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -1,11 +1,11 @@ Function name: lazy_boolean::branch_and -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 13, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 19, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -16,13 +16,13 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::branch_or -Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] +Raw bytes (38): 0x[01, 01, 01, 01, 05, 06, 01, 1b, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 27, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 14) @@ -34,7 +34,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: lazy_boolean::chain -Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] +Raw bytes (141): 0x[01, 01, 0f, 01, 05, 05, 09, 09, 0d, 01, 11, 01, 11, 01, 3b, 11, 15, 01, 3b, 11, 15, 01, 37, 3b, 19, 11, 15, 01, 37, 3b, 19, 11, 15, 13, 01, 24, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 05, 02, 00, 0d, 00, 12, 05, 00, 16, 00, 1b, 20, 09, 06, 00, 16, 00, 1b, 09, 00, 1f, 00, 24, 20, 0d, 0a, 00, 1f, 00, 24, 0d, 00, 28, 00, 2d, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0d, 00, 12, 20, 11, 12, 00, 0d, 00, 12, 12, 00, 16, 00, 1b, 20, 15, 1e, 00, 16, 00, 1b, 1e, 00, 1f, 00, 24, 20, 19, 32, 00, 1f, 00, 24, 32, 00, 28, 00, 2d, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 15 @@ -54,7 +54,7 @@ Number of expressions: 15 - expression 13 operands: lhs = Expression(14, Add), rhs = Counter(6) - expression 14 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 36, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 18) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 13) to (start + 0, 18) @@ -91,7 +91,7 @@ Number of file 0 mappings: 19 Highest counter ID seen: c6 Function name: lazy_boolean::nested_mixed -Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 10, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] +Raw bytes (137): 0x[01, 01, 0d, 01, 05, 01, 1f, 05, 09, 05, 09, 1f, 0d, 05, 09, 1f, 0d, 05, 09, 01, 11, 11, 15, 01, 15, 01, 33, 15, 19, 13, 01, 31, 01, 01, 0e, 01, 04, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 05, 02, 00, 0e, 00, 13, 02, 00, 17, 00, 1d, 20, 09, 06, 00, 17, 00, 1d, 1f, 00, 23, 00, 28, 20, 0d, 1a, 00, 23, 00, 28, 1a, 00, 2c, 00, 33, 01, 01, 05, 00, 10, 01, 03, 09, 00, 0a, 01, 00, 0e, 00, 13, 20, 11, 22, 00, 0e, 00, 13, 11, 00, 17, 00, 1c, 20, 15, 26, 00, 17, 00, 1c, 2a, 00, 22, 00, 28, 20, 19, 2e, 00, 22, 00, 28, 19, 00, 2c, 00, 33, 01, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -109,7 +109,7 @@ Number of expressions: 13 - expression 11 operands: lhs = Counter(0), rhs = Expression(12, Add) - expression 12 operands: lhs = Counter(5), rhs = Counter(6) Number of file 0 mappings: 19 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 4, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 19) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 14) to (start + 0, 19) diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 811b9838e3f51..78507a326388a 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,11 +1,11 @@ Function name: let_else::let_else -Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 10, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 01, 01, 05, 07, 01, 0c, 01, 01, 0e, 20, 02, 05, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 01, 00, 13, 00, 18, 05, 01, 09, 01, 0f, 02, 04, 05, 00, 0a, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Branch { true: Expression(0, Sub), false: Counter(1) } at (prev + 3, 9) to (start + 0, 16) true = (c0 - c1) false = c1 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index caa18820cf8e7..ef71d12c8af1a 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -1,5 +1,5 @@ Function name: match_arms::guards -Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 10, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] +Raw bytes (88): 0x[01, 01, 08, 15, 05, 19, 09, 1d, 0d, 21, 11, 01, 17, 1b, 11, 1f, 0d, 05, 09, 0c, 01, 30, 01, 01, 0e, 21, 03, 0b, 00, 10, 05, 01, 11, 00, 28, 20, 05, 02, 00, 17, 00, 1b, 09, 01, 11, 00, 28, 20, 09, 06, 00, 17, 00, 1b, 0d, 01, 11, 00, 28, 20, 0d, 0a, 00, 17, 00, 1b, 11, 01, 11, 00, 28, 20, 11, 0e, 00, 17, 00, 1b, 12, 01, 0e, 00, 15, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Expression(7, Add), rhs = Counter(3) - expression 7 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 12 -- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 48, 1) to (start + 1, 14) - Code(Counter(8)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 40) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 0, 23) to (start + 0, 27) @@ -36,7 +36,7 @@ Number of file 0 mappings: 12 Highest counter ID seen: c8 Function name: match_arms::match_arms -Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] +Raw bytes (45): 0x[01, 01, 03, 01, 07, 0b, 0d, 05, 09, 07, 01, 18, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 20, 09, 01, 11, 00, 20, 0d, 01, 11, 00, 20, 02, 01, 11, 00, 20, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -44,7 +44,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 32) - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 32) @@ -55,7 +55,7 @@ Number of file 0 mappings: 7 Highest counter ID seen: c3 Function name: match_arms::or_patterns -Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 10, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] +Raw bytes (57): 0x[01, 01, 04, 05, 09, 01, 0b, 03, 0d, 01, 03, 09, 01, 25, 01, 01, 0e, 01, 03, 0b, 00, 10, 05, 01, 11, 00, 12, 09, 00, 1e, 00, 1f, 03, 00, 24, 00, 2d, 0d, 01, 11, 00, 12, 06, 00, 1e, 00, 1f, 0e, 00, 24, 00, 2d, 01, 03, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -64,7 +64,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(0), rhs = Expression(0, Add) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 37, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 0, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 18) - Code(Counter(2)) at (prev + 0, 30) to (start + 0, 31) diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map index 31322f127af78..1b0c6d12e3dc1 100644 --- a/tests/coverage/branch/match-trivial.cov-map +++ b/tests/coverage/branch/match-trivial.cov-map @@ -1,19 +1,19 @@ Function name: match_trivial::_uninhabited (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 10] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 0e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 1) to (start + 1, 16) +- Code(Zero) at (prev + 22, 1) to (start + 1, 14) Highest counter ID seen: (none) Function name: match_trivial::trivial -Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 01, 03, 0b, 05, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 0e, 01, 03, 0b, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 11) to (start + 5, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map index 5ce92c72b5120..67746af051b68 100644 --- a/tests/coverage/branch/while.cov-map +++ b/tests/coverage/branch/while.cov-map @@ -1,11 +1,11 @@ Function name: while::while_cond -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 0c, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 10, 20, 02, 01, 00, 0b, 00, 10, 02, 00, 11, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 16) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 16) @@ -17,13 +17,13 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_cond_not -Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 10, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (38): 0x[01, 01, 01, 05, 01, 06, 01, 15, 01, 01, 0e, 01, 03, 09, 00, 12, 05, 01, 0b, 00, 14, 20, 02, 01, 00, 0b, 00, 14, 02, 00, 15, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 11) to (start + 0, 20) - Branch { true: Expression(0, Sub), false: Counter(0) } at (prev + 0, 11) to (start + 0, 20) @@ -35,7 +35,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: while::while_op_and -Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (58): 0x[01, 01, 05, 05, 09, 05, 01, 0f, 05, 01, 09, 05, 01, 08, 01, 1e, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 09, 00, 14, 00, 19, 20, 12, 0a, 00, 14, 00, 19, 12, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -45,7 +45,7 @@ Number of expressions: 5 - expression 3 operands: lhs = Counter(0), rhs = Counter(2) - expression 4 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) @@ -61,7 +61,7 @@ Number of file 0 mappings: 8 Highest counter ID seen: c2 Function name: while::while_op_or -Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 10, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] +Raw bytes (56): 0x[01, 01, 04, 05, 09, 05, 0b, 01, 09, 05, 01, 08, 01, 29, 01, 01, 0e, 01, 03, 09, 01, 12, 05, 02, 0b, 00, 10, 20, 09, 02, 00, 0b, 00, 10, 02, 00, 14, 00, 19, 20, 06, 01, 00, 14, 00, 19, 0e, 00, 1a, 03, 06, 01, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -70,7 +70,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(0), rhs = Counter(2) - expression 3 operands: lhs = Counter(1), rhs = Counter(0) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16) +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 14) - Code(Counter(0)) at (prev + 3, 9) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 16) - Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 11) to (start + 0, 16) diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 653848dd6ffc7..9dd99c8fab3f0 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -8,16 +8,16 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: closure_macro::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 32) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 1bd1460a147a2..2548754d754c0 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -17,16 +17,16 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 20, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 34, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 32) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) -- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) +- Code(Counter(0)) at (prev + 0, 18) to (start + 0, 52) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 297dde3b2b0f9..fee32376d8317 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -13,7 +13,7 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: coroutine::main -Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 35, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 35, 09, 02, 01, 00, 02] +Raw bytes (53): 0x[01, 01, 02, 01, 05, 05, 09, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2d, 05, 01, 2b, 00, 2d, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 @@ -23,12 +23,12 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 22) - Code(Counter(0)) at (prev + 8, 11) to (start + 0, 45) - Code(Counter(1)) at (prev + 1, 43) to (start + 0, 45) -- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) -- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 53) +- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c1 - c2) - Code(Counter(2)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c3 diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map index a569ad53cbc24..7264391baaf7b 100644 --- a/tests/coverage/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -15,12 +15,12 @@ Number of file 0 mappings: 5 Highest counter ID seen: c1 Function name: inline::error -Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 0b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20) +- Code(Counter(0)) at (prev + 49, 1) to (start + 1, 11) Highest counter ID seen: c0 Function name: inline::length:: diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index c188cca1b517a..f102310900894 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -1,12 +1,12 @@ Function name: issue_83601::main -Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 0f, 05, 03, 09, 01, 0f, 02, 02, 05, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28) -- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) +- Code(Counter(0)) at (prev + 6, 1) to (start + 2, 15) +- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) = (c1 - c2) Highest counter ID seen: c1 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index c8f75cddcb5b9..3bd4e7d2a3666 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -1,11 +1,11 @@ Function name: ::fmt -Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, 8a, 01, 05, 01, 24, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 37) +- Code(Counter(0)) at (prev + 138, 5) to (start + 1, 36) - Code(Counter(1)) at (prev + 1, 37) to (start + 0, 38) - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) @@ -59,7 +59,7 @@ Number of file 0 mappings: 1 Highest counter ID seen: c0 Function name: issue_84561::test3 -Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 09, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 11, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 19, 02, 05, 00, 1f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 05, 06, 35, 06, 05, 03, 06, 39, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 41, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 1a, 05, 09, 03, 0a, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] +Raw bytes (315): 0x[01, 01, 1b, 1d, 21, 25, 29, 21, 25, 2d, 31, 21, 17, 25, 2d, 41, 45, 49, 4d, 51, 55, 33, 51, 49, 4d, 33, 37, 49, 4d, 51, 59, 55, 59, 55, 59, 47, 5d, 55, 59, 61, 65, 71, 75, 69, 6d, 69, 6d, 69, 6d, 63, 79, 71, 75, 79, 7d, 7d, 81, 01, 33, 01, 08, 01, 03, 0f, 05, 04, 09, 01, 0f, 09, 02, 05, 04, 0f, 0d, 05, 05, 00, 0f, 11, 01, 05, 00, 0f, 15, 01, 09, 01, 0f, 19, 02, 05, 00, 0f, 1d, 01, 05, 00, 0f, 02, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 25, 03, 20, 00, 30, 29, 00, 33, 00, 41, 06, 00, 4b, 00, 5a, 0a, 01, 05, 00, 0f, 2d, 05, 09, 03, 10, 31, 05, 0d, 00, 1b, 0e, 02, 0d, 00, 1c, 12, 04, 09, 02, 0f, 35, 06, 05, 00, 0f, 39, 04, 05, 00, 0f, 3d, 04, 09, 01, 0f, 41, 05, 08, 00, 0f, 45, 01, 09, 00, 13, 1a, 05, 09, 00, 13, 33, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 22, 03, 0d, 00, 1d, 26, 03, 09, 00, 13, 2e, 03, 0d, 00, 1d, 47, 03, 05, 00, 0f, 47, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 42, 02, 0d, 00, 13, 61, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 4a, 02, 0d, 00, 13, 63, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 00, 17, 71, 04, 0d, 00, 13, 5a, 02, 0d, 00, 17, 5a, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 5a, 02, 15, 00, 1b, 75, 04, 0d, 00, 13, 5e, 03, 09, 00, 19, 79, 02, 05, 00, 0f, 66, 03, 09, 00, 22, 7d, 02, 05, 00, 0f, 6a, 03, 09, 00, 2c, 81, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 27 @@ -91,13 +91,13 @@ Number of expressions: 27 - expression 25 operands: lhs = Counter(30), rhs = Counter(31) - expression 26 operands: lhs = Counter(31), rhs = Counter(32) Number of file 0 mappings: 51 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28) -- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28) -- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 31) -- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31) -- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 31) -- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28) -- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 31) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 15) +- Code(Counter(1)) at (prev + 4, 9) to (start + 1, 15) +- Code(Counter(2)) at (prev + 2, 5) to (start + 4, 15) +- Code(Counter(3)) at (prev + 5, 5) to (start + 0, 15) +- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 15) +- Code(Counter(5)) at (prev + 1, 9) to (start + 1, 15) +- Code(Counter(6)) at (prev + 2, 5) to (start + 0, 15) - Code(Counter(7)) at (prev + 1, 5) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 0, 32) to (start + 0, 48) = (c7 - c8) @@ -112,14 +112,14 @@ Number of file 0 mappings: 51 - Code(Counter(12)) at (prev + 5, 13) to (start + 0, 27) - Code(Expression(3, Sub)) at (prev + 2, 13) to (start + 0, 28) = (c11 - c12) -- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 5, 6) +- Code(Expression(4, Sub)) at (prev + 4, 9) to (start + 2, 15) = (c8 - (c9 + c11)) -- Code(Counter(13)) at (prev + 6, 5) to (start + 3, 6) -- Code(Counter(14)) at (prev + 4, 5) to (start + 3, 6) -- Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6) +- Code(Counter(13)) at (prev + 6, 5) to (start + 0, 15) +- Code(Counter(14)) at (prev + 4, 5) to (start + 0, 15) +- Code(Counter(15)) at (prev + 4, 9) to (start + 1, 15) - Code(Counter(16)) at (prev + 5, 8) to (start + 0, 15) -- Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10) -- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 3, 10) +- Code(Counter(17)) at (prev + 1, 9) to (start + 0, 19) +- Code(Expression(6, Sub)) at (prev + 5, 9) to (start + 0, 19) = (c16 - c17) - Code(Expression(12, Add)) at (prev + 5, 8) to (start + 0, 15) = (c18 + c19) @@ -144,7 +144,7 @@ Number of file 0 mappings: 51 - Code(Expression(24, Add)) at (prev + 3, 5) to (start + 0, 15) = (c28 + c29) - Code(Counter(26)) at (prev + 1, 12) to (start + 0, 19) -- Code(Counter(27)) at (prev + 1, 13) to (start + 3, 14) +- Code(Counter(27)) at (prev + 1, 13) to (start + 0, 23) - Code(Counter(28)) at (prev + 4, 13) to (start + 0, 19) - Code(Expression(22, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c26 - c27) diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index 2a642e2427b90..a55f42a696e69 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -47,32 +47,32 @@ LL| 1| let is_true = std::env::args().len() == 1; LL| 1| LL| 1| assert_eq!( - LL| 1| Foo(1), - LL| 1| Foo(1) - LL| 1| ); + LL| | Foo(1), + LL| | Foo(1) + LL| | ); LL| 1| assert_ne!( - LL| 1| Foo(0), - LL| 1| Foo(1) - LL| 1| ); + LL| | Foo(0), + LL| | Foo(1) + LL| | ); LL| 1| assert_eq!( - LL| 1| Foo(2), - LL| 1| Foo(2) - LL| 1| ); + LL| | Foo(2), + LL| | Foo(2) + LL| | ); LL| 1| let bar = Foo(1); LL| 1| assert_ne!( - LL| 1| bar, - LL| 1| Foo(3) - LL| 1| ); + LL| | bar, + LL| | Foo(3) + LL| | ); LL| 1| if is_true { LL| 1| assert_ne!( - LL| 1| Foo(0), - LL| 1| Foo(4) - LL| 1| ); + LL| | Foo(0), + LL| | Foo(4) + LL| | ); LL| | } else { LL| 0| assert_eq!( - LL| 0| Foo(3), - LL| 0| Foo(3) - LL| 0| ); + LL| | Foo(3), + LL| | Foo(3) + LL| | ); LL| | } LL| 1| if is_true { LL| 1| assert_ne!( @@ -106,9 +106,9 @@ LL| 1| assert_ne!( LL| 1| if is_true { LL| 1| assert_eq!( - LL| 1| Foo(3), - LL| 1| Foo(3) - LL| 1| ); + LL| | Foo(3), + LL| | Foo(3) + LL| | ); LL| 1| Foo(0) LL| | } else { LL| 0| assert_ne!( diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 2cb0f948b3e1d..2157cd6ee3f8e 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -1,5 +1,5 @@ Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 22, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 0d, 05, 09, 09, 0d, 14, 01, 09, 05, 01, 10, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 05, 00, 1e, 00, 1f, 00, 01, 10, 01, 0a, 0d, 03, 0d, 00, 0e, 09, 00, 12, 00, 17, 0d, 01, 10, 00, 14, 0d, 01, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 0d, 01, 11, 00, 12, 0d, 01, 11, 00, 21, 02, 00, 22, 00, 23, 00, 01, 14, 01, 0e, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -13,7 +13,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) - Code(Counter(1)) at (prev + 0, 30) to (start + 0, 31) - Code(Zero) at (prev + 1, 16) to (start + 1, 10) - Code(Counter(3)) at (prev + 3, 13) to (start + 0, 14) @@ -23,7 +23,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(3)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 34) +- Code(Counter(3)) at (prev + 1, 17) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c3) - (c1 + c2)) - Code(Zero) at (prev + 1, 20) to (start + 1, 14) @@ -33,7 +33,7 @@ Number of file 0 mappings: 20 Highest counter ID seen: c3 Function name: ::fmt -Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1e, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 22, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] +Raw bytes (112): 0x[01, 01, 04, 07, 0b, 01, 09, 05, 0d, 05, 09, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 01, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 01, 01, 0d, 00, 0e, 01, 01, 0d, 00, 1d, 0d, 00, 1e, 00, 1f, 09, 02, 0d, 00, 0e, 05, 00, 12, 00, 17, 09, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 09, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 09, 01, 11, 00, 12, 09, 01, 11, 00, 21, 02, 00, 22, 00, 23, 0e, 03, 09, 00, 0f, 01, 01, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -48,7 +48,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 23) to (start + 0, 27) - Code(Zero) at (prev + 0, 28) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) -- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 30) +- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 29) - Code(Counter(3)) at (prev + 0, 30) to (start + 0, 31) - Code(Counter(2)) at (prev + 2, 13) to (start + 0, 14) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 23) @@ -58,7 +58,7 @@ Number of file 0 mappings: 20 - Code(Zero) at (prev + 1, 27) to (start + 0, 31) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Counter(2)) at (prev + 1, 17) to (start + 0, 18) -- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 34) +- Code(Counter(2)) at (prev + 1, 17) to (start + 0, 33) - Code(Expression(0, Sub)) at (prev + 0, 34) to (start + 0, 35) = ((c0 + c2) - (c1 + c3)) - Code(Expression(3, Sub)) at (prev + 3, 9) to (start + 0, 15) diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index 58620452b2ba6..bd033faa5510f 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -1,10 +1,10 @@ Function name: macro_name_span::affected_function -Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 3e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) +- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 62) Highest counter ID seen: c0 Function name: macro_name_span::main diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index 4628a24689e7a..18b13919fe5e4 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -26,14 +26,14 @@ Number of file 0 mappings: 9 Highest counter ID seen: c3 Function name: panic_unwind::might_panic -Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 0f, 02, 02, 0c, 03, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 4, 1) to (start + 1, 20) -- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25) +- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 15) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) Highest counter ID seen: c1 diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index a4a8e21d8c315..e45f3de10815e 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -82,7 +82,7 @@ Number of file 0 mappings: 11 Highest counter ID seen: c2 Function name: try_error_result::test2 -Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 20, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 20, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 20, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 20, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 20, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] +Raw bytes (336): 0x[01, 01, 36, 0d, 11, 0d, 3f, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 0d, 3f, 11, 15, 0d, 3b, 3f, 19, 11, 15, 0d, 37, 3b, 1d, 3f, 19, 11, 15, 41, 53, 21, 25, 41, 21, 41, 53, 21, 25, 09, 73, 77, 2d, 0d, 29, 09, 0d, 09, 77, 0d, 29, 09, 73, 77, 2d, 0d, 29, 45, 8b, 01, 31, 35, 45, 31, 45, 8b, 01, 31, 35, 49, 9f, 01, 39, 3d, 49, 39, 49, 9f, 01, 39, 3d, 05, 09, ab, 01, 09, af, 01, 3d, b3, 01, 39, b7, 01, 35, bb, 01, 31, bf, 01, 2d, c3, 01, 29, c7, 01, 25, cb, 01, 21, cf, 01, 1d, d3, 01, 19, d7, 01, 15, 05, 11, 28, 01, 3d, 01, 03, 17, 05, 08, 09, 00, 0e, 09, 02, 09, 04, 1a, 0d, 06, 0d, 00, 1f, 11, 00, 2f, 00, 30, 02, 00, 31, 03, 1c, 15, 04, 11, 00, 12, 1e, 02, 11, 03, 27, 32, 05, 11, 00, 14, 1e, 00, 17, 00, 29, 19, 00, 41, 00, 42, 26, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 32, 01, 0d, 00, 17, 4e, 01, 11, 00, 14, 41, 00, 17, 00, 29, 21, 00, 41, 00, 42, 4a, 00, 43, 00, 47, 25, 00, 60, 00, 61, 4e, 01, 0d, 00, 17, 6e, 04, 11, 00, 14, 62, 00, 17, 00, 29, 29, 00, 42, 00, 43, 66, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 6e, 01, 0d, 00, 17, 86, 01, 01, 11, 00, 14, 45, 00, 17, 01, 1d, 31, 01, 36, 00, 37, 82, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, 86, 01, 01, 0d, 00, 17, 9a, 01, 01, 11, 00, 14, 49, 00, 17, 01, 1d, 39, 02, 11, 00, 12, 96, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, 9a, 01, 02, 0d, 00, 17, a2, 01, 03, 05, 00, 0b, a6, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 54 @@ -159,7 +159,7 @@ Number of file 0 mappings: 40 - Code(Expression(9, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c3 - ((c4 + c5) + c6)) - Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96) -- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(12, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c3 - (((c4 + c5) + c6) + c7)) - Code(Expression(19, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c16 - (c8 + c9)) @@ -168,7 +168,7 @@ Number of file 0 mappings: 40 - Code(Expression(18, Sub)) at (prev + 0, 67) to (start + 0, 71) = (c16 - c8) - Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97) -- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(19, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c16 - (c8 + c9)) - Code(Expression(27, Sub)) at (prev + 4, 17) to (start + 0, 20) = (c2 - ((c3 + c10) + c11)) @@ -178,7 +178,7 @@ Number of file 0 mappings: 40 - Code(Expression(25, Sub)) at (prev + 0, 68) to (start + 0, 72) = (c2 - (c3 + c10)) - Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98) -- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(27, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c2 - ((c3 + c10) + c11)) - Code(Expression(33, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c17 - (c12 + c13)) @@ -187,7 +187,7 @@ Number of file 0 mappings: 40 - Code(Expression(32, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c17 - c12) - Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48) -- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 32) +- Code(Expression(33, Sub)) at (prev + 1, 13) to (start + 0, 23) = (c17 - (c12 + c13)) - Code(Expression(38, Sub)) at (prev + 1, 17) to (start + 0, 20) = (c18 - (c14 + c15)) @@ -196,7 +196,7 @@ Number of file 0 mappings: 40 - Code(Expression(37, Sub)) at (prev + 1, 18) to (start + 0, 22) = (c18 - c14) - Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18) -- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 32) +- Code(Expression(38, Sub)) at (prev + 2, 13) to (start + 0, 23) = (c18 - (c14 + c15)) - Code(Expression(40, Sub)) at (prev + 3, 5) to (start + 0, 11) = (c1 - c2) diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index d296f9bd778a2..bf0916e5503a9 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -1,5 +1,5 @@ Function name: yield::main -Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 34, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 34, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 34, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 34, 12, 02, 01, 00, 02] +Raw bytes (94): 0x[01, 01, 05, 01, 05, 05, 09, 09, 11, 11, 15, 11, 15, 10, 01, 07, 01, 01, 16, 01, 07, 0b, 00, 2e, 05, 01, 27, 00, 29, 02, 01, 0e, 00, 14, 05, 02, 0b, 00, 2e, 0d, 01, 22, 00, 27, 09, 00, 2c, 00, 2e, 06, 01, 0e, 00, 14, 09, 03, 09, 00, 16, 09, 08, 0b, 00, 2e, 11, 01, 27, 00, 29, 0a, 01, 0e, 00, 14, 11, 02, 0b, 00, 2e, 12, 01, 27, 00, 29, 15, 01, 0e, 00, 14, 12, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 5 @@ -12,22 +12,22 @@ Number of file 0 mappings: 16 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 22) - Code(Counter(0)) at (prev + 7, 11) to (start + 0, 46) - Code(Counter(1)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(0, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c0 - c1) - Code(Counter(1)) at (prev + 2, 11) to (start + 0, 46) - Code(Counter(3)) at (prev + 1, 34) to (start + 0, 39) - Code(Counter(2)) at (prev + 0, 44) to (start + 0, 46) -- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(1, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c1 - c2) - Code(Counter(2)) at (prev + 3, 9) to (start + 0, 22) - Code(Counter(2)) at (prev + 8, 11) to (start + 0, 46) - Code(Counter(4)) at (prev + 1, 39) to (start + 0, 41) -- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 52) +- Code(Expression(2, Sub)) at (prev + 1, 14) to (start + 0, 20) = (c2 - c4) - Code(Counter(4)) at (prev + 2, 11) to (start + 0, 46) - Code(Expression(4, Sub)) at (prev + 1, 39) to (start + 0, 41) = (c4 - c5) -- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 52) +- Code(Counter(5)) at (prev + 1, 14) to (start + 0, 20) - Code(Expression(4, Sub)) at (prev + 2, 1) to (start + 0, 2) = (c4 - c5) Highest counter ID seen: c5 From 59307fd9fd17b46d0fa65c7e542d39dedd2dec66 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Mar 2025 15:53:22 +1100 Subject: [PATCH 227/333] Factor out some shared code. `global_allocator_spans` and `alloc_error_handler_span` are identical except for `name`. --- compiler/rustc_metadata/src/creader.rs | 46 ++++++++------------------ 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b7f13e0afdcde..e1ee562dafeb3 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1032,14 +1032,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } fn inject_allocator_crate(&mut self, krate: &ast::Crate) { - self.cstore.has_global_allocator = match &*global_allocator_spans(krate) { - [span1, span2, ..] => { - self.dcx().emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); - true - } - spans => !spans.is_empty(), - }; - self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) { + self.cstore.has_global_allocator = + match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { + [span1, span2, ..] => { + self.dcx() + .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); + true + } + spans => !spans.is_empty(), + }; + self.cstore.has_alloc_error_handler = match &*fn_spans( + krate, + Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)), + ) { [span1, span2, ..] => { self.dcx() .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); @@ -1368,29 +1373,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } -fn global_allocator_spans(krate: &ast::Crate) -> Vec { - struct Finder { - name: Symbol, - spans: Vec, - } - impl<'ast> visit::Visitor<'ast> for Finder { - fn visit_item(&mut self, item: &'ast ast::Item) { - if item.ident.name == self.name - && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) - { - self.spans.push(item.span); - } - visit::walk_item(self, item) - } - } - - let name = Symbol::intern(&global_fn_name(sym::alloc)); - let mut f = Finder { name, spans: Vec::new() }; - visit::walk_crate(&mut f, krate); - f.spans -} - -fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec { +fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec { struct Finder { name: Symbol, spans: Vec, @@ -1406,7 +1389,6 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec { } } - let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)); let mut f = Finder { name, spans: Vec::new() }; visit::walk_crate(&mut f, krate); f.spans From 4c551bcacd4b6d5652a6e9bc6fd5b7afbac435ae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 09:47:32 +1100 Subject: [PATCH 228/333] Simplify `ItemVisitorKind`. Instead of putting the item inside it, just pass the ident and visibility (the only things needed) alongside it where necessary. This helps with the next commit, which will move the ident's location. Specifically, it gets rid of the `match visitor_kind` in `rewrite_type_alias`. --- src/tools/rustfmt/src/items.rs | 42 ++++++++++++++++++-------------- src/tools/rustfmt/src/visitor.rs | 29 +++++++++++++--------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 3fb3284e3d7fd..415b83060b85c 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -6,7 +6,7 @@ use std::cmp::{Ordering, max, min}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{BytePos, DUMMY_SP, Span, symbol}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol}; use tracing::debug; use crate::attr::filter_inline_attrs; @@ -1679,11 +1679,12 @@ fn format_tuple_struct( Some(result) } -pub(crate) enum ItemVisitorKind<'a> { - Item(&'a ast::Item), - AssocTraitItem(&'a ast::AssocItem), - AssocImplItem(&'a ast::AssocItem), - ForeignItem(&'a ast::ForeignItem), +#[derive(Clone, Copy)] +pub(crate) enum ItemVisitorKind { + Item, + AssocTraitItem, + AssocImplItem, + ForeignItem, } struct TyAliasRewriteInfo<'c, 'g>( @@ -1695,11 +1696,13 @@ struct TyAliasRewriteInfo<'c, 'g>( Span, ); -pub(crate) fn rewrite_type_alias<'a, 'b>( +pub(crate) fn rewrite_type_alias<'a>( ty_alias_kind: &ast::TyAlias, + vis: &ast::Visibility, + ident: Ident, context: &RewriteContext<'a>, indent: Indent, - visitor_kind: &ItemVisitorKind<'b>, + visitor_kind: ItemVisitorKind, span: Span, ) -> RewriteResult { use ItemVisitorKind::*; @@ -1715,11 +1718,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( let rhs_hi = ty .as_ref() .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi()); - let (ident, vis) = match visitor_kind { - Item(i) => (i.ident, &i.vis), - AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis), - ForeignItem(i) => (i.ident, &i.vis), - }; let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span); let op_ty = opaque_ty(ty); // Type Aliases are formatted slightly differently depending on the context @@ -1727,14 +1725,14 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases match (visitor_kind, &op_ty) { - (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => { + (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => { let op = OpaqueType { bounds: op_bounds }; rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis) } - (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => { + (Item | AssocTraitItem | ForeignItem, None) => { rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis) } - (AssocImplItem(_), _) => { + (AssocImplItem, _) => { let result = if let Some(op_bounds) = op_ty { let op = OpaqueType { bounds: op_bounds }; rewrite_ty( @@ -3498,8 +3496,16 @@ impl Rewrite for ast::ForeignItem { .map(|s| s + ";") } ast::ForeignItemKind::TyAlias(ref ty_alias) => { - let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); - rewrite_type_alias(ty_alias, context, shape.indent, kind, span) + let kind = ItemVisitorKind::ForeignItem; + rewrite_type_alias( + ty_alias, + &self.vis, + self.ident, + context, + shape.indent, + kind, + self.span, + ) } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 5749d8c63faf4..c70649cc81259 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use std::sync::Arc; use rustc_ast::{ast, token::Delimiter, visit}; -use rustc_span::{BytePos, Pos, Span, symbol}; +use rustc_span::{BytePos, Ident, Pos, Span, symbol}; use tracing::debug; use crate::attr::*; @@ -573,7 +573,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } ast::ItemKind::TyAlias(ref ty_alias) => { use ItemVisitorKind::Item; - self.visit_ty_alias_kind(ty_alias, &Item(item), item.span); + self.visit_ty_alias_kind(ty_alias, &item.vis, item.ident, Item, item.span); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); @@ -605,11 +605,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_ty_alias_kind( &mut self, ty_kind: &ast::TyAlias, - visitor_kind: &ItemVisitorKind<'_>, + vis: &ast::Visibility, + ident: Ident, + visitor_kind: ItemVisitorKind, span: Span, ) { let rewrite = rewrite_type_alias( ty_kind, + vis, + ident, &self.get_context(), self.block_indent, visitor_kind, @@ -619,15 +623,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(span, rewrite); } - fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) { + fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) { use ItemVisitorKind::*; // TODO(calebcartwright): Not sure the skip spans are correct - let (ai, skip_span, assoc_ctxt) = match visitor_kind { - AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait), + let assoc_ctxt = match visitor_kind { + AssocTraitItem => visit::AssocCtxt::Trait, // There is no difference between trait and inherent assoc item formatting - AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl { of_trait: false }), + AssocImplItem => visit::AssocCtxt::Impl { of_trait: false }, _ => unreachable!(), }; + let skip_span = ai.span; skip_out_of_file_lines_range_visitor!(self, ai.span); if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) { @@ -637,10 +642,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // TODO(calebcartwright): consider enabling box_patterns feature gate match (&ai.kind, visitor_kind) { - (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => { + (ast::AssocItemKind::Const(..), AssocTraitItem) => { self.visit_static(&StaticParts::from_trait_item(ai)) } - (ast::AssocItemKind::Const(..), AssocImplItem(_)) => { + (ast::AssocItemKind::Const(..), AssocImplItem) => { self.visit_static(&StaticParts::from_impl_item(ai)) } (ast::AssocItemKind::Fn(ref fn_kind), _) => { @@ -670,7 +675,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } (ast::AssocItemKind::Type(ref ty_alias), _) => { - self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span); + self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { self.visit_mac(mac, Some(ai.ident), MacroPosition::Item); @@ -680,11 +685,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { - self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti)); + self.visit_assoc_item(ti, ItemVisitorKind::AssocTraitItem); } pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { - self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii)); + self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem); } fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { From deed0f2480c507f7a3979ea814ade54685c5c45a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Mar 2025 17:28:45 +1100 Subject: [PATCH 229/333] Remove useless `Option` arg. `FmtVisitor::visit_mac` has an `Option` arg which is always either `None` or `Some(kw::Empty)`, because `ItemKind::MacCall` always has an empty ident. This value is passed through various functions until it reaches `rewrite_macro_name`, which treats `None` and `Some(kw::Empty)` the same. In other words, the argument is useless. This commit removes it. There is no change in behaviour. The commit also changes a few `symbol::Ident` occurrences to `Ident` in `macros.rs`; `Symbol` is imported in that file so `Ident` might as well be, too. (This is a good example of why it's a bad idea for `Itemt` to have an `ident` field when various item kinds don't have an identifier. It's easy to get confused when "empty identifier" is used to mean "no identifier". This will be fixed in a subsequent commit.) --- src/tools/rustfmt/src/expr.rs | 2 +- src/tools/rustfmt/src/items.rs | 2 +- src/tools/rustfmt/src/macros.rs | 34 +++++++------------------------ src/tools/rustfmt/src/patterns.rs | 4 +--- src/tools/rustfmt/src/types.rs | 2 +- src/tools/rustfmt/src/visitor.rs | 10 ++++----- 6 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index e866f13efc73e..65120770edd61 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -246,7 +246,7 @@ pub(crate) fn format_expr( | ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { + rewrite_macro(mac, context, shape, MacroPosition::Expression).or_else(|_| { wrap_str( context.snippet(expr.span).to_owned(), context.config.max_width(), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 415b83060b85c..fdda885b7298d 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3508,7 +3508,7 @@ impl Rewrite for ast::ForeignItem { ) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item) + rewrite_macro(mac, context, shape, MacroPosition::Item) } }?; diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index e239ff47c043e..ddf3d2ce96af6 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -16,10 +16,7 @@ use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; -use rustc_span::{ - BytePos, DUMMY_SP, Span, Symbol, - symbol::{self, kw}, -}; +use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol}; use tracing::debug; use crate::comment::{ @@ -60,7 +57,7 @@ pub(crate) enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), - Keyword(symbol::Ident, Span), + Keyword(Ident, Span), } impl MacroArg { @@ -103,20 +100,12 @@ impl Rewrite for MacroArg { } /// Rewrite macro name without using pretty-printer if possible. -fn rewrite_macro_name( - context: &RewriteContext<'_>, - path: &ast::Path, - extra_ident: Option, -) -> String { - let name = if path.segments.len() == 1 { +fn rewrite_macro_name(context: &RewriteContext<'_>, path: &ast::Path) -> String { + if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. format!("{}!", rewrite_ident(context, path.segments[0].ident)) } else { format!("{}!", pprust::path_to_string(path)) - }; - match extra_ident { - Some(ident) if ident.name != kw::Empty => format!("{name} {ident}"), - _ => name, } } @@ -165,7 +154,6 @@ fn return_macro_parse_failure_fallback( pub(crate) fn rewrite_macro( mac: &ast::MacCall, - extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -179,14 +167,7 @@ pub(crate) fn rewrite_macro( } else { let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { - rewrite_macro_inner( - mac, - extra_ident, - context, - shape, - position, - guard.is_nested(), - ) + rewrite_macro_inner(mac, context, shape, position, guard.is_nested()) })); match result { Err(..) => { @@ -207,7 +188,6 @@ pub(crate) fn rewrite_macro( fn rewrite_macro_inner( mac: &ast::MacCall, - extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -222,7 +202,7 @@ fn rewrite_macro_inner( let original_style = macro_style(mac, context); - let macro_name = rewrite_macro_name(context, &mac.path, extra_ident); + let macro_name = rewrite_macro_name(context, &mac.path); let is_forced_bracket = FORCED_BRACKET_MACROS.contains(&¯o_name[..]); let style = if is_forced_bracket && !is_nested_macro { @@ -432,7 +412,7 @@ pub(crate) fn rewrite_macro_def( shape: Shape, indent: Indent, def: &ast::MacroDef, - ident: symbol::Ident, + ident: Ident, vis: &ast::Visibility, span: Span, ) -> RewriteResult { diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index bafed41e39f42..8dc9457450326 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -307,9 +307,7 @@ impl Rewrite for Pat { context, shape, ), - PatKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Pat) - } + PatKind::MacCall(ref mac) => rewrite_macro(mac, context, shape, MacroPosition::Pat), PatKind::Paren(ref pat) => pat .rewrite_result( context, diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 06a67334086c5..75a5a8532b84f 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1018,7 +1018,7 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + rewrite_macro(mac, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Ok(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c70649cc81259..c73976d90b1e6 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -172,7 +172,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { get_span_without_attrs(stmt.as_ast_node()), ); } else { - self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement); + self.visit_mac(&mac_stmt.mac, MacroPosition::Statement); } self.format_missing(stmt.span().hi()); } @@ -531,7 +531,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { - self.visit_mac(mac, Some(item.ident), MacroPosition::Item); + self.visit_mac(mac, MacroPosition::Item); } ast::ItemKind::ForeignMod(ref foreign_mod) => { self.format_missing_with_indent(source!(self, item.span).lo()); @@ -678,7 +678,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { - self.visit_mac(mac, Some(ai.ident), MacroPosition::Item); + self.visit_mac(mac, MacroPosition::Item); } _ => unreachable!(), } @@ -692,12 +692,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_assoc_item(ii, ItemVisitorKind::AssocImplItem); } - fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; let shape = self.shape().saturating_sub_width(1); - let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok()); + let rewrite = self.with_context(|ctx| rewrite_macro(mac, ctx, shape, pos).ok()); // As of v638 of the rustc-ap-* crates, the associated span no longer includes // the trailing semicolon. This determines the correct span to ensure scenarios // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) From 43018eacb61da96b718f70b7719bf5e51207df61 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 15:25:30 +1100 Subject: [PATCH 230/333] Ignore `#[test_case]` on anything other than `fn`/`const`/`static`. `expand_test_case` looks for any item with a `#[test_case]` attribute and adds a `test_path_symbol` attribute to it while also fiddling with the item's ident's span. This is pretty weird, because `#[test_case]` is only valid on `fn`/`const`/`static` items, as far as I can tell. But you don't currently get an error or warning if you use it on other kinds of items. This commit changes things so that a `#[test_case]` item is modified only if it is `fn`/`const`/`static`. This is relevant for moving idents from `Item` to `ItemKind`, because some item kinds don't have an ident, e.g. `impl` blocks. The commit also does the following. - Renames a local variable `test_id` as `test_ident`. - Changes a `const` to `static` in `tests/ui/custom_test_frameworks/full.rs` to give the `static` case some test coverage. - Adds a `struct` and `impl` to the same test to give some test coverage to the non-affected item kinds. These have a `FIXME` comment identifying the weirdness here. Hopefully this will be useful breadcrumbs for somebody else in the future. --- compiler/rustc_builtin_macros/src/test.rs | 46 +++++++++++++---------- tests/ui/custom_test_frameworks/full.rs | 14 ++++++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 239f8657284d5..db3e431495bf7 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -51,21 +51,26 @@ pub(crate) fn expand_test_case( return vec![]; } }; - item = item.map(|mut item| { - let test_path_symbol = Symbol::intern(&item_path( - // skip the name of the root module - &ecx.current_expansion.module.mod_path[1..], - &item.ident, - )); - item.vis = ast::Visibility { - span: item.vis.span, - kind: ast::VisibilityKind::Public, - tokens: None, - }; - item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); - item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); - item - }); + + // `#[test_case]` is valid on functions, consts, and statics. Only modify + // the item in those cases. + match &mut item.kind { + ast::ItemKind::Fn(_) | ast::ItemKind::Const(_) | ast::ItemKind::Static(_) => { + item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); + let test_path_symbol = Symbol::intern(&item_path( + // skip the name of the root module + &ecx.current_expansion.module.mod_path[1..], + &item.ident, + )); + item.vis = ast::Visibility { + span: item.vis.span, + kind: ast::VisibilityKind::Public, + tokens: None, + }; + item.attrs.push(ecx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, sp)); + } + _ => {} + } let ret = if is_stmt { Annotatable::Stmt(P(ecx.stmt_item(item.span, item))) @@ -162,17 +167,17 @@ pub(crate) fn expand_test_or_bench( let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span()); let attr_sp = cx.with_def_site_ctxt(attr_sp); - let test_id = Ident::new(sym::test, attr_sp); + let test_ident = Ident::new(sym::test, attr_sp); // creates test::$name - let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]); + let test_path = |name| cx.path(ret_ty_sp, vec![test_ident, Ident::from_str_and_span(name, sp)]); // creates test::ShouldPanic::$name let should_panic_path = |name| { cx.path( sp, vec![ - test_id, + test_ident, Ident::from_str_and_span("ShouldPanic", sp), Ident::from_str_and_span(name, sp), ], @@ -184,7 +189,7 @@ pub(crate) fn expand_test_or_bench( cx.path( sp, vec![ - test_id, + test_ident, Ident::from_str_and_span("TestType", sp), Ident::from_str_and_span(name, sp), ], @@ -380,7 +385,8 @@ pub(crate) fn expand_test_or_bench( }); // extern crate test - let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + let test_extern = + cx.item(sp, test_ident, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs index 289767b1f698a..6be29f0418d61 100644 --- a/tests/ui/custom_test_frameworks/full.rs +++ b/tests/ui/custom_test_frameworks/full.rs @@ -25,4 +25,16 @@ impl example_runner::Testable for IsFoo { const TEST_1: IsFoo = IsFoo("hello"); #[test_case] -const TEST_2: IsFoo = IsFoo("foo"); +static TEST_2: IsFoo = IsFoo("foo"); + +// FIXME: `test_case` is currently ignored on anything other than +// fn/const/static. Should this be a warning/error? +#[test_case] +struct _S; + +// FIXME: `test_case` is currently ignored on anything other than +// fn/const/static. Should this be a warning/error? +#[test_case] +impl _S { + fn _f() {} +} From df247968f267d30fb8b048c21f595f2293d8ff62 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Mar 2025 09:47:43 +1100 Subject: [PATCH 231/333] Move `ast::Item::ident` into `ast::ItemKind`. `ast::Item` has an `ident` field. - It's always non-empty for these item kinds: `ExternCrate`, `Static`, `Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`, `Trait`, `TraitAlias`, `MacroDef`, `Delegation`. - It's always empty for these item kinds: `Use`, `ForeignMod`, `GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`. There is a similar story for `AssocItemKind` and `ForeignItemKind`. Some sites that handle items check for an empty ident, some don't. This is a very C-like way of doing things, but this is Rust, we have sum types, we can do this properly and never forget to check for the exceptional case and never YOLO possibly empty identifiers (or possibly dummy spans) around and hope that things will work out. The commit is large but it's mostly obvious plumbing work. Some notable things. - `ast::Item` got 8 bytes bigger. This could be avoided by boxing the fields within some of the `ast::ItemKind` variants (specifically: `Struct`, `Union`, `Enum`). I might do that in a follow-up; this commit is big enough already. - For the visitors: `FnKind` no longer needs an `ident` field because the `Fn` within how has one. - In the parser, the `ItemInfo` typedef is no longer needed. It was used in various places to return an `Ident` alongside an `ItemKind`, but now the `Ident` (if present) is within the `ItemKind`. - In a few places I renamed identifier variables called `name` (or `foo_name`) as `ident` (or `foo_ident`), to better match the type, and because `name` is normally used for `Symbol`s. It's confusing to see something like `foo_name.name`. --- compiler/rustc_ast/src/ast.rs | 107 ++++-- compiler/rustc_ast/src/mut_visit.rs | 84 +++-- compiler/rustc_ast/src/visit.rs | 87 +++-- compiler/rustc_ast_lowering/src/delegation.rs | 8 +- compiler/rustc_ast_lowering/src/item.rs | 353 ++++++++++-------- .../rustc_ast_passes/src/ast_validation.rs | 83 ++-- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 83 ++-- .../src/alloc_error_handler.rs | 11 +- compiler/rustc_builtin_macros/src/asm.rs | 3 +- .../src/assert/context.rs | 1 - compiler/rustc_builtin_macros/src/autodiff.rs | 28 +- .../src/deriving/clone.rs | 4 +- .../src/deriving/cmp/partial_ord.rs | 2 +- .../src/deriving/coerce_pointee.rs | 6 +- .../src/deriving/generic/mod.rs | 17 +- .../src/global_allocator.rs | 20 +- .../src/proc_macro_harness.rs | 41 +- .../src/standard_library_imports.rs | 4 +- compiler/rustc_builtin_macros/src/test.rs | 24 +- .../rustc_builtin_macros/src/test_harness.rs | 46 +-- compiler/rustc_expand/src/base.rs | 7 +- compiler/rustc_expand/src/build.rs | 17 +- compiler/rustc_expand/src/expand.rs | 13 +- compiler/rustc_expand/src/placeholders.rs | 7 +- compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_lint/src/nonstandard_style.rs | 22 +- compiler/rustc_metadata/src/creader.rs | 12 +- compiler/rustc_parse/src/parser/item.rs | 201 +++++----- compiler/rustc_parse/src/parser/tests.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 14 +- .../rustc_resolve/src/build_reduced_graph.rs | 81 ++-- compiler/rustc_resolve/src/check_unused.rs | 4 +- compiler/rustc_resolve/src/def_collector.rs | 33 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- .../src/effective_visibilities.rs | 4 +- compiler/rustc_resolve/src/late.rs | 68 ++-- .../rustc_resolve/src/late/diagnostics.rs | 56 +-- src/librustdoc/doctest/make.rs | 8 +- .../clippy_lints/src/crate_in_macro_def.rs | 2 +- .../src/doc/needless_doctest_main.rs | 16 +- .../clippy/clippy_lints/src/duplicate_mod.rs | 2 +- .../clippy_lints/src/empty_line_after.rs | 16 +- .../clippy_lints/src/empty_with_brackets.rs | 5 +- .../src/field_scoped_visibility_modifiers.rs | 2 +- .../src/multiple_bound_locations.rs | 2 +- .../clippy_lints/src/partial_pub_fields.rs | 2 +- .../src/single_component_path_imports.rs | 6 +- .../clippy/clippy_utils/src/ast_utils/mod.rs | 79 +++- src/tools/rustfmt/src/items.rs | 78 ++-- src/tools/rustfmt/src/modules.rs | 10 +- src/tools/rustfmt/src/reorder.rs | 17 +- src/tools/rustfmt/src/visitor.rs | 52 +-- tests/ui/stats/input-stats.stderr | 78 ++-- 54 files changed, 1072 insertions(+), 864 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 064f05ef1f3ef..33c20602dfd23 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3303,9 +3303,6 @@ pub struct Item { pub id: NodeId, pub span: Span, pub vis: Visibility, - /// The name of the item. - /// It might be a dummy name in case of anonymous items. - pub ident: Ident, pub kind: K, @@ -3327,23 +3324,23 @@ impl Item { pub fn opt_generics(&self) -> Option<&Generics> { match &self.kind { - ItemKind::ExternCrate(_) + ItemKind::ExternCrate(..) | ItemKind::Use(_) - | ItemKind::Mod(_, _) + | ItemKind::Mod(..) | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) | ItemKind::MacCall(_) | ItemKind::Delegation(_) | ItemKind::DelegationMac(_) - | ItemKind::MacroDef(_) => None, + | ItemKind::MacroDef(..) => None, ItemKind::Static(_) => None, ItemKind::Const(i) => Some(&i.generics), ItemKind::Fn(i) => Some(&i.generics), ItemKind::TyAlias(i) => Some(&i.generics), - ItemKind::TraitAlias(generics, _) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) => Some(&generics), + ItemKind::TraitAlias(_, generics, _) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) => Some(&generics), ItemKind::Trait(i) => Some(&i.generics), ItemKind::Impl(i) => Some(&i.generics), } @@ -3420,6 +3417,7 @@ impl Default for FnHeader { pub struct Trait { pub safety: Safety, pub is_auto: IsAuto, + pub ident: Ident, pub generics: Generics, pub bounds: GenericBounds, pub items: ThinVec>, @@ -3465,6 +3463,7 @@ pub struct TyAliasWhereClauses { #[derive(Clone, Encodable, Decodable, Debug)] pub struct TyAlias { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub where_clauses: TyAliasWhereClauses, pub bounds: GenericBounds, @@ -3493,6 +3492,7 @@ pub struct FnContract { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Fn { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub sig: FnSig, pub contract: Option>, @@ -3506,6 +3506,7 @@ pub struct Delegation { pub id: NodeId, pub qself: Option>, pub path: Path, + pub ident: Ident, pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. @@ -3523,6 +3524,7 @@ pub struct DelegationMac { #[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticItem { + pub ident: Ident, pub ty: P, pub safety: Safety, pub mutability: Mutability, @@ -3533,6 +3535,7 @@ pub struct StaticItem { #[derive(Clone, Encodable, Decodable, Debug)] pub struct ConstItem { pub defaultness: Defaultness, + pub ident: Ident, pub generics: Generics, pub ty: P, pub expr: Option>, @@ -3545,7 +3548,7 @@ pub enum ItemKind { /// An `extern crate` item, with the optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. - ExternCrate(Option), + ExternCrate(Option, Ident), /// A use declaration item (`use`). /// /// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`. @@ -3567,7 +3570,7 @@ pub enum ItemKind { /// E.g., `mod foo;` or `mod foo { .. }`. /// `unsafe` keyword on modules is accepted syntactically for macro DSLs, but not /// semantically by Rust. - Mod(Safety, ModKind), + Mod(Safety, Ident, ModKind), /// An external module (`extern`). /// /// E.g., `extern {}` or `extern "C" {}`. @@ -3581,15 +3584,15 @@ pub enum ItemKind { /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. - Enum(EnumDef, Generics), + Enum(Ident, EnumDef, Generics), /// A struct definition (`struct`). /// /// E.g., `struct Foo { x: A }`. - Struct(VariantData, Generics), + Struct(Ident, VariantData, Generics), /// A union definition (`union`). /// /// E.g., `union Foo { x: A, y: B }`. - Union(VariantData, Generics), + Union(Ident, VariantData, Generics), /// A trait declaration (`trait`). /// /// E.g., `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}`. @@ -3597,7 +3600,7 @@ pub enum ItemKind { /// Trait alias. /// /// E.g., `trait Foo = Bar + Quux;`. - TraitAlias(Generics, GenericBounds), + TraitAlias(Ident, Generics, GenericBounds), /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. @@ -3608,7 +3611,7 @@ pub enum ItemKind { MacCall(P), /// A macro definition. - MacroDef(MacroDef), + MacroDef(Ident, MacroDef), /// A single delegation item (`reuse`). /// @@ -3620,6 +3623,31 @@ pub enum ItemKind { } impl ItemKind { + pub fn ident(&self) -> Option { + match *self { + ItemKind::ExternCrate(_, ident) + | ItemKind::Static(box StaticItem { ident, .. }) + | ItemKind::Const(box ConstItem { ident, .. }) + | ItemKind::Fn(box Fn { ident, .. }) + | ItemKind::Mod(_, ident, _) + | ItemKind::TyAlias(box TyAlias { ident, .. }) + | ItemKind::Enum(ident, ..) + | ItemKind::Struct(ident, ..) + | ItemKind::Union(ident, ..) + | ItemKind::Trait(box Trait { ident, .. }) + | ItemKind::TraitAlias(ident, ..) + | ItemKind::MacroDef(ident, _) + | ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), + + ItemKind::Use(_) + | ItemKind::ForeignMod(_) + | ItemKind::GlobalAsm(_) + | ItemKind::Impl(_) + | ItemKind::MacCall(_) + | ItemKind::DelegationMac(_) => None, + } + } + /// "a" or "an" pub fn article(&self) -> &'static str { use ItemKind::*; @@ -3660,11 +3688,11 @@ impl ItemKind { Self::Fn(box Fn { generics, .. }) | Self::TyAlias(box TyAlias { generics, .. }) | Self::Const(box ConstItem { generics, .. }) - | Self::Enum(_, generics) - | Self::Struct(_, generics) - | Self::Union(_, generics) + | Self::Enum(_, _, generics) + | Self::Struct(_, _, generics) + | Self::Union(_, _, generics) | Self::Trait(box Trait { generics, .. }) - | Self::TraitAlias(generics, _) + | Self::TraitAlias(_, generics, _) | Self::Impl(box Impl { generics, .. }) => Some(generics), _ => None, } @@ -3700,6 +3728,17 @@ pub enum AssocItemKind { } impl AssocItemKind { + pub fn ident(&self) -> Option { + match *self { + AssocItemKind::Const(box ConstItem { ident, .. }) + | AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Type(box TyAlias { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident), + + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None, + } + } + pub fn defaultness(&self) -> Defaultness { match *self { Self::Const(box ConstItem { defaultness, .. }) @@ -3746,14 +3785,26 @@ impl TryFrom for AssocItemKind { pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). Static(Box), - /// An foreign function. + /// A foreign function. Fn(Box), - /// An foreign type. + /// A foreign type. TyAlias(Box), /// A macro expanding to foreign items. MacCall(P), } +impl ForeignItemKind { + pub fn ident(&self) -> Option { + match *self { + ForeignItemKind::Static(box StaticItem { ident, .. }) + | ForeignItemKind::Fn(box Fn { ident, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => Some(ident), + + ForeignItemKind::MacCall(_) => None, + } + } +} + impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { @@ -3790,21 +3841,21 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(AssocItem, 88); + static_assert_size!(AssocItem, 80); static_assert_size!(AssocItemKind, 16); static_assert_size!(Attribute, 32); static_assert_size!(Block, 32); static_assert_size!(Expr, 72); static_assert_size!(ExprKind, 40); - static_assert_size!(Fn, 176); - static_assert_size!(ForeignItem, 88); + static_assert_size!(Fn, 184); + static_assert_size!(ForeignItem, 80); static_assert_size!(ForeignItemKind, 16); static_assert_size!(GenericArg, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); - static_assert_size!(Item, 136); - static_assert_size!(ItemKind, 64); + static_assert_size!(Item, 144); + static_assert_size!(ItemKind, 80); static_assert_size!(LitKind, 24); static_assert_size!(Local, 80); static_assert_size!(MetaItemLit, 40); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 274fe312f7fad..30af6d910bfa2 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -41,7 +41,6 @@ pub trait WalkItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, @@ -963,10 +962,10 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { match kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { defaultness, + ident, generics, contract, body, @@ -974,8 +973,9 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { define_opaque, }, ) => { - // Identifier and visibility are visited as a part of the item. + // Visibility is visited as a part of the item. visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_fn_header(header); vis.visit_generics(generics); vis.visit_fn_decl(decl); @@ -1233,12 +1233,11 @@ pub fn walk_item_kind( kind: &mut K, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: K::Ctxt, vis: &mut impl MutVisitor, ) { - kind.walk(span, id, ident, visibility, ctxt, vis) + kind.walk(span, id, visibility, ctxt, vis) } impl WalkItemKind for ItemKind { @@ -1247,21 +1246,22 @@ impl WalkItemKind for ItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, _ctxt: Self::Ctxt, vis: &mut impl MutVisitor, ) { match self { - ItemKind::ExternCrate(_orig_name) => {} + ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, expr, define_opaque, }) => { + vis.visit_ident(ident); vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); walk_define_opaques(vis, define_opaque); @@ -1270,10 +1270,11 @@ impl WalkItemKind for ItemKind { walk_const_item(vis, item); } ItemKind::Fn(func) => { - vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id); + vis.visit_fn(FnKind::Fn(FnCtxt::Free, visibility, &mut *func), span, id); } - ItemKind::Mod(safety, mod_kind) => { + ItemKind::Mod(safety, ident, mod_kind) => { visit_safety(vis, safety); + vis.visit_ident(ident); match mod_kind { ModKind::Loaded( items, @@ -1290,18 +1291,29 @@ impl WalkItemKind for ItemKind { } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), - ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => { + ItemKind::TyAlias(box TyAlias { + defaultness, + ident, + generics, + where_clauses, + bounds, + ty, + }) => { visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); visit_opt(ty, |ty| vis.visit_ty(ty)); walk_ty_alias_where_clauses(vis, where_clauses); } - ItemKind::Enum(EnumDef { variants }, generics) => { + ItemKind::Enum(ident, EnumDef { variants }, generics) => { + vis.visit_ident(ident); vis.visit_generics(generics); variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); } - ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => { + ItemKind::Struct(ident, variant_data, generics) + | ItemKind::Union(ident, variant_data, generics) => { + vis.visit_ident(ident); vis.visit_generics(generics); vis.visit_variant_data(variant_data); } @@ -1326,22 +1338,28 @@ impl WalkItemKind for ItemKind { vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() }) }); } - ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => { + ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => { visit_safety(vis, safety); + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Trait)); } - ItemKind::TraitAlias(generics, bounds) => { + ItemKind::TraitAlias(ident, generics, bounds) => { + vis.visit_ident(ident); vis.visit_generics(generics); visit_bounds(vis, bounds, BoundKind::Bound); } ItemKind::MacCall(m) => vis.visit_mac_call(m), - ItemKind::MacroDef(def) => vis.visit_macro_def(def), + ItemKind::MacroDef(ident, def) => { + vis.visit_ident(ident); + vis.visit_macro_def(def) + } ItemKind::Delegation(box Delegation { id, qself, path, + ident, rename, body, from_glob: _, @@ -1349,6 +1367,7 @@ impl WalkItemKind for ItemKind { vis.visit_id(id); vis.visit_qself(qself); vis.visit_path(path); + vis.visit_ident(ident); if let Some(rename) = rename { vis.visit_ident(rename); } @@ -1381,7 +1400,6 @@ impl WalkItemKind for AssocItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, @@ -1391,20 +1409,18 @@ impl WalkItemKind for AssocItemKind { walk_const_item(visitor, item); } AssocItemKind::Fn(func) => { - visitor.visit_fn( - FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func), - span, - id, - ); + visitor.visit_fn(FnKind::Fn(FnCtxt::Assoc(ctxt), visibility, &mut *func), span, id); } AssocItemKind::Type(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { visit_defaultness(visitor, defaultness); + visitor.visit_ident(ident); visitor.visit_generics(generics); visit_bounds(visitor, bounds, BoundKind::Bound); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1415,6 +1431,7 @@ impl WalkItemKind for AssocItemKind { id, qself, path, + ident, rename, body, from_glob: _, @@ -1422,6 +1439,7 @@ impl WalkItemKind for AssocItemKind { visitor.visit_id(id); visitor.visit_qself(qself); visitor.visit_path(path); + visitor.visit_ident(ident); if let Some(rename) = rename { visitor.visit_ident(rename); } @@ -1449,8 +1467,9 @@ impl WalkItemKind for AssocItemKind { } fn walk_const_item(vis: &mut T, item: &mut ConstItem) { - let ConstItem { defaultness, generics, ty, expr, define_opaque } = item; + let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; visit_defaultness(vis, defaultness); + vis.visit_ident(ident); vis.visit_generics(generics); vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); @@ -1487,12 +1506,11 @@ fn walk_item_ctxt( item: &mut P>, ctxt: K::Ctxt, ) { - let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut(); + let Item { attrs, id, kind, vis, span, tokens } = item.deref_mut(); visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); - visitor.visit_ident(ident); - kind.walk(*span, *id, ident, vis, ctxt, visitor); + kind.walk(*span, *id, vis, ctxt, visitor); visit_lazy_tts(visitor, tokens); visitor.visit_span(span); } @@ -1525,38 +1543,37 @@ impl WalkItemKind for ForeignItemKind { &mut self, span: Span, id: NodeId, - ident: &mut Ident, visibility: &mut Visibility, _ctxt: Self::Ctxt, visitor: &mut impl MutVisitor, ) { match self { ForeignItemKind::Static(box StaticItem { + ident, ty, mutability: _, expr, safety: _, define_opaque, }) => { + visitor.visit_ident(ident); visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); walk_define_opaques(visitor, define_opaque); } ForeignItemKind::Fn(func) => { - visitor.visit_fn( - FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func), - span, - id, - ); + visitor.visit_fn(FnKind::Fn(FnCtxt::Foreign, visibility, &mut *func), span, id); } ForeignItemKind::TyAlias(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { visit_defaultness(visitor, defaultness); + visitor.visit_ident(ident); visitor.visit_generics(generics); visit_bounds(visitor, bounds, BoundKind::Bound); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1984,8 +2001,7 @@ impl DummyAstNode for Item { span: Default::default(), tokens: Default::default(), }, - ident: Ident::dummy(), - kind: ItemKind::ExternCrate(None), + kind: ItemKind::ExternCrate(None, Ident::dummy()), tokens: Default::default(), } } @@ -2052,7 +2068,7 @@ impl DummyAstNode for crate::ast_traits::AstNo #[derive(Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn), + Fn(FnCtxt, &'a mut Visibility, &'a mut Fn), /// E.g., `|x, y| body`. Closure( diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2716601ca4f9d..1ef92ff8898ef 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -66,7 +66,7 @@ impl BoundKind { #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn), + Fn(FnCtxt, &'a Visibility, &'a Fn), /// E.g., `|x, y| body`. Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), @@ -75,21 +75,21 @@ pub enum FnKind<'a> { impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { - FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header), + FnKind::Fn(_, _, Fn { sig, .. }) => Some(&sig.header), FnKind::Closure(..) => None, } } pub fn ident(&self) -> Option<&Ident> { match self { - FnKind::Fn(_, ident, ..) => Some(ident), + FnKind::Fn(_, _, Fn { ident, .. }) => Some(ident), _ => None, } } pub fn decl(&self) -> &'a FnDecl { match self { - FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl, + FnKind::Fn(_, _, Fn { sig, .. }) => &sig.decl, FnKind::Closure(_, _, decl, _) => decl, } } @@ -118,7 +118,6 @@ pub trait WalkItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, visibility: &'a Visibility, ctxt: Self::Ctxt, visitor: &mut V, @@ -364,63 +363,72 @@ impl WalkItemKind for ItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { match self { - ItemKind::ExternCrate(_rename) => {} + ItemKind::ExternCrate(_rename, ident) => try_visit!(visitor.visit_ident(ident)), ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ItemKind::Const(box ConstItem { defaultness: _, + ident, generics, ty, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Free, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } - ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { - ModKind::Loaded(items, _inline, _inner_span, _) => { - walk_list!(visitor, visit_item, items); + ItemKind::Mod(_unsafety, ident, mod_kind) => { + try_visit!(visitor.visit_ident(ident)); + match mod_kind { + ModKind::Loaded(items, _inline, _inner_span, _) => { + walk_list!(visitor, visit_item, items); + } + ModKind::Unloaded => {} } - ModKind::Unloaded => {} - }, + } ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => { walk_list!(visitor, visit_foreign_item, items); } ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), ItemKind::TyAlias(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); } - ItemKind::Enum(enum_definition, generics) => { + ItemKind::Enum(ident, enum_definition, generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_enum_def(enum_definition)); } @@ -444,32 +452,47 @@ impl WalkItemKind for ItemKind { AssocCtxt::Impl { of_trait: of_trait.is_some() } ); } - ItemKind::Struct(struct_definition, generics) - | ItemKind::Union(struct_definition, generics) => { + ItemKind::Struct(ident, struct_definition, generics) + | ItemKind::Union(ident, struct_definition, generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => { + ItemKind::Trait(box Trait { + safety: _, + is_auto: _, + ident, + generics, + bounds, + items, + }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait); } - ItemKind::TraitAlias(generics, bounds) => { + ItemKind::TraitAlias(ident, generics, bounds) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)), + ItemKind::MacroDef(ident, ts) => { + try_visit!(visitor.visit_ident(ident)); + try_visit!(visitor.visit_mac_def(ts, id)) + } ItemKind::Delegation(box Delegation { id, qself, path, + ident, rename, body, from_glob: _, }) => { try_visit!(visitor.visit_qself(qself)); try_visit!(visitor.visit_path(path, *id)); + try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_ident, rename); visit_opt!(visitor, visit_block, body); } @@ -743,34 +766,37 @@ impl WalkItemKind for ForeignItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { match self { ForeignItemKind::Static(box StaticItem { + ident, ty, mutability: _, expr, safety: _, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } ForeignItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Foreign, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); @@ -917,10 +943,10 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu match kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { defaultness: _, + ident, sig: FnSig { header, decl, span: _ }, generics, contract, @@ -928,7 +954,8 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu define_opaque, }, ) => { - // Identifier and visibility are visited as a part of the item. + // Visibility is visited as a part of the item. + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_fn_header(header)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(decl)); @@ -952,7 +979,6 @@ impl WalkItemKind for AssocItemKind { &'a self, span: Span, id: NodeId, - ident: &'a Ident, vis: &'a Visibility, ctxt: Self::Ctxt, visitor: &mut V, @@ -960,28 +986,32 @@ impl WalkItemKind for AssocItemKind { match self { AssocItemKind::Const(box ConstItem { defaultness: _, + ident, generics, ty, expr, define_opaque, }) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); try_visit!(walk_define_opaques(visitor, define_opaque)); } AssocItemKind::Fn(func) => { - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { generics, + ident, bounds, ty, defaultness: _, where_clauses: _, }) => { try_visit!(visitor.visit_generics(generics)); + try_visit!(visitor.visit_ident(ident)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); } @@ -992,12 +1022,14 @@ impl WalkItemKind for AssocItemKind { id, qself, path, + ident, rename, body, from_glob: _, }) => { try_visit!(visitor.visit_qself(qself)); try_visit!(visitor.visit_path(path, *id)); + try_visit!(visitor.visit_ident(ident)); visit_opt!(visitor, visit_ident, rename); visit_opt!(visitor, visit_block, body); } @@ -1039,11 +1071,10 @@ fn walk_item_ctxt<'a, V: Visitor<'a>, K: WalkItemKind>( item: &'a Item, ctxt: K::Ctxt, ) -> V::Result { - let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; + let Item { id, span, vis, attrs, kind, tokens: _ } = item; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); - try_visit!(visitor.visit_ident(ident)); - try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor)); + try_visit!(kind.walk(*span, *id, vis, ctxt, visitor)); V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index f7640c602d6fd..9899ee03a513a 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -56,6 +56,7 @@ use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { pub body_id: hir::BodyId, pub sig: hir::FnSig<'hir>, + pub ident: Ident, pub generics: &'hir hir::Generics<'hir>, } @@ -104,9 +105,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span); let sig = self.lower_delegation_sig(sig_id, decl, span); let body_id = self.lower_delegation_body(delegation, param_count, span); - + let ident = self.lower_ident(delegation.ident); let generics = self.lower_delegation_generics(span); - DelegationResults { body_id, sig, generics } + DelegationResults { body_id, sig, ident, generics } } Err(err) => self.generate_delegation_error(err, span), } @@ -405,8 +406,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.generate_header_error(); let sig = hir::FnSig { decl, header, span }; + let ident = Ident::dummy(); let body_id = self.lower_body(|this| (&[], this.mk_expr(hir::ExprKind::Err(err), span))); - DelegationResults { generics, body_id, sig } + DelegationResults { ident, generics, body_id, sig } } fn generate_header_error(&self) -> hir::FnHeader { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 43bf951eddc6c..28f596ac0926d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -107,7 +107,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } fn lower_foreign_item(&mut self, item: &ForeignItem) { - debug_assert_ne!(item.ident.name, kw::Empty); self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } @@ -151,7 +150,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), kind, @@ -166,41 +165,44 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, id: NodeId, hir_id: hir::HirId, - ident: Ident, attrs: &'hir [hir::Attribute], vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { match i { - ItemKind::ExternCrate(orig_name) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::ExternCrate(orig_name, ident) => { + let ident = self.lower_ident(*ident); hir::ItemKind::ExternCrate(*orig_name, ident) } ItemKind::Use(use_tree) => { - debug_assert_eq!(ident.name, kw::Empty); // Start with an empty prefix. let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None }; self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) } ItemKind::Static(box ast::StaticItem { + ident, ty: t, safety: _, mutability: m, expr: e, define_opaque, }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + let ident = self.lower_ident(*ident); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); self.lower_define_opaque(hir_id, define_opaque); hir::ItemKind::Static(ident, ty, *m, body_id) } - ItemKind::Const(box ast::ConstItem { generics, ty, expr, define_opaque, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Const(box ast::ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => { + let ident = self.lower_ident(*ident); let (generics, (ty, body_id)) = self.lower_generics( generics, id, @@ -214,13 +216,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } ItemKind::Fn(box Fn { sig: FnSig { decl, header, span: fn_sig_span }, + ident, generics, body, contract, define_opaque, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); self.with_new_scopes(*fn_sig_span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body @@ -248,7 +250,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: this.lower_span(*fn_sig_span), }; this.lower_define_opaque(hir_id, define_opaque); - let ident = this.lower_ident(ident); + let ident = this.lower_ident(*ident); hir::ItemKind::Fn { ident, sig, @@ -258,9 +260,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } }) } - ItemKind::Mod(_, mod_kind) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Mod(_, ident, mod_kind) => { + let ident = self.lower_ident(*ident); match mod_kind { ModKind::Loaded(items, _, spans, _) => { hir::ItemKind::Mod(ident, self.lower_mod(items, spans)) @@ -268,24 +269,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), } } - ItemKind::ForeignMod(fm) => { - debug_assert_eq!(ident.name, kw::Empty); - hir::ItemKind::ForeignMod { - abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), - items: self - .arena - .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), - } - } + ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod { + abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), + items: self + .arena + .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), + }, ItemKind::GlobalAsm(asm) => { - debug_assert_eq!(ident.name, kw::Empty); let asm = self.lower_inline_asm(span, asm); let fake_body = self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); hir::ItemKind::GlobalAsm { asm, fake_body } } - ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { - debug_assert_ne!(ident.name, kw::Empty); + ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => { // We lower // // type Foo = impl Trait @@ -294,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // type Foo = Foo1 // opaque type Foo1: Trait - let ident = self.lower_ident(ident); + let ident = self.lower_ident(*ident); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( @@ -322,9 +318,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TyAlias(ident, ty, generics) } - ItemKind::Enum(enum_definition, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Enum(ident, enum_definition, generics) => { + let ident = self.lower_ident(*ident); let (generics, variants) = self.lower_generics( generics, id, @@ -337,9 +332,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics) } - ItemKind::Struct(struct_def, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Struct(ident, struct_def, generics) => { + let ident = self.lower_ident(*ident); let (generics, struct_def) = self.lower_generics( generics, id, @@ -348,9 +342,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Struct(ident, struct_def, generics) } - ItemKind::Union(vdata, generics) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Union(ident, vdata, generics) => { + let ident = self.lower_ident(*ident); let (generics, vdata) = self.lower_generics( generics, id, @@ -369,7 +362,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ty, items: impl_items, }) => { - debug_assert_eq!(ident.name, kw::Empty); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: // @@ -435,9 +427,8 @@ impl<'hir> LoweringContext<'_, 'hir> { items: new_impl_items, })) } - ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => { + let ident = self.lower_ident(*ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, id, @@ -456,9 +447,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items) } - ItemKind::TraitAlias(generics, bounds) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::TraitAlias(ident, generics, bounds) => { + let ident = self.lower_ident(*ident); let (generics, bounds) = self.lower_generics( generics, id, @@ -472,9 +462,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TraitAlias(ident, generics, bounds) } - ItemKind::MacroDef(MacroDef { body, macro_rules }) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); + ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => { + let ident = self.lower_ident(*ident); let body = P(self.lower_delim_args(body)); let def_id = self.local_def_id(id); let def_kind = self.tcx.def_kind(def_id); @@ -488,11 +477,9 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Macro(ident, macro_def, macro_kind) } ItemKind::Delegation(box delegation) => { - debug_assert_ne!(ident.name, kw::Empty); - let ident = self.lower_ident(ident); let delegation_results = self.lower_delegation(delegation, id, false); hir::ItemKind::Fn { - ident, + ident: delegation_results.ident, sig: delegation_results.sig, generics: delegation_results.generics, body: delegation_results.body_id, @@ -649,61 +636,64 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let owner_id = hir_id.expect_owner(); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let item = hir::ForeignItem { - owner_id, - ident: self.lower_ident(i.ident), - kind: match &i.kind { - ForeignItemKind::Fn(box Fn { sig, generics, define_opaque, .. }) => { - let fdec = &sig.decl; - let itctx = ImplTraitContext::Universal; - let (generics, (decl, fn_args)) = - self.lower_generics(generics, i.id, itctx, |this| { - ( - // Disallow `impl Trait` in foreign items. - this.lower_fn_decl( - fdec, - i.id, - sig.span, - FnDeclKind::ExternFn, - None, - ), - this.lower_fn_params_to_names(fdec), - ) - }); + let (ident, kind) = match &i.kind { + ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => { + let fdec = &sig.decl; + let itctx = ImplTraitContext::Universal; + let (generics, (decl, fn_args)) = + self.lower_generics(generics, i.id, itctx, |this| { + ( + // Disallow `impl Trait` in foreign items. + this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None), + this.lower_fn_params_to_names(fdec), + ) + }); - // Unmarked safety in unsafe block defaults to unsafe. - let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs); + // Unmarked safety in unsafe block defaults to unsafe. + let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs); - if define_opaque.is_some() { - self.dcx().span_err(i.span, "foreign functions cannot define opaque types"); - } + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign functions cannot define opaque types"); + } + ( + ident, hir::ForeignItemKind::Fn( hir::FnSig { header, decl, span: self.lower_span(sig.span) }, fn_args, generics, - ) - } - ForeignItemKind::Static(box StaticItem { - ty, - mutability, - expr: _, - safety, - define_opaque, - }) => { - let ty = self - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); - let safety = self.lower_safety(*safety, hir::Safety::Unsafe); - - if define_opaque.is_some() { - self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); - } + ), + ) + } + ForeignItemKind::Static(box StaticItem { + ident, + ty, + mutability, + expr: _, + safety, + define_opaque, + }) => { + let ty = + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + let safety = self.lower_safety(*safety, hir::Safety::Unsafe); - hir::ForeignItemKind::Static(ty, *mutability, safety) + // njn: where for this? + if define_opaque.is_some() { + self.dcx().span_err(i.span, "foreign statics cannot define opaque types"); } - ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, - ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), - }, + + (ident, hir::ForeignItemKind::Static(ty, *mutability, safety)) + } + ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => { + (ident, hir::ForeignItemKind::Type) + } + ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), + }; + + let item = hir::ForeignItem { + owner_id, + ident: self.lower_ident(*ident), + kind, vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), }; @@ -713,7 +703,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { id: hir::ForeignItemId { owner_id: self.owner_id(i.id) }, - ident: self.lower_ident(i.ident), + // `unwrap` is safe because `ForeignItemKind::MacCall` is the only foreign item kind + // without an identifier and it cannot reach here. + ident: self.lower_ident(i.kind.ident().unwrap()), span: self.lower_span(i.span), } } @@ -800,13 +792,19 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { - debug_assert_ne!(i.ident.name, kw::Empty); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let trait_item_def_id = hir_id.expect_owner(); - let (generics, kind, has_default) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => { + let (ident, generics, kind, has_default) = match &i.kind { + AssocItemKind::Const(box ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => { let (generics, kind) = self.lower_generics( generics, i.id, @@ -831,9 +829,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - (generics, kind, expr.is_some()) + (*ident, generics, kind, expr.is_some()) } - AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => { + AssocItemKind::Fn(box Fn { + sig, ident, generics, body: None, define_opaque, .. + }) => { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. let names = self.lower_fn_params_to_names(&sig.decl); @@ -851,10 +851,16 @@ impl<'hir> LoweringContext<'_, 'hir> { "only trait methods with default bodies can define opaque types", ); } - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) + ( + *ident, + generics, + hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), + false, + ) } AssocItemKind::Fn(box Fn { sig, + ident, generics, body: Some(body), contract, @@ -880,9 +886,16 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs, ); self.lower_define_opaque(hir_id, &define_opaque); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) + ( + *ident, + generics, + hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), + true, + ) } - AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => { + AssocItemKind::Type(box TyAlias { + ident, generics, where_clauses, bounds, ty, .. + }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); let (generics, kind) = self.lower_generics( @@ -905,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - (generics, kind, ty.is_some()) + (*ident, generics, kind, ty.is_some()) } AssocItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, i.id, false); @@ -913,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation_results.sig, hir::TraitFn::Provided(delegation_results.body_id), ); - (delegation_results.generics, item_kind, true) + (delegation.ident, delegation_results.generics, item_kind, true) } AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") @@ -922,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let item = hir::TraitItem { owner_id: trait_item_def_id, - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), generics, kind, span: self.lower_span(i.span), @@ -932,15 +945,20 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { - let kind = match &i.kind { - AssocItemKind::Const(..) => hir::AssocItemKind::Const, - AssocItemKind::Type(..) => hir::AssocItemKind::Type, - AssocItemKind::Fn(box Fn { sig, .. }) => { - hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } + let (ident, kind) = match &i.kind { + AssocItemKind::Const(box ConstItem { ident, .. }) => { + (*ident, hir::AssocItemKind::Const) } - AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { - has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false), - }, + AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, hir::AssocItemKind::Type), + AssocItemKind::Fn(box Fn { ident, sig, .. }) => { + (*ident, hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }) + } + AssocItemKind::Delegation(box delegation) => ( + delegation.ident, + hir::AssocItemKind::Fn { + has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false), + }, + ), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { panic!("macros should have been expanded by now") } @@ -948,7 +966,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let id = hir::TraitItemId { owner_id: self.owner_id(i.id) }; hir::TraitItemRef { id, - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), span: self.lower_span(i.span), kind, } @@ -964,16 +982,23 @@ impl<'hir> LoweringContext<'_, 'hir> { i: &AssocItem, is_in_trait_impl: bool, ) -> &'hir hir::ImplItem<'hir> { - debug_assert_ne!(i.ident.name, kw::Empty); // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let (generics, kind) = match &i.kind { - AssocItemKind::Const(box ConstItem { generics, ty, expr, define_opaque, .. }) => self - .lower_generics( + let (ident, (generics, kind)) = match &i.kind { + AssocItemKind::Const(box ConstItem { + ident, + generics, + ty, + expr, + define_opaque, + .. + }) => ( + *ident, + self.lower_generics( generics, i.id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -982,11 +1007,19 @@ impl<'hir> LoweringContext<'_, 'hir> { .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = this.lower_const_body(i.span, expr.as_deref()); this.lower_define_opaque(hir_id, &define_opaque); - hir::ImplItemKind::Const(ty, body) }, ), - AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => { + ), + AssocItemKind::Fn(box Fn { + sig, + ident, + generics, + body, + contract, + define_opaque, + .. + }) => { let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -1007,44 +1040,50 @@ impl<'hir> LoweringContext<'_, 'hir> { ); self.lower_define_opaque(hir_id, &define_opaque); - (generics, hir::ImplItemKind::Fn(sig, body_id)) + (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id))) } - AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => { + AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); - self.lower_generics( - &generics, - i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| match ty { - None => { - let guar = this.dcx().span_delayed_bug( - i.span, - "expected to lower associated type, but it was missing", - ); - let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))); - hir::ImplItemKind::Type(ty) - } - Some(ty) => { - let ty = this.lower_ty( - ty, - ImplTraitContext::OpaqueTy { - origin: hir::OpaqueTyOrigin::TyAlias { - parent: this.local_def_id(i.id), - in_assoc_ty: true, + ( + *ident, + self.lower_generics( + &generics, + i.id, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| match ty { + None => { + let guar = this.dcx().span_delayed_bug( + i.span, + "expected to lower associated type, but it was missing", + ); + let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))); + hir::ImplItemKind::Type(ty) + } + Some(ty) => { + let ty = this.lower_ty( + ty, + ImplTraitContext::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias { + parent: this.local_def_id(i.id), + in_assoc_ty: true, + }, }, - }, - ); - hir::ImplItemKind::Type(ty) - } - }, + ); + hir::ImplItemKind::Type(ty) + } + }, + ), ) } AssocItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl); ( - delegation_results.generics, - hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), + delegation.ident, + ( + delegation_results.generics, + hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), + ), ) } AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { @@ -1054,7 +1093,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let item = hir::ImplItem { owner_id: hir_id.expect_owner(), - ident: self.lower_ident(i.ident), + ident: self.lower_ident(ident), generics, kind, vis_span: self.lower_span(i.vis.span), @@ -1067,7 +1106,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef { hir::ImplItemRef { id: hir::ImplItemId { owner_id: self.owner_id(i.id) }, - ident: self.lower_ident(i.ident), + // `unwrap` is safe because `AssocItemKind::{MacCall,DelegationMac}` are the only + // assoc item kinds without an identifier and they cannot reach here. + ident: self.lower_ident(i.kind.ident().unwrap()), span: self.lower_span(i.span), kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index da739b0e4532b..86661f3f35905 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -607,7 +607,7 @@ impl<'a> AstValidator<'a> { fn deny_items(&self, trait_items: &[P], ident: Span) { if !trait_items.is_empty() { - let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); + let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect(); let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span); self.dcx().emit_err(errors::AutoTraitItems { spans, total, ident }); } @@ -818,7 +818,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if attr::contains_name(&item.attrs, sym::no_mangle) { - self.check_nomangle_item_asciionly(item.ident, item.span); + if let Some(ident) = item.kind.ident() { + self.check_nomangle_item_asciionly(ident, item.span); + } } match &item.kind { @@ -852,7 +854,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } this.visit_vis(&item.vis); - this.visit_ident(&item.ident); let disallowed = matches!(constness, Const::No) .then(|| TildeConstReason::TraitImpl { span: item.span }); this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); @@ -906,7 +907,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } this.visit_vis(&item.vis); - this.visit_ident(&item.ident); this.with_tilde_const( Some(TildeConstReason::Impl { span: item.span }), |this| this.visit_generics(generics), @@ -918,8 +918,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { return; // Avoid visiting again. } ItemKind::Fn( - func - @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ }, + func @ box Fn { + defaultness, + ident, + generics: _, + sig, + contract: _, + body, + define_opaque: _, + }, ) => { self.check_defaultness(item.span, *defaultness); @@ -949,8 +956,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func); + self.visit_ident(ident); + let kind = FnKind::Fn(FnCtxt::Free, &item.vis, &*func); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -986,7 +993,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); return; // Avoid visiting again. } - ItemKind::Enum(def, _) => { + ItemKind::Enum(_, def, _) => { for variant in &def.variants { self.visibility_not_permitted( &variant.vis, @@ -1000,22 +1007,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => { + ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => { let is_const_trait = attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); self.with_in_trait(item.span, is_const_trait, |this| { if *is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. - this.deny_generic_params(generics, item.ident.span); - this.deny_super_traits(bounds, item.ident.span); - this.deny_where_clause(&generics.where_clause, item.ident.span); - this.deny_items(items, item.ident.span); + this.deny_generic_params(generics, ident.span); + this.deny_super_traits(bounds, ident.span); + this.deny_where_clause(&generics.where_clause, ident.span); + this.deny_items(items, ident.span); } // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound // context for the supertraits. this.visit_vis(&item.vis); - this.visit_ident(&item.ident); + this.visit_ident(ident); let disallowed = is_const_trait .is_none() .then(|| TildeConstReason::Trait { span: item.span }); @@ -1028,7 +1035,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again } - ItemKind::Mod(safety, mod_kind) => { + ItemKind::Mod(safety, ident, mod_kind) => { if let &Safety::Unsafe(span) = safety { self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } @@ -1036,13 +1043,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) && !attr::contains_name(&item.attrs, sym::path) { - self.check_mod_file_item_asciionly(item.ident); + self.check_mod_file_item_asciionly(*ident); } } - ItemKind::Struct(vdata, generics) => match vdata { + ItemKind::Struct(ident, vdata, generics) => match vdata { VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); + self.visit_ident(ident); self.visit_generics(generics); // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); @@ -1051,14 +1058,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } _ => {} }, - ItemKind::Union(vdata, generics) => { + ItemKind::Union(ident, vdata, generics) => { if vdata.fields().is_empty() { self.dcx().emit_err(errors::FieldlessUnion { span: item.span }); } match vdata { VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); + self.visit_ident(ident); self.visit_generics(generics); // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); @@ -1121,14 +1128,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match &fi.kind { - ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => { + ForeignItemKind::Fn(box Fn { defaultness, ident, sig, body, .. }) => { self.check_defaultness(fi.span, *defaultness); - self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); + self.check_foreign_fn_bodyless(*ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_item_ascii_only(*ident); } ForeignItemKind::TyAlias(box TyAlias { defaultness, + ident, generics, where_clauses, bounds, @@ -1136,15 +1144,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) => { self.check_defaultness(fi.span, *defaultness); - self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span)); + self.check_foreign_kind_bodyless(*ident, "type", ty.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics, where_clauses); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_item_ascii_only(*ident); } - ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => { + ForeignItemKind::Static(box StaticItem { ident, safety, expr, .. }) => { self.check_item_safety(fi.span, *safety); - self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); - self.check_foreign_item_ascii_only(fi.ident); + self.check_foreign_kind_bodyless(*ident, "static", expr.as_ref().map(|b| b.span)); + self.check_foreign_item_ascii_only(*ident); } ForeignItemKind::MacCall(..) => {} } @@ -1351,7 +1359,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if let FnKind::Fn( - _, _, _, Fn { @@ -1364,7 +1371,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } // Functions without bodies cannot have patterns. - if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk { + if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { @@ -1398,7 +1405,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .is_some(); let disallowed = (!tilde_const_allowed).then(|| match fk { - FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span }, + FnKind::Fn(_, _, f) => TildeConstReason::Function { ident: f.ident.span }, FnKind::Closure(..) => TildeConstReason::Closure, }); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); @@ -1406,7 +1413,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { if attr::contains_name(&item.attrs, sym::no_mangle) { - self.check_nomangle_item_asciionly(item.ident, item.span); + if let Some(ident) = item.kind.ident() { + self.check_nomangle_item_asciionly(ident, item.span); + } } if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { @@ -1466,8 +1475,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - if let AssocItemKind::Const(..) = item.kind { - self.check_item_named(item.ident, "const"); + if let AssocItemKind::Const(ci) = &item.kind { + self.check_item_named(ci.ident, "const"); } let parent_is_const = @@ -1480,8 +1489,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { || matches!(func.sig.header.constness, Const::Yes(_)) => { self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func); + self.visit_ident(&func.ident); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.vis, &*func); walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a3fcc110a1666..2fac881f4c42f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -236,7 +236,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate!(&self, trait_alias, i.span, "trait aliases are experimental"); } - ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => { + ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => { let msg = "`macro` is experimental"; gate!(&self, decl_macro, i.span, msg); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index d406a56c05da0..653bd77cc4dd8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -28,23 +28,24 @@ impl<'a> State<'a> { } fn print_foreign_item(&mut self, item: &ast::ForeignItem) { - let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; + let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { ast::ForeignItemKind::Fn(func) => { - self.print_fn_full(ident, vis, attrs, &*func); + self.print_fn_full(vis, attrs, &*func); } ast::ForeignItemKind::Static(box ast::StaticItem { + ident, ty, mutability, expr, safety, define_opaque, }) => self.print_item_const( - ident, + *ident, Some(*mutability), &ast::Generics::default(), ty, @@ -56,13 +57,14 @@ impl<'a> State<'a> { ), ast::ForeignItemKind::TyAlias(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - ident, + *ident, generics, *where_clauses, bounds, @@ -162,7 +164,7 @@ impl<'a> State<'a> { self.print_outer_attributes(&item.attrs); self.ann.pre(self, AnnNode::Item(item)); match &item.kind { - ast::ItemKind::ExternCrate(orig_name) => { + ast::ItemKind::ExternCrate(orig_name, ident) => { self.head(visibility_qualified(&item.vis, "extern crate")); if let &Some(orig_name) = orig_name { self.print_name(orig_name); @@ -170,7 +172,7 @@ impl<'a> State<'a> { self.word("as"); self.space(); } - self.print_ident(item.ident); + self.print_ident(*ident); self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block @@ -182,6 +184,7 @@ impl<'a> State<'a> { self.word(";"); } ast::ItemKind::Static(box StaticItem { + ident, ty, safety, mutability: mutbl, @@ -190,7 +193,7 @@ impl<'a> State<'a> { }) => { self.print_safety(*safety); self.print_item_const( - item.ident, + *ident, Some(*mutbl), &ast::Generics::default(), ty, @@ -203,13 +206,14 @@ impl<'a> State<'a> { } ast::ItemKind::Const(box ast::ConstItem { defaultness, + ident, generics, ty, expr, define_opaque, }) => { self.print_item_const( - item.ident, + *ident, None, generics, ty, @@ -221,15 +225,15 @@ impl<'a> State<'a> { ); } ast::ItemKind::Fn(func) => { - self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func); + self.print_fn_full(&item.vis, &item.attrs, &*func); } - ast::ItemKind::Mod(safety, mod_kind) => { + ast::ItemKind::Mod(safety, ident, mod_kind) => { self.head(Self::to_string(|s| { s.print_visibility(&item.vis); s.print_safety(*safety); s.word("mod"); })); - self.print_ident(item.ident); + self.print_ident(*ident); match mod_kind { ModKind::Loaded(items, ..) => { @@ -273,13 +277,14 @@ impl<'a> State<'a> { } ast::ItemKind::TyAlias(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - item.ident, + *ident, generics, *where_clauses, bounds, @@ -288,16 +293,16 @@ impl<'a> State<'a> { *defaultness, ); } - ast::ItemKind::Enum(enum_definition, params) => { - self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis); + ast::ItemKind::Enum(ident, enum_definition, params) => { + self.print_enum_def(enum_definition, params, *ident, item.span, &item.vis); } - ast::ItemKind::Struct(struct_def, generics) => { + ast::ItemKind::Struct(ident, struct_def, generics) => { self.head(visibility_qualified(&item.vis, "struct")); - self.print_struct(struct_def, generics, item.ident, item.span, true); + self.print_struct(struct_def, generics, *ident, item.span, true); } - ast::ItemKind::Union(struct_def, generics) => { + ast::ItemKind::Union(ident, struct_def, generics) => { self.head(visibility_qualified(&item.vis, "union")); - self.print_struct(struct_def, generics, item.ident, item.span, true); + self.print_struct(struct_def, generics, *ident, item.span, true); } ast::ItemKind::Impl(box ast::Impl { safety, @@ -347,19 +352,19 @@ impl<'a> State<'a> { self.bclose(item.span, empty); } ast::ItemKind::Trait(box ast::Trait { - is_auto, safety, + is_auto, + ident, generics, bounds, items, - .. }) => { self.head(""); self.print_visibility(&item.vis); self.print_safety(*safety); self.print_is_auto(*is_auto); self.word_nbsp("trait"); - self.print_ident(item.ident); + self.print_ident(*ident); self.print_generic_params(&generics.params); if !bounds.is_empty() { self.word_nbsp(":"); @@ -375,9 +380,9 @@ impl<'a> State<'a> { let empty = item.attrs.is_empty() && items.is_empty(); self.bclose(item.span, empty); } - ast::ItemKind::TraitAlias(generics, bounds) => { + ast::ItemKind::TraitAlias(ident, generics, bounds) => { self.head(visibility_qualified(&item.vis, "trait")); - self.print_ident(item.ident); + self.print_ident(*ident); self.print_generic_params(&generics.params); self.nbsp(); if !bounds.is_empty() { @@ -395,8 +400,8 @@ impl<'a> State<'a> { self.word(";"); } } - ast::ItemKind::MacroDef(macro_def) => { - self.print_mac_def(macro_def, &item.ident, item.span, |state| { + ast::ItemKind::MacroDef(ident, macro_def) => { + self.print_mac_def(macro_def, &ident, item.span, |state| { state.print_visibility(&item.vis) }); } @@ -549,24 +554,25 @@ impl<'a> State<'a> { } fn print_assoc_item(&mut self, item: &ast::AssocItem) { - let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; + let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { ast::AssocItemKind::Fn(func) => { - self.print_fn_full(ident, vis, attrs, &*func); + self.print_fn_full(vis, attrs, &*func); } ast::AssocItemKind::Const(box ast::ConstItem { defaultness, + ident, generics, ty, expr, define_opaque, }) => { self.print_item_const( - ident, + *ident, None, generics, ty, @@ -579,13 +585,14 @@ impl<'a> State<'a> { } ast::AssocItemKind::Type(box ast::TyAlias { defaultness, + ident, generics, where_clauses, bounds, ty, }) => { self.print_associated_type( - ident, + *ident, generics, *where_clauses, bounds, @@ -671,14 +678,8 @@ impl<'a> State<'a> { } } - fn print_fn_full( - &mut self, - name: Ident, - vis: &ast::Visibility, - attrs: &[ast::Attribute], - func: &ast::Fn, - ) { - let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func; + fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) { + let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque } = func; self.print_define_opaques(define_opaque.as_deref()); @@ -687,7 +688,7 @@ impl<'a> State<'a> { } self.print_visibility(vis); self.print_defaultness(*defaultness); - self.print_fn(&sig.decl, sig.header, Some(name), generics); + self.print_fn(&sig.decl, sig.header, Some(*ident), generics); if let Some(contract) = &contract { self.nbsp(); self.print_contract(contract); @@ -734,13 +735,13 @@ impl<'a> State<'a> { &mut self, decl: &ast::FnDecl, header: ast::FnHeader, - name: Option, + ident: Option, generics: &ast::Generics, ) { self.print_fn_header_info(header); - if let Some(name) = name { + if let Some(ident) = ident { self.nbsp(); - self.print_ident(name); + self.print_ident(ident); } self.print_generic_params(&generics.params); self.print_fn_params_and_ret(decl, false); diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 1c1b2c88f76ee..ea406e706660d 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -21,15 +21,15 @@ pub(crate) fn expand( // Allow using `#[alloc_error_handler]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, sig_span) = if let Annotatable::Item(item) = &item + let (item, ident, is_stmt, sig_span) = if let Annotatable::Item(item) = &item && let ItemKind::Fn(fn_kind) = &item.kind { - (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) + (item, fn_kind.ident, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind && let ItemKind::Fn(fn_kind) = &item.kind { - (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) + (item, fn_kind.ident, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) } else { ecx.dcx().emit_err(errors::AllocErrorMustBeFn { span: item.span() }); return vec![orig_item]; @@ -39,7 +39,7 @@ pub(crate) fn expand( let span = ecx.with_def_site_ctxt(item.span); // Generate item statements for the allocator methods. - let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)]; + let stmts = thin_vec![generate_handler(ecx, ident, span, sig_span)]; // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new())); @@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let kind = ItemKind::Fn(Box::new(Fn { defaultness: ast::Defaultness::Final, sig, + ident: Ident::from_str_and_span("__rg_oom", span), generics: Generics::default(), contract: None, body, @@ -93,6 +94,6 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; - let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); + let item = cx.item(span, attrs, kind); cx.stmt_item(sig_span, item) } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index eb5b345e49ecd..3e8ddb8abd43f 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -10,7 +10,7 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_parse::exp; use rustc_parse::parser::{ExpKeywordPair, Parser}; use rustc_session::lint; -use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw}; +use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, kw}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; use {rustc_ast as ast, rustc_parse_format as parse}; @@ -888,7 +888,6 @@ pub(super) fn expand_global_asm<'cx>( }; match mac { Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { - ident: Ident::empty(), attrs: ast::AttrVec::new(), id: ast::DUMMY_NODE_ID, kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index a949ab94f3ad7..ea7248ca5393a 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -112,7 +112,6 @@ impl<'cx, 'a> Context<'cx, 'a> { self.span, self.cx.item( self.span, - Ident::empty(), thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)], ItemKind::Use(UseTree { prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index be11711757e4b..8937d35d53aed 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -146,26 +146,26 @@ mod llvm_enzyme { } let dcx = ecx.sess.dcx(); // first get the annotable item: - let (sig, is_impl): (FnSig, bool) = match &item { + let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item { Annotatable::Item(iitem) => { - let sig = match &iitem.kind { - ItemKind::Fn(box ast::Fn { sig, .. }) => sig, + let (ident, sig) = match &iitem.kind { + ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (sig.clone(), false) + (*ident, sig.clone(), false) } Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => { - let sig = match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig, + let (ident, sig) = match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (sig.clone(), true) + (*ident, sig.clone(), true) } _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); @@ -184,11 +184,9 @@ mod llvm_enzyme { let has_ret = has_ret(&sig.decl.output); let sig_span = ecx.with_call_site_ctxt(sig.span); - let (vis, primal) = match &item { - Annotatable::Item(iitem) => (iitem.vis.clone(), iitem.ident.clone()), - Annotatable::AssocItem(assoc_item, _) => { - (assoc_item.vis.clone(), assoc_item.ident.clone()) - } + let vis = match &item { + Annotatable::Item(iitem) => iitem.vis.clone(), + Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; @@ -237,12 +235,12 @@ mod llvm_enzyme { let d_body = gen_enzyme_body( ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored, ); - let d_ident = first_ident(&meta_item_vec[0]); // The first element of it is the name of the function to be generated let asdf = Box::new(ast::Fn { defaultness: ast::Defaultness::Final, sig: d_sig, + ident: first_ident(&meta_item_vec[0]), generics: Generics::default(), contract: None, body: Some(d_body), @@ -323,14 +321,12 @@ mod llvm_enzyme { id: ast::DUMMY_NODE_ID, span, vis, - ident: d_ident, kind: assoc_item, tokens: None, }); Annotatable::AssocItem(d_fn, Impl { of_trait: false }) } else { - let mut d_fn = - ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); + let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); d_fn.vis = vis; Annotatable::Item(d_fn) }; diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index c3656e8244fe0..44cf215c66227 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -34,8 +34,8 @@ pub(crate) fn expand_deriving_clone( let is_simple; match item { Annotatable::Item(annitem) => match &annitem.kind { - ItemKind::Struct(_, Generics { params, .. }) - | ItemKind::Enum(_, Generics { params, .. }) => { + ItemKind::Struct(_, _, Generics { params, .. }) + | ItemKind::Enum(_, _, Generics { params, .. }) => { let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_copy = cx.resolver.has_derive_copy(container_id); if has_derive_copy diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 7958e037555d5..aa01da3151eb4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_partial_ord( // Order in which to perform matching let discr_then_data = if let Annotatable::Item(item) = item - && let ItemKind::Enum(def, _) = &item.kind + && let ItemKind::Enum(_, def, _) = &item.kind { let dataful: Vec = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect(); match dataful.iter().filter(|&&b| b).count() { diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 46b79e0978082..446d8afeedd7f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_coerce_pointee( item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); let (name_ident, generics) = if let Annotatable::Item(aitem) = item - && let ItemKind::Struct(struct_data, g) = &aitem.kind + && let ItemKind::Struct(ident, struct_data, g) = &aitem.kind { if !matches!( struct_data, @@ -40,7 +40,7 @@ pub(crate) fn expand_deriving_coerce_pointee( cx.dcx().emit_err(RequireOneField { span }); return; } - (aitem.ident, g) + (*ident, g) } else { cx.dcx().emit_err(RequireTransparent { span }); return; @@ -108,7 +108,6 @@ pub(crate) fn expand_deriving_coerce_pointee( push(Annotatable::Item( cx.item( span, - Ident::empty(), attrs.clone(), ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, @@ -153,7 +152,6 @@ pub(crate) fn expand_deriving_coerce_pointee( let trait_ref = cx.trait_ref(trait_path); let item = cx.item( span, - Ident::empty(), attrs.clone(), ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 03ee59de70e12..b9197be444266 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -487,28 +487,28 @@ impl<'a> TraitDef<'a> { ); let newitem = match &item.kind { - ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def( + ast::ItemKind::Struct(ident, struct_def, generics) => self.expand_struct_def( cx, struct_def, - item.ident, + *ident, generics, from_scratch, is_packed, ), - ast::ItemKind::Enum(enum_def, generics) => { + ast::ItemKind::Enum(ident, enum_def, generics) => { // We ignore `is_packed` here, because `repr(packed)` // enums cause an error later on. // // This can only cause further compilation errors // downstream in blatantly illegal code, so it is fine. - self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch) + self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) } - ast::ItemKind::Union(struct_def, generics) => { + ast::ItemKind::Union(ident, struct_def, generics) => { if self.supports_unions { self.expand_struct_def( cx, struct_def, - item.ident, + *ident, generics, from_scratch, is_packed, @@ -596,7 +596,6 @@ impl<'a> TraitDef<'a> { P(ast::AssocItem { id: ast::DUMMY_NODE_ID, span: self.span, - ident, vis: ast::Visibility { span: self.span.shrink_to_lo(), kind: ast::VisibilityKind::Inherited, @@ -605,6 +604,7 @@ impl<'a> TraitDef<'a> { attrs: ast::AttrVec::new(), kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias { defaultness: ast::Defaultness::Final, + ident, generics: Generics::default(), where_clauses: ast::TyAliasWhereClauses::default(), bounds: Vec::new(), @@ -789,7 +789,6 @@ impl<'a> TraitDef<'a> { cx.item( self.span, - Ident::empty(), attrs, ast::ItemKind::Impl(Box::new(ast::Impl { safety: ast::Safety::Default, @@ -1033,10 +1032,10 @@ impl<'a> MethodDef<'a> { kind: ast::VisibilityKind::Inherited, tokens: None, }, - ident: method_ident, kind: ast::AssocItemKind::Fn(Box::new(ast::Fn { defaultness, sig, + ident: method_ident, generics: fn_generics, contract: None, body: Some(body_block), diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 90d79235820f4..4b1958bce3223 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -25,15 +25,15 @@ pub(crate) fn expand( // Allow using `#[global_allocator]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, ty_span) = if let Annotatable::Item(item) = &item - && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind + let (item, ident, is_stmt, ty_span) = if let Annotatable::Item(item) = &item + && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind { - (item, false, ecx.with_def_site_ctxt(ty.span)) + (item, *ident, false, ecx.with_def_site_ctxt(ty.span)) } else if let Annotatable::Stmt(stmt) = &item && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Static(box ast::StaticItem { ty, .. }) = &item.kind + && let ItemKind::Static(box ast::StaticItem { ident, ty, .. }) = &item.kind { - (item, true, ecx.with_def_site_ctxt(ty.span)) + (item, *ident, true, ecx.with_def_site_ctxt(ty.span)) } else { ecx.dcx().emit_err(errors::AllocMustStatics { span: item.span() }); return vec![orig_item]; @@ -41,7 +41,7 @@ pub(crate) fn expand( // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); - let f = AllocFnFactory { span, ty_span, global: item.ident, cx: ecx }; + let f = AllocFnFactory { span, ty_span, global: ident, cx: ecx }; // Generate item statements for the allocator methods. let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect(); @@ -80,17 +80,13 @@ impl AllocFnFactory<'_, '_> { let kind = ItemKind::Fn(Box::new(Fn { defaultness: ast::Defaultness::Final, sig, + ident: Ident::from_str_and_span(&global_fn_name(method.name), self.span), generics: Generics::default(), contract: None, body, define_opaque: None, })); - let item = self.cx.item( - self.span, - Ident::from_str_and_span(&global_fn_name(method.name), self.span), - self.attrs(), - kind, - ); + let item = self.cx.item(self.span, self.attrs(), kind); self.cx.stmt_item(self.ty_span, item) } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index ee6475c8b8e91..7c25f26895ca0 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -92,7 +92,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { + fn collect_custom_derive( + &mut self, + item: &'a ast::Item, + function_name: Ident, + attr: &'a ast::Attribute, + ) { let Some((trait_name, proc_attrs)) = parse_macro_name_and_helper_attrs(self.dcx, attr, "derive") else { @@ -104,7 +109,7 @@ impl<'a> CollectProcMacros<'a> { id: item.id, span: item.span, trait_name, - function_name: item.ident, + function_name, attrs: proc_attrs, })); } else { @@ -118,12 +123,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { + fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Attr(ProcMacroDef { id: item.id, span: item.span, - function_name: item.ident, + function_name, })); } else { let msg = if !self.in_root { @@ -136,12 +141,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) { + fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Bang(ProcMacroDef { id: item.id, span: item.span, - function_name: item.ident, + function_name, })); } else { let msg = if !self.in_root { @@ -165,12 +170,6 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } } - // First up, make sure we're checking a bare function. If we're not then - // we're just not interested in this item. - // - // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. - let is_fn = matches!(item.kind, ast::ItemKind::Fn(..)); - let mut found_attr: Option<&'a ast::Attribute> = None; for attr in &item.attrs { @@ -214,7 +213,13 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; }; - if !is_fn { + // First up, make sure we're checking a bare function. If we're not then + // we're just not interested in this item. + // + // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. + let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind { + fn_.ident + } else { self.dcx .create_err(errors::AttributeOnlyBeUsedOnBareFunctions { span: attr.span, @@ -222,7 +227,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { }) .emit(); return; - } + }; if self.is_test_crate { return; @@ -239,11 +244,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } if attr.has_name(sym::proc_macro_derive) { - self.collect_custom_derive(item, attr); + self.collect_custom_derive(item, fn_ident, attr); } else if attr.has_name(sym::proc_macro_attribute) { - self.collect_attr_proc_macro(item); + self.collect_attr_proc_macro(item, fn_ident); } else if attr.has_name(sym::proc_macro) { - self.collect_bang_proc_macro(item); + self.collect_bang_proc_macro(item, fn_ident); }; let prev_in_root = mem::replace(&mut self.in_root, false); @@ -278,7 +283,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); let proc_macro = Ident::new(sym::proc_macro, span); - let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + let krate = cx.item(span, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, proc_macro)); let bridge = Ident::new(sym::bridge, span); let client = Ident::new(sym::client, span); diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index ba63b185e0967..a1ee53b7ca21f 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -43,9 +43,8 @@ pub fn inject( let item = cx.item( span, - Ident::new(name, ident_span), thin_vec![cx.attr_word(sym::macro_use, span)], - ast::ItemKind::ExternCrate(None), + ast::ItemKind::ExternCrate(None, Ident::new(name, ident_span)), ); krate.items.insert(0, item); @@ -68,7 +67,6 @@ pub fn inject( // Inject the relevant crate's prelude. let use_item = cx.item( span, - Ident::empty(), thin_vec![cx.attr_word(sym::prelude_import, span)], ast::ItemKind::Use(ast::UseTree { prefix: cx.path(span, import_path), diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index db3e431495bf7..1cef4f9514cd7 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -55,12 +55,14 @@ pub(crate) fn expand_test_case( // `#[test_case]` is valid on functions, consts, and statics. Only modify // the item in those cases. match &mut item.kind { - ast::ItemKind::Fn(_) | ast::ItemKind::Const(_) | ast::ItemKind::Static(_) => { - item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); + ast::ItemKind::Fn(box ast::Fn { ident, .. }) + | ast::ItemKind::Const(box ast::ConstItem { ident, .. }) + | ast::ItemKind::Static(box ast::StaticItem { ident, .. }) => { + ident.span = ident.span.with_ctxt(sp.ctxt()); let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module &ecx.current_expansion.module.mod_path[1..], - &item.ident, + ident, )); item.vis = ast::Visibility { span: item.vis.span, @@ -228,7 +230,7 @@ pub(crate) fn expand_test_or_bench( // super::$test_fn(b) cx.expr_call( ret_ty_sp, - cx.expr_path(cx.path(sp, vec![item.ident])), + cx.expr_path(cx.path(sp, vec![fn_.ident])), thin_vec![cx.expr_ident(sp, b)], ), ], @@ -254,7 +256,7 @@ pub(crate) fn expand_test_or_bench( // $test_fn() cx.expr_call( ret_ty_sp, - cx.expr_path(cx.path(sp, vec![item.ident])), + cx.expr_path(cx.path(sp, vec![fn_.ident])), ThinVec::new(), ), // ) ], @@ -267,15 +269,14 @@ pub(crate) fn expand_test_or_bench( let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module &cx.current_expansion.module.mod_path[1..], - &item.ident, + &fn_.ident, )); - let location_info = get_location_info(cx, &item); + let location_info = get_location_info(cx, &fn_); let mut test_const = cx.item( sp, - Ident::new(item.ident.name, sp), thin_vec![ // #[cfg(test)] cx.attr_nested_word(sym::cfg, sym::test, attr_sp), @@ -288,6 +289,7 @@ pub(crate) fn expand_test_or_bench( ast::ItemKind::Const( ast::ConstItem { defaultness: ast::Defaultness::Final, + ident: Ident::new(fn_.ident.name, sp), generics: ast::Generics::default(), ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), define_opaque: None, @@ -386,7 +388,7 @@ pub(crate) fn expand_test_or_bench( // extern crate test let test_extern = - cx.item(sp, test_ident, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)); + cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)); debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const)); @@ -440,8 +442,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) .emit(); } -fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) { - let span = item.ident.span; +fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize, usize, usize) { + let span = fn_.ident.span; let (source_file, lo_line, lo_col, hi_line, hi_col) = cx.sess.source_map().span_to_location_info(span); diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 768b459ec5e30..56a67b0534d98 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -134,27 +134,21 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { if let Some(name) = get_test_name(&item) { debug!("this is a test item"); - let test = Test { span: item.span, ident: item.ident, name }; + // `unwrap` is ok because only functions, consts, and static should reach here. + let test = Test { span: item.span, ident: item.kind.ident().unwrap(), name }; self.tests.push(test); } // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things if let ast::ItemKind::Mod( + _, _, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. }, _), ) = item.kind { let prev_tests = mem::take(&mut self.tests); - walk_item_kind( - &mut item.kind, - item.span, - item.id, - &mut item.ident, - &mut item.vis, - (), - self, - ); + walk_item_kind(&mut item.kind, item.span, item.id, &mut item.vis, (), self); self.add_test_cases(item.id, span, prev_tests); } else { // But in those cases, we emit a lint to warn the user of these missing tests. @@ -181,9 +175,9 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> { } fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType { - match item.kind { - ast::ItemKind::Fn(..) => { - rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name)) + match &item.kind { + ast::ItemKind::Fn(fn_) => { + rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name)) } _ => EntryPointType::None, } @@ -295,7 +289,7 @@ fn generate_test_harness( fn mk_main(cx: &mut TestCtxt<'_>) -> P { let sp = cx.def_site; let ecx = &cx.ext_cx; - let test_id = Ident::new(sym::test, sp); + let test_ident = Ident::new(sym::test, sp); let runner_name = match cx.panic_strategy { PanicStrategy::Unwind => "test_main_static", @@ -303,10 +297,9 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { }; // test::test_main_static(...) - let mut test_runner = cx - .test_runner - .clone() - .unwrap_or_else(|| ecx.path(sp, vec![test_id, Ident::from_str_and_span(runner_name, sp)])); + let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| { + ecx.path(sp, vec![test_ident, Ident::from_str_and_span(runner_name, sp)]) + }); test_runner.span = sp; @@ -317,7 +310,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { // extern crate test let test_extern_stmt = ecx.stmt_item( sp, - ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)), + ecx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident)), ); // #[rustc_main] @@ -340,23 +333,24 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty)); let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp }; let defaultness = ast::Defaultness::Final; + + // Honor the reexport_test_harness_main attribute + let main_ident = match cx.reexport_test_harness_main { + Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), + None => Ident::new(sym::main, sp), + }; + let main = ast::ItemKind::Fn(Box::new(ast::Fn { defaultness, sig, + ident: main_ident, generics: ast::Generics::default(), contract: None, body: Some(main_body), define_opaque: None, })); - // Honor the reexport_test_harness_main attribute - let main_id = match cx.reexport_test_harness_main { - Some(sym) => Ident::new(sym, sp.with_ctxt(SyntaxContext::root())), - None => Ident::new(sym::main, sp), - }; - let main = P(ast::Item { - ident: main_id, attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr], id: ast::DUMMY_NODE_ID, kind: main, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 990d0f2e028aa..d14e476ba3223 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1424,12 +1424,11 @@ pub fn parse_macro_name_and_helper_attrs( /// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. fn pretty_printing_compatibility_hack(item: &Item, psess: &ParseSess) { - let name = item.ident.name; - if name == sym::ProceduralMasqueradeDummyType - && let ast::ItemKind::Enum(enum_def, _) = &item.kind + if let ast::ItemKind::Enum(ident, enum_def, _) = &item.kind + && ident.name == sym::ProceduralMasqueradeDummyType && let [variant] = &*enum_def.variants && variant.ident.name == sym::Input - && let FileName::Real(real) = psess.source_map().span_to_filename(item.ident.span) + && let FileName::Real(real) = psess.source_map().span_to_filename(ident.span) && let Some(c) = real .local_path() .unwrap_or(Path::new("")) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 89a750bb39f0c..f68172c1f67c0 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -662,15 +662,8 @@ impl<'a> ExtCtxt<'a> { P(ast::FnDecl { inputs, output }) } - pub fn item( - &self, - span: Span, - name: Ident, - attrs: ast::AttrVec, - kind: ast::ItemKind, - ) -> P { + pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P { P(ast::Item { - ident: name, attrs, id: ast::DUMMY_NODE_ID, kind, @@ -687,17 +680,17 @@ impl<'a> ExtCtxt<'a> { pub fn item_static( &self, span: Span, - name: Ident, + ident: Ident, ty: P, mutability: ast::Mutability, expr: P, ) -> P { self.item( span, - name, AttrVec::new(), ast::ItemKind::Static( ast::StaticItem { + ident, ty, safety: ast::Safety::Default, mutability, @@ -712,18 +705,18 @@ impl<'a> ExtCtxt<'a> { pub fn item_const( &self, span: Span, - name: Ident, + ident: Ident, ty: P, expr: P, ) -> P { let defaultness = ast::Defaultness::Final; self.item( span, - name, AttrVec::new(), ast::ItemKind::Const( ast::ConstItem { defaultness, + ident, // FIXME(generic_const_items): Pass the generics as a parameter. generics: ast::Generics::default(), ty, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 22da1179feb98..d1dd454fa73d7 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -743,6 +743,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { && matches!( item_inner.kind, ItemKind::Mod( + _, _, ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _, _), ) @@ -911,7 +912,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { - ItemKind::Mod(_, mod_kind) + ItemKind::Mod(_, _, mod_kind) if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _, _)) => { feature_err( @@ -1221,8 +1222,9 @@ impl InvocationCollectorNode for P { } // Work around borrow checker not seeing through `P`'s deref. - let (ident, span, mut attrs) = (node.ident, node.span, mem::take(&mut node.attrs)); - let ItemKind::Mod(_, mod_kind) = &mut node.kind else { unreachable!() }; + let (span, mut attrs) = (node.span, mem::take(&mut node.attrs)); + let ItemKind::Mod(_, ident, mod_kind) = &mut node.kind else { unreachable!() }; + let ident = *ident; let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { @@ -1305,6 +1307,7 @@ impl InvocationCollectorNode for P { collector.cx.current_expansion.module = orig_module; res } + fn declared_names(&self) -> Vec { if let ItemKind::Use(ut) = &self.kind { fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec) { @@ -1324,7 +1327,7 @@ impl InvocationCollectorNode for P { return idents; } - vec![self.ident] + if let Some(ident) = self.kind.ident() { vec![ident] } else { vec![] } } } @@ -1844,11 +1847,11 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( id: ast::DUMMY_NODE_ID, span: if from_glob { item_span } else { ident.span }, vis: item.vis.clone(), - ident: rename.unwrap_or(ident), kind: Node::delegation_item_kind(Box::new(ast::Delegation { id: ast::DUMMY_NODE_ID, qself: deleg.qself.clone(), path, + ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), from_glob, diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index a60a87244cc6e..0136292decbcf 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -26,7 +26,7 @@ pub(crate) fn placeholder( }) } - let ident = Ident::empty(); + let ident = Ident::dummy(); let attrs = ast::AttrVec::new(); let vis = vis.unwrap_or(ast::Visibility { span: DUMMY_SP, @@ -62,7 +62,6 @@ pub(crate) fn placeholder( AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { id, span, - ident, vis, attrs, kind: ast::ItemKind::MacCall(mac_placeholder()), @@ -71,7 +70,6 @@ pub(crate) fn placeholder( AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -80,7 +78,6 @@ pub(crate) fn placeholder( AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -90,7 +87,6 @@ pub(crate) fn placeholder( AstFragment::TraitImplItems(smallvec![P(ast::AssocItem { id, span, - ident, vis, attrs, kind: ast::AssocItemKind::MacCall(mac_placeholder()), @@ -101,7 +97,6 @@ pub(crate) fn placeholder( AstFragment::ForeignItems(smallvec![P(ast::ForeignItem { id, span, - ident, vis, attrs, kind: ast::ForeignItemKind::MacCall(mac_placeholder()), diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9dccd4a0552c3..c56dbc2e1c401 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -330,7 +330,6 @@ impl EarlyLintPass for UnsafeCode { if let FnKind::Fn( ctxt, _, - _, ast::Fn { sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. }, body, @@ -3116,6 +3115,7 @@ impl EarlyLintPass for SpecialModuleName { for item in &krate.items { if let ast::ItemKind::Mod( _, + ident, ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _, _), ) = item.kind { @@ -3123,7 +3123,7 @@ impl EarlyLintPass for SpecialModuleName { continue; } - match item.ident.name.as_str() { + match ident.name.as_str() { "lib" => cx.emit_span_lint( SPECIAL_MODULE_NAME, item.span, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 752636ccaf061..df567e80e5568 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -172,20 +172,22 @@ impl EarlyLintPass for NonCamelCaseTypes { } match &it.kind { - ast::ItemKind::TyAlias(..) - | ast::ItemKind::Enum(..) - | ast::ItemKind::Struct(..) - | ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident), - ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident), - ast::ItemKind::TraitAlias(..) => self.check_case(cx, "trait alias", &it.ident), + ast::ItemKind::TyAlias(box ast::TyAlias { ident, .. }) + | ast::ItemKind::Enum(ident, ..) + | ast::ItemKind::Struct(ident, ..) + | ast::ItemKind::Union(ident, ..) => self.check_case(cx, "type", ident), + ast::ItemKind::Trait(box ast::Trait { ident, .. }) => { + self.check_case(cx, "trait", ident) + } + ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident), // N.B. This check is only for inherent associated types, so that we don't lint against // trait impls where we should have warned for the trait definition already. ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => { for it in items { // FIXME: this doesn't respect `#[allow(..)]` on the item itself. - if let ast::AssocItemKind::Type(..) = it.kind { - self.check_case(cx, "associated type", &it.ident); + if let ast::AssocItemKind::Type(alias) = &it.kind { + self.check_case(cx, "associated type", &alias.ident); } } } @@ -194,8 +196,8 @@ impl EarlyLintPass for NonCamelCaseTypes { } fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { - if let ast::AssocItemKind::Type(..) = it.kind { - self.check_case(cx, "associated type", &it.ident); + if let ast::AssocItemKind::Type(alias) = &it.kind { + self.check_case(cx, "associated type", &alias.ident); } } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e1ee562dafeb3..16f87ab79bee5 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1315,17 +1315,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { definitions: &Definitions, ) -> Option { match item.kind { - ast::ItemKind::ExternCrate(orig_name) => { - debug!( - "resolving extern crate stmt. ident: {} orig_name: {:?}", - item.ident, orig_name - ); + ast::ItemKind::ExternCrate(orig_name, ident) => { + debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name); let name = match orig_name { Some(orig_name) => { validate_crate_name(self.sess, orig_name, Some(item.span)); orig_name } - None => item.ident.name, + None => ident.name, }; let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) { CrateDepKind::MacrosOnly @@ -1380,7 +1377,8 @@ fn fn_spans(krate: &ast::Crate, name: Symbol) -> Vec { } impl<'ast> visit::Visitor<'ast> for Finder { fn visit_item(&mut self, item: &'ast ast::Item) { - if item.ident.name == self.name + if let Some(ident) = item.kind.ident() + && ident.name == self.name && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) { self.spans.push(item.span); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad1857837554..ed6522850960d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -34,10 +34,10 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> { + fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(exp!(Mod))?; - let id = self.parse_ident()?; + let ident = self.parse_ident()?; let mod_kind = if self.eat(exp!(Semi)) { ModKind::Unloaded } else { @@ -46,7 +46,7 @@ impl<'a> Parser<'a> { attrs.extend(inner_attrs); ModKind::Loaded(items, Inline::Yes, inner_span, Ok(())) }; - Ok((id, ItemKind::Mod(safety, mod_kind))) + Ok(ItemKind::Mod(safety, ident, mod_kind)) } /// Parses the contents of a module (inner attributes followed by module items). @@ -115,8 +115,6 @@ impl<'a> Parser<'a> { } } -pub(super) type ItemInfo = (Ident, ItemKind); - impl<'a> Parser<'a> { pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; @@ -163,11 +161,11 @@ impl<'a> Parser<'a> { fn_parse_mode, Case::Sensitive, )?; - if let Some((ident, kind)) = kind { + if let Some(kind) = kind { this.error_on_unconsumed_default(def, &kind); let span = lo.to(this.prev_token.span); let id = DUMMY_NODE_ID; - let item = Item { ident, attrs, id, kind, vis, span, tokens: None }; + let item = Item { attrs, id, kind, vis, span, tokens: None }; return Ok((Some(item), Trailing::No, UsePreAttrPos::No)); } @@ -208,7 +206,7 @@ impl<'a> Parser<'a> { def: &mut Defaultness, fn_parse_mode: FnParseMode, case: Case, - ) -> PResult<'a, Option> { + ) -> PResult<'a, Option> { let check_pub = def == &Defaultness::Final; let mut def_ = || mem::replace(def, Defaultness::Final); @@ -218,17 +216,15 @@ impl<'a> Parser<'a> { // FUNCTION ITEM let (ident, sig, generics, contract, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?; - ( + ItemKind::Fn(Box::new(Fn { + defaultness: def_(), ident, - ItemKind::Fn(Box::new(Fn { - defaultness: def_(), - sig, - generics, - contract, - body, - define_opaque: None, - })), - ) + sig, + generics, + contract, + body, + define_opaque: None, + })) } else if self.eat_keyword(exp!(Extern)) { if self.eat_keyword(exp!(Crate)) { // EXTERN CRATE @@ -247,8 +243,8 @@ impl<'a> Parser<'a> { // STATIC ITEM self.bump(); // `static` let mutability = self.parse_mutability(); - let (ident, item) = self.parse_static_item(safety, mutability)?; - (ident, ItemKind::Static(Box::new(item))) + let item = self.parse_static_item(safety, mutability)?; + ItemKind::Static(Box::new(item)) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -258,16 +254,14 @@ impl<'a> Parser<'a> { self.recover_const_mut(const_span); self.recover_missing_kw_before_item()?; let (ident, generics, ty, expr) = self.parse_const_item()?; - ( + ItemKind::Const(Box::new(ConstItem { + defaultness: def_(), ident, - ItemKind::Const(Box::new(ConstItem { - defaultness: def_(), - generics, - ty, - expr, - define_opaque: None, - })), - ) + generics, + ty, + expr, + define_opaque: None, + })) } } else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -334,14 +328,14 @@ impl<'a> Parser<'a> { self.recover_missing_kw_before_item()?; } // MACRO INVOCATION ITEM - (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?))) + ItemKind::MacCall(P(self.parse_item_macro(vis)?)) } else { return Ok(None); }; Ok(Some(info)) } - fn recover_import_as_use(&mut self) -> PResult<'a, Option> { + fn recover_import_as_use(&mut self) -> PResult<'a, Option> { let span = self.token.span; let token_name = super::token_descr(&self.token); let snapshot = self.create_snapshot_for_diagnostic(); @@ -359,7 +353,7 @@ impl<'a> Parser<'a> { } } - fn parse_use_item(&mut self) -> PResult<'a, ItemInfo> { + fn parse_use_item(&mut self) -> PResult<'a, ItemKind> { let tree = self.parse_use_tree()?; if let Err(mut e) = self.expect_semi() { match tree.kind { @@ -373,7 +367,7 @@ impl<'a> Parser<'a> { } return Err(e); } - Ok((Ident::empty(), ItemKind::Use(tree))) + Ok(ItemKind::Use(tree)) } /// When parsing a statement, would the start of a path be an item? @@ -483,7 +477,7 @@ impl<'a> Parser<'a> { if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } - fn parse_item_builtin(&mut self) -> PResult<'a, Option> { + fn parse_item_builtin(&mut self) -> PResult<'a, Option> { // To be expanded Ok(None) } @@ -577,7 +571,7 @@ impl<'a> Parser<'a> { &mut self, attrs: &mut AttrVec, defaultness: Defaultness, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(exp!(Impl))?; @@ -698,10 +692,10 @@ impl<'a> Parser<'a> { items: impl_items, })); - Ok((Ident::empty(), item_kind)) + Ok(item_kind) } - fn parse_item_delegation(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { let span = self.token.span; self.expect_keyword(exp!(Reuse))?; @@ -724,7 +718,7 @@ impl<'a> Parser<'a> { }) }; - let (ident, item_kind) = if self.eat_path_sep() { + let item_kind = if self.eat_path_sep() { let suffixes = if self.eat(exp!(Star)) { None } else { @@ -732,7 +726,7 @@ impl<'a> Parser<'a> { Some(self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), parse_suffix)?.0) }; let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? }; - (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg))) + ItemKind::DelegationMac(Box::new(deleg)) } else { let rename = rename(self)?; let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); @@ -740,17 +734,18 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, qself, path, + ident, rename, body: body(self)?, from_glob: false, }; - (ident, ItemKind::Delegation(Box::new(deleg))) + ItemKind::Delegation(Box::new(deleg)) }; let span = span.to(self.prev_token.span); self.psess.gated_spans.gate(sym::fn_delegation, span); - Ok((ident, item_kind)) + Ok(item_kind) } fn parse_item_list( @@ -900,7 +895,7 @@ impl<'a> Parser<'a> { } /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> { + fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> { let safety = self.parse_safety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(exp!(Auto)) { @@ -941,15 +936,12 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(generics, bounds))) + Ok(ItemKind::TraitAlias(ident, generics, bounds)) } else { // It's a normal trait. generics.where_clause = self.parse_where_clause()?; let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; - Ok(( - ident, - ItemKind::Trait(Box::new(Trait { is_auto, safety, generics, bounds, items })), - )) + Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items }))) } } @@ -977,11 +969,12 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, ) -> PResult<'a, Option>>> { Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, ident, kind, tokens }| { + |Item { attrs, id, span, vis, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { ItemKind::Static(box StaticItem { + ident, ty, safety: _, mutability: _, @@ -991,6 +984,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, + ident, generics: Generics::default(), ty, expr, @@ -1000,7 +994,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }, }; - Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) + Some(P(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1010,7 +1004,7 @@ impl<'a> Parser<'a> { /// TypeAlias = "type" Ident Generics (":" GenericBounds)? WhereClause ("=" Ty)? WhereClause ";" ; /// ``` /// The `"type"` has already been eaten. - fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> { + fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1045,16 +1039,14 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok(( + Ok(ItemKind::TyAlias(Box::new(TyAlias { + defaultness, ident, - ItemKind::TyAlias(Box::new(TyAlias { - defaultness, - generics, - where_clauses, - bounds, - ty, - })), - )) + generics, + where_clauses, + bounds, + ty, + }))) } /// Parses a `UseTree`. @@ -1158,16 +1150,16 @@ impl<'a> Parser<'a> { /// extern crate foo; /// extern crate bar as foo; /// ``` - fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemKind> { // Accept `extern crate name-like-this` for better diagnostics - let orig_name = self.parse_crate_name_with_dashes()?; - let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { - (rename, Some(orig_name.name)) + let orig_ident = self.parse_crate_name_with_dashes()?; + let (orig_name, item_ident) = if let Some(rename) = self.parse_rename()? { + (Some(orig_ident.name), rename) } else { - (orig_name, None) + (None, orig_ident) }; self.expect_semi()?; - Ok((item_name, ItemKind::ExternCrate(orig_name))) + Ok(ItemKind::ExternCrate(orig_name, item_ident)) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> { @@ -1218,7 +1210,7 @@ impl<'a> Parser<'a> { &mut self, attrs: &mut AttrVec, mut safety: Safety, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let extern_span = self.prev_token.uninterpolated_span(); let abi = self.parse_abi(); // ABI? // FIXME: This recovery should be tested better. @@ -1236,7 +1228,7 @@ impl<'a> Parser<'a> { abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, }; - Ok((Ident::empty(), ItemKind::ForeignMod(module))) + Ok(ItemKind::ForeignMod(module)) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1246,11 +1238,11 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Option>>> { let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( - |Item { attrs, id, span, vis, ident, kind, tokens }| { + |Item { attrs, id, span, vis, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(box ConstItem { ty, expr, .. }) => { + ItemKind::Const(box ConstItem { ident, ty, expr, .. }) => { let const_span = Some(span.with_hi(ident.span.lo())) .filter(|span| span.can_be_used_for_suggestions()); self.dcx().emit_err(errors::ExternItemCannotBeConst { @@ -1258,6 +1250,7 @@ impl<'a> Parser<'a> { const_span, }); ForeignItemKind::Static(Box::new(StaticItem { + ident, ty, mutability: Mutability::Not, expr, @@ -1268,7 +1261,7 @@ impl<'a> Parser<'a> { _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }, }; - Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) + Some(P(Item { attrs, id, span, vis, kind, tokens })) }, )) } @@ -1343,13 +1336,13 @@ impl<'a> Parser<'a> { const_span: Span, attrs: &mut AttrVec, defaultness: Defaultness, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { let impl_span = self.token.span; let err = self.expected_ident_found_err(); // Only try to recover if this is implementing a trait for a type - let mut impl_info = match self.parse_item_impl(attrs, defaultness) { - Ok(impl_info) => impl_info, + let mut item_kind = match self.parse_item_impl(attrs, defaultness) { + Ok(item_kind) => item_kind, Err(recovery_error) => { // Recovery failed, raise the "expected identifier" error recovery_error.cancel(); @@ -1357,7 +1350,7 @@ impl<'a> Parser<'a> { } }; - match &mut impl_info.1 { + match &mut item_kind { ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => { *constness = Const::Yes(const_span); @@ -1374,7 +1367,7 @@ impl<'a> Parser<'a> { _ => unreachable!(), } - Ok(impl_info) + Ok(item_kind) } /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`. @@ -1386,7 +1379,7 @@ impl<'a> Parser<'a> { &mut self, safety: Safety, mutability: Mutability, - ) -> PResult<'a, (Ident, StaticItem)> { + ) -> PResult<'a, StaticItem> { let ident = self.parse_ident()?; if self.token == TokenKind::Lt && self.may_recover() { @@ -1406,7 +1399,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok((ident, StaticItem { ty, safety, mutability, expr, define_opaque: None })) + Ok(StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }) } /// Parse a constant item with the prefix `"const"` already parsed. @@ -1531,7 +1524,7 @@ impl<'a> Parser<'a> { } /// Parses an enum declaration. - fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_enum(&mut self) -> PResult<'a, ItemKind> { if self.token.is_keyword(kw::Struct) { let span = self.prev_token.span.to(self.token.span); let err = errors::EnumStructMutuallyExclusive { span }; @@ -1584,7 +1577,7 @@ impl<'a> Parser<'a> { }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; - Ok((id, ItemKind::Enum(enum_definition, generics))) + Ok(ItemKind::Enum(id, enum_definition, generics)) } fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> { @@ -1676,8 +1669,8 @@ impl<'a> Parser<'a> { } /// Parses `struct Foo { ... }`. - fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { - let class_name = self.parse_ident()?; + fn parse_item_struct(&mut self) -> PResult<'a, ItemKind> { + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1698,7 +1691,7 @@ impl<'a> Parser<'a> { let vdata = if self.token.is_keyword(kw::Where) { let tuple_struct_body; (generics.where_clause, tuple_struct_body) = - self.parse_struct_where_clause(class_name, generics.span)?; + self.parse_struct_where_clause(ident, generics.span)?; if let Some(body) = tuple_struct_body { // If we see a misplaced tuple struct body: `struct Foo where T: Copy, (T);` @@ -1712,7 +1705,7 @@ impl<'a> Parser<'a> { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body( "struct", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1724,7 +1717,7 @@ impl<'a> Parser<'a> { } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "struct", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1740,12 +1733,12 @@ impl<'a> Parser<'a> { return Err(self.dcx().create_err(err)); }; - Ok((class_name, ItemKind::Struct(vdata, generics))) + Ok(ItemKind::Struct(ident, vdata, generics)) } /// Parses `union Foo { ... }`. - fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { - let class_name = self.parse_ident()?; + fn parse_item_union(&mut self) -> PResult<'a, ItemKind> { + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1753,14 +1746,14 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body( "union", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "union", - class_name.span, + ident.span, generics.where_clause.has_where_token, )?; VariantData::Struct { fields, recovered } @@ -1772,7 +1765,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Union(vdata, generics))) + Ok(ItemKind::Union(ident, vdata, generics)) } /// This function parses the fields of record structs: @@ -2124,15 +2117,17 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(exp!(Struct)) { match self.parse_item_struct() { - Ok((ident, _)) => self - .dcx() - .struct_span_err( - lo.with_hi(ident.span.hi()), - format!("structs are not allowed in {adt_ty} definitions"), - ) - .with_help( - "consider creating a new `struct` definition instead of nesting", - ), + Ok(item) => { + let ItemKind::Struct(ident, ..) = item else { unreachable!() }; + self.dcx() + .struct_span_err( + lo.with_hi(ident.span.hi()), + format!("structs are not allowed in {adt_ty} definitions"), + ) + .with_help( + "consider creating a new `struct` definition instead of nesting", + ) + } Err(err) => { err.cancel(); self.restore_snapshot(snapshot); @@ -2177,7 +2172,7 @@ impl<'a> Parser<'a> { /// MacParams = "(" TOKEN_STREAM ")" ; /// DeclMac = "macro" Ident MacParams? MacBody ; /// ``` - fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { + fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; let body = if self.check(exp!(OpenBrace)) { self.parse_delim_args()? // `MacBody` @@ -2199,7 +2194,7 @@ impl<'a> Parser<'a> { }; self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) + Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: false })) } /// Is this a possibly malformed start of a `macro_rules! foo` item definition? @@ -2228,7 +2223,7 @@ impl<'a> Parser<'a> { &mut self, vis: &Visibility, has_bang: bool, - ) -> PResult<'a, ItemInfo> { + ) -> PResult<'a, ItemKind> { self.expect_keyword(exp!(MacroRules))?; // `macro_rules` if has_bang { @@ -2246,7 +2241,7 @@ impl<'a> Parser<'a> { self.eat_semi_for_macro_if_needed(&body); self.complain_if_pub_macro(vis, true); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true }))) + Ok(ItemKind::MacroDef(ident, ast::MacroDef { body, macro_rules: true })) } /// Item macro invocations or `macro_rules!` definitions need inherited visibility. diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 471966d086d5f..49ae6cb9b7264 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2922,7 +2922,7 @@ fn out_of_line_mod() { .unwrap() .unwrap(); - let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() }; + let ast::ItemKind::Mod(_, _, mod_kind) = &item.kind else { panic!() }; assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2); }); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 9d4b46cd30660..664bd4ad0a252 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -268,22 +268,22 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { fn visit_item(&mut self, i: &'ast ast::Item) { let target = match &i.kind { - ast::ItemKind::ExternCrate(_) => Target::ExternCrate, + ast::ItemKind::ExternCrate(..) => Target::ExternCrate, ast::ItemKind::Use(_) => Target::Use, ast::ItemKind::Static(_) => Target::Static, ast::ItemKind::Const(_) => Target::Const, ast::ItemKind::Fn(_) | ast::ItemKind::Delegation(..) => Target::Fn, - ast::ItemKind::Mod(_, _) => Target::Mod, + ast::ItemKind::Mod(..) => Target::Mod, ast::ItemKind::ForeignMod(_) => Target::ForeignFn, ast::ItemKind::GlobalAsm(_) => Target::GlobalAsm, ast::ItemKind::TyAlias(_) => Target::TyAlias, - ast::ItemKind::Enum(_, _) => Target::Enum, - ast::ItemKind::Struct(_, _) => Target::Struct, - ast::ItemKind::Union(_, _) => Target::Union, + ast::ItemKind::Enum(..) => Target::Enum, + ast::ItemKind::Struct(..) => Target::Struct, + ast::ItemKind::Union(..) => Target::Union, ast::ItemKind::Trait(_) => Target::Trait, - ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias, + ast::ItemKind::TraitAlias(..) => Target::TraitAlias, ast::ItemKind::Impl(_) => Target::Impl, - ast::ItemKind::MacroDef(_) => Target::MacroDef, + ast::ItemKind::MacroDef(..) => Target::MacroDef, ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => { unreachable!("macros should have been expanded") } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 97fbf7e378acf..7f29f1a084e6f 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item, - ItemKind, MetaItemKind, NodeId, StmtKind, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, ForeignItem, + ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, }; use rustc_attr_parsing as attr; use rustc_expand::base::ResolverExpand; @@ -735,7 +735,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; - let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); let feed = self.r.feed(item.id); @@ -762,9 +761,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, ident) => { self.build_reduced_graph_for_extern_crate( orig_name, + ident, item, local_def_id, vis, @@ -772,7 +772,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } - ItemKind::Mod(.., ref mod_kind) => { + ItemKind::Mod(_, ident, ref mod_kind) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), @@ -792,10 +792,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the value namespace. - ItemKind::Const(..) | ItemKind::Delegation(..) | ItemKind::Static(..) => { + ItemKind::Const(box ConstItem { ident, .. }) + | ItemKind::Delegation(box Delegation { ident, .. }) + | ItemKind::Static(box StaticItem { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } - ItemKind::Fn(..) => { + ItemKind::Fn(box ast::Fn { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -804,11 +806,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(..) | ItemKind::TraitAlias(..) => { + ItemKind::TyAlias(box ast::TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } - ItemKind::Enum(_, _) | ItemKind::Trait(..) => { + ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { let module = self.r.new_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), @@ -821,7 +823,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in both the type and value namespaces. - ItemKind::Struct(ref vdata, _) => { + ItemKind::Struct(ident, ref vdata, _) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, @@ -872,7 +874,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } } - ItemKind::Union(ref vdata, _) => { + ItemKind::Union(ident, ref vdata, _) => { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, @@ -898,12 +900,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn build_reduced_graph_for_extern_crate( &mut self, orig_name: Option, + ident: Ident, item: &Item, local_def_id: LocalDefId, vis: ty::Visibility, parent: Module<'ra>, ) { - let ident = item.ident; let sp = item.span; let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; @@ -987,7 +989,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { + fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) { let feed = self.r.feed(item.id); let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); @@ -1000,7 +1002,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); - self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); + self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion)); self.r.feed_visibility(feed, vis); } @@ -1043,7 +1045,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { span: item.span, }); } - if let ItemKind::ExternCrate(Some(orig_name)) = item.kind + if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind && orig_name == kw::SelfLower { self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); @@ -1177,11 +1179,15 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) } - fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { + fn proc_macro_stub( + &self, + item: &ast::Item, + fn_ident: Ident, + ) -> Option<(MacroKind, Ident, Span)> { if ast::attr::contains_name(&item.attrs, sym::proc_macro) { - return Some((MacroKind::Bang, item.ident, item.span)); + return Some((MacroKind::Bang, fn_ident, item.span)); } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) { - return Some((MacroKind::Attr, item.ident, item.span)); + return Some((MacroKind::Attr, fn_ident, item.span)); } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) && let Some(meta_item_inner) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) @@ -1214,17 +1220,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let feed = self.r.feed(item.id); let def_id = feed.key(); let (res, ident, span, macro_rules) = match &item.kind { - ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), - ItemKind::Fn(..) => match self.proc_macro_stub(item) { - Some((macro_kind, ident, span)) => { - let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); - let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); - self.r.macro_map.insert(def_id.to_def_id(), macro_data); - self.r.proc_macro_stubs.insert(def_id); - (res, ident, span, false) + ItemKind::MacroDef(ident, def) => { + (self.res(def_id), *ident, item.span, def.macro_rules) + } + ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => { + match self.proc_macro_stub(item, *fn_ident) { + Some((macro_kind, ident, span)) => { + let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); + let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); + self.r.macro_map.insert(def_id.to_def_id(), macro_data); + self.r.proc_macro_stubs.insert(def_id); + (res, ident, span, false) + } + None => return parent_scope.macro_rules, } - None => return parent_scope.macro_rules, - }, + } _ => unreachable!(), }; @@ -1327,8 +1337,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // Visit attributes after items for backward compatibility. // This way they can use `macro_rules` defined later. self.visit_vis(&item.vis); - self.visit_ident(&item.ident); - item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self); + item.kind.walk(item.span, item.id, &item.vis, (), self); visit::walk_list!(self, visit_attribute, &item.attrs); } _ => visit::walk_item(self, item), @@ -1358,7 +1367,10 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return; } - self.build_reduced_graph_for_foreign_item(foreign_item); + // `unwrap` is safe because `MacCall` has been excluded, and other foreign item kinds have + // an ident. + let ident = foreign_item.kind.ident().unwrap(); + self.build_reduced_graph_for_foreign_item(foreign_item, ident); visit::walk_item(self, foreign_item); } @@ -1413,13 +1425,16 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { AssocItemKind::Type(..) => TypeNS, AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above }; + // `unwrap` is safe because `MacCall`/`DelegationMac` have been excluded, and other foreign + // item kinds have an ident. + let ident = item.kind.ident().unwrap(); if ctxt == AssocCtxt::Trait { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; - self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); + self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion)); } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) { let impl_def_id = self.r.tcx.local_parent(local_def_id); - let key = BindingKey::new(item.ident.normalize_to_macros_2_0(), ns); + let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns); self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key); } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 51ff4aa834baa..e97233e97ce55 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -219,14 +219,14 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // because this means that they were generated in some fashion by the // compiler and we don't need to consider them. ast::ItemKind::Use(..) if item.span.is_dummy() => return, - ast::ItemKind::ExternCrate(orig_name) => { + ast::ItemKind::ExternCrate(orig_name, ident) => { self.extern_crate_items.push(ExternCrateToLint { id: item.id, span: item.span, vis_span: item.vis.span, span_with_attributes: item.span_with_attributes(), has_attrs: !item.attrs.is_empty(), - ident: item.ident, + ident, renames: orig_name.is_some(), }); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6f48a75d61742..6ad056edbaf85 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -122,7 +122,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, - ItemKind::MacroDef(def) => { + ItemKind::MacroDef(ident, def) => { let edition = i.span.edition(); // FIXME(jdonszelmann) make one of these in the resolver? @@ -141,7 +141,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ); let macro_data = - self.resolver.compile_macro(def, i.ident, &attrs, i.span, i.id, edition); + self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition); let macro_kind = macro_data.ext.macro_kind(); opt_macro_data = Some(macro_data); DefKind::Macro(macro_kind) @@ -152,7 +152,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { return self.visit_macro_invoc(i.id); } }; - let def_id = self.create_def(i.id, Some(i.ident.name), def_kind, i.span); + let def_id = + self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); if let Some(macro_data) = opt_macro_data { self.resolver.macro_map.insert(def_id.to_def_id(), macro_data); @@ -161,7 +162,8 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { self.with_parent(def_id, |this| { this.with_impl_trait(ImplTraitContext::Existential, |this| { match i.kind { - ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { + ItemKind::Struct(_, ref struct_def, _) + | ItemKind::Union(_, ref struct_def, _) => { // If this is a unit or tuple-like struct, register the constructor. if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) { this.create_def( @@ -183,7 +185,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { match fn_kind { FnKind::Fn( _ctxt, - _ident, _vis, Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. }, ) if let Some(coroutine_kind) = header.coroutine_kind => { @@ -234,8 +235,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { - let def_kind = match fi.kind { + let (ident, def_kind) = match fi.kind { ForeignItemKind::Static(box StaticItem { + ident, ty: _, mutability, expr: _, @@ -247,14 +249,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ast::Safety::Safe(_) => hir::Safety::Safe, }; - DefKind::Static { safety, mutability, nested: false } + (ident, DefKind::Static { safety, mutability, nested: false }) } - ForeignItemKind::Fn(_) => DefKind::Fn, - ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, + ForeignItemKind::Fn(box Fn { ident, .. }) => (ident, DefKind::Fn), + ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => (ident, DefKind::ForeignTy), ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), }; - let def = self.create_def(fi.id, Some(fi.ident.name), def_kind, fi.span); + let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span); self.with_parent(def, |this| visit::walk_item(this, fi)); } @@ -318,16 +320,17 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { - let def_kind = match &i.kind { - AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn, - AssocItemKind::Const(..) => DefKind::AssocConst, - AssocItemKind::Type(..) => DefKind::AssocTy, + let (ident, def_kind) = match &i.kind { + AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => (*ident, DefKind::AssocFn), + AssocItemKind::Const(box ConstItem { ident, .. }) => (*ident, DefKind::AssocConst), + AssocItemKind::Type(box TyAlias { ident, .. }) => (*ident, DefKind::AssocTy), AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { return self.visit_macro_invoc(i.id); } }; - let def = self.create_def(i.id, Some(i.ident.name), def_kind, i.span); + let def = self.create_def(i.id, Some(ident.name), def_kind, i.span); self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt)); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 63ea8c4ced13c..7d6af12909c71 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3063,7 +3063,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { fn visit_item(&mut self, item: &'tcx ast::Item) { if self.target_module == item.id { - if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { + if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans, _)) = &item.kind { let inject = mod_spans.inject_use_span; if is_span_suitable_for_use_injection(inject) { self.first_legal_span = Some(inject); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 6ef4aa407253d..a5ca4565d7b42 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -252,7 +252,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> self.current_private_vis = prev_private_vis; } - ast::ItemKind::Enum(EnumDef { ref variants }, _) => { + ast::ItemKind::Enum(_, EnumDef { ref variants }, _) => { self.set_bindings_effective_visibilities(def_id); for variant in variants { let variant_def_id = self.r.local_def_id(variant.id); @@ -262,7 +262,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> } } - ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => { + ast::ItemKind::Struct(_, ref def, _) | ast::ItemKind::Union(_, ref def, _) => { for field in def.fields() { self.update_field(self.r.local_def_id(field.id), def_id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0d23ae501f04b..d4dd0800452a3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1025,8 +1025,8 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. }) - | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => { + FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, generics, .. }) + | FnKind::Fn(_, _, Fn { sig, generics, body: None, .. }) => { self.visit_fn_header(&sig.header); self.visit_generics(generics); self.with_lifetime_rib( @@ -1058,7 +1058,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r // Create a label rib for the function. this.with_label_rib(RibKind::FnOrCoroutine, |this| { match fn_kind { - FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => { + FnKind::Fn(_, _, Fn { sig, generics, contract, body, .. }) => { this.visit_generics(generics); let declaration = &sig.decl; @@ -2632,8 +2632,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } - let name = item.ident.name; - debug!("(resolving item) resolving {} ({:?})", name, item.kind); + debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); let def_kind = self.r.local_def_kind(item.id); match item.kind { @@ -2664,9 +2663,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::Union(_, ref generics) => { + ItemKind::Enum(_, _, ref generics) + | ItemKind::Struct(_, _, ref generics) + | ItemKind::Union(_, _, ref generics) => { self.resolve_adt(item, generics); } @@ -2710,7 +2709,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::TraitAlias(ref generics, ref bounds) => { + ItemKind::TraitAlias(_, ref generics, ref bounds) => { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, @@ -2748,7 +2747,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ItemKind::Static(box ast::StaticItem { - ref ty, ref expr, ref define_opaque, .. + ident, + ref ty, + ref expr, + ref define_opaque, + .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib( @@ -2762,13 +2765,14 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. - this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static))); + this.resolve_const_body(expr, Some((ident, ConstantItemKind::Static))); } }); self.resolve_define_opaques(define_opaque); } ItemKind::Const(box ast::ConstItem { + ident, ref generics, ref ty, ref expr, @@ -2801,10 +2805,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); if let Some(expr) = expr { - this.resolve_const_body( - expr, - Some((item.ident, ConstantItemKind::Const)), - ); + this.resolve_const_body(expr, Some((ident, ConstantItemKind::Const))); } }, ); @@ -2821,7 +2822,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.future_proof_import(use_tree); } - ItemKind::MacroDef(ref macro_def) => { + ItemKind::MacroDef(_, ref macro_def) => { // Maintain macro_rules scopes in the same way as during early resolution // for diagnostics and doc links. if macro_def.macro_rules { @@ -3319,7 +3320,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); match &item.kind { AssocItemKind::Const(box ast::ConstItem { - generics, ty, expr, define_opaque, .. + ident, + generics, + ty, + expr, + define_opaque, + .. }) => { debug!("resolve_implementation AssocItemKind::Const"); self.with_generic_param_rib( @@ -3350,7 +3356,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, ValueNS, item.span, @@ -3376,7 +3382,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_define_opaques(define_opaque); } - AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => { + AssocItemKind::Fn(box Fn { ident, generics, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( @@ -3392,7 +3398,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, ValueNS, item.span, @@ -3406,7 +3412,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_define_opaques(define_opaque); } - AssocItemKind::Type(box TyAlias { generics, .. }) => { + AssocItemKind::Type(box TyAlias { ident, generics, .. }) => { self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); debug!("resolve_implementation AssocItemKind::Type"); // We also need a new scope for the impl item type parameters. @@ -3424,7 +3430,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // exists in trait this.check_trait_item( item.id, - item.ident, + *ident, &item.kind, TypeNS, item.span, @@ -3451,7 +3457,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this| { this.check_trait_item( item.id, - item.ident, + delegation.ident, &item.kind, ValueNS, item.span, @@ -4337,7 +4343,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let Some(items) = self.diag_metadata.current_trait_assoc_items && let [Segment { ident, .. }] = path && items.iter().any(|item| { - item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_)) + if let AssocItemKind::Type(alias) = &item.kind + && alias.ident == *ident + { + true + } else { + false + } }) { let mut diag = self.r.tcx.dcx().struct_allow(""); @@ -5159,12 +5171,12 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { ItemKind::TyAlias(box TyAlias { generics, .. }) | ItemKind::Const(box ConstItem { generics, .. }) | ItemKind::Fn(box Fn { generics, .. }) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) | ItemKind::Impl(box Impl { generics, .. }) | ItemKind::Trait(box Trait { generics, .. }) - | ItemKind::TraitAlias(generics, _) => { + | ItemKind::TraitAlias(_, generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e40f84e7e598e..2a2b1ecef1613 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -224,12 +224,17 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diag_metadata.current_function && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind && let Some(items) = self.diag_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - i.ident.name == item_str.name + if let Some(ident) = i.kind.ident() + && ident.name == item_str.name + { // Don't suggest if the item is in Fn signature arguments (#112590). - && !sig.span.contains(item_span) + !sig.span.contains(item_span) + } else { + false + } }) { let sp = item_span.shrink_to_lo(); @@ -268,14 +273,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // you can't call `fn foo(&self)` from `fn bar()` (#115992). // We also want to mention that the method exists. span_label = Some(( - item.ident.span, + fn_.ident.span, "a method by that name is available on `Self` here", )); None } AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => { span_label = Some(( - item.ident.span, + fn_.ident.span, "an associated function by that name is available on `Self` here", )); None @@ -604,7 +609,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); if !self.self_value_is_available(path[0].ident.span) { - if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) = + if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) = &self.diag_metadata.current_function { let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) { @@ -1064,15 +1069,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } err.code(E0411); err.span_label(span, "`Self` is only available in impls, traits, and type definitions"); - if let Some(item_kind) = self.diag_metadata.current_item { - if !item_kind.ident.span.is_dummy() { + if let Some(item) = self.diag_metadata.current_item { + if let Some(ident) = item.kind.ident() { err.span_label( - item_kind.ident.span, - format!( - "`Self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), + ident.span, + format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()), ); } } @@ -1150,17 +1151,14 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } } - } else if let Some(item_kind) = self.diag_metadata.current_item { - if matches!(item_kind.kind, ItemKind::Delegation(..)) { - err.span_label(item_kind.span, format!("delegation supports {self_from_macro}")); + } else if let Some(item) = self.diag_metadata.current_item { + if matches!(item.kind, ItemKind::Delegation(..)) { + err.span_label(item.span, format!("delegation supports {self_from_macro}")); } else { + let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span }; err.span_label( - item_kind.ident.span, - format!( - "`self` not allowed in {} {}", - item_kind.kind.article(), - item_kind.kind.descr() - ), + span, + format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()), ); } } @@ -2196,7 +2194,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(items) = self.diag_metadata.current_trait_assoc_items { for assoc_item in items { - if assoc_item.ident == ident { + if let Some(assoc_ident) = assoc_item.kind.ident() + && assoc_ident == ident + { return Some(match &assoc_item.kind { ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst, ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => { @@ -2735,7 +2735,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return None; } match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) { - (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => { + (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } ( @@ -3400,7 +3400,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { let pre = if lt.kind == MissingLifetimeKind::Ampersand && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && !sig.decl.inputs.is_empty() && let sugg = sig .decl @@ -3441,7 +3441,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } else if (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output && !sig.decl.inputs.is_empty() && let arg_refs = sig @@ -3501,7 +3501,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand; let mut sugg = vec![(lt.span, String::new())]; if let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind + && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ty) = &sig.decl.output { let mut lt_finder = diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 56b1e76ae8cfd..4edd5433de6cd 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -350,21 +350,21 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result { + ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => { // We only push if it's the top item because otherwise, we would duplicate // its content since the top-level item was already added. - if item.ident.name == sym::main { + if fn_item.ident.name == sym::main { info.has_main_fn = true; } } - ast::ItemKind::ExternCrate(original) => { + ast::ItemKind::ExternCrate(original, ident) => { is_extern_crate = true; if !info.already_has_extern_crate && let Some(crate_name) = crate_name { info.already_has_extern_crate = match original { Some(name) => name.as_str() == *crate_name, - None => item.ident.as_str() == *crate_name, + None => ident.as_str() == *crate_name, }; } } diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs index 7d86bd3e540a1..c2aac7ca090bb 100644 --- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs +++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs @@ -53,7 +53,7 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); impl EarlyLintPass for CrateInMacroDef { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::MacroDef(macro_def) = &item.kind + if let ItemKind::MacroDef(_, macro_def) = &item.kind && item.attrs.iter().any(is_macro_export) && let Some(span) = contains_unhygienic_crate_reference(¯o_def.body.tokens) { diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 3008082c2329d..f6c10da1596b2 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -13,16 +13,16 @@ use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::{FileName, Pos, sym}; +use rustc_span::{FileName, Ident, Pos, sym}; use super::Fragments; -fn get_test_spans(item: &Item, test_attr_spans: &mut Vec>) { +fn get_test_spans(item: &Item, ident: Ident, test_attr_spans: &mut Vec>) { test_attr_spans.extend( item.attrs .iter() .find(|attr| attr.has_name(sym::test)) - .map(|attr| attr.span.lo().to_usize()..item.ident.span.hi().to_usize()), + .map(|attr| attr.span.lo().to_usize()..ident.span.hi().to_usize()), ); } @@ -64,10 +64,10 @@ pub fn check( match parser.parse_item(ForceCollect::No) { Ok(Some(item)) => match &item.kind { ItemKind::Fn(box Fn { - sig, body: Some(block), .. - }) if item.ident.name == sym::main => { + ident, sig, body: Some(block), .. + }) if ident.name == sym::main => { if !ignore { - get_test_spans(&item, &mut test_attr_spans); + get_test_spans(&item, *ident, &mut test_attr_spans); } let is_async = matches!(sig.header.coroutine_kind, Some(CoroutineKind::Async { .. })); let returns_nothing = match &sig.decl.output { @@ -85,10 +85,10 @@ pub fn check( } }, // Another function was found; this case is ignored for needless_doctest_main - ItemKind::Fn(box Fn { .. }) => { + ItemKind::Fn(fn_) => { eligible = false; if !ignore { - get_test_spans(&item, &mut test_attr_spans); + get_test_spans(&item, fn_.ident, &mut test_attr_spans); } }, // Tests with one of these items are ignored diff --git a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs index 1dac7b971f957..243c99a19ce1b 100644 --- a/src/tools/clippy/clippy_lints/src/duplicate_mod.rs +++ b/src/tools/clippy/clippy_lints/src/duplicate_mod.rs @@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]); impl EarlyLintPass for DuplicateMod { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind + if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind && let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span) && let Some(local_path) = real.into_local_path() && let Ok(absolute_path) = local_path.canonicalize() diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index 80c2b03c41cf4..899b5c5952614 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -9,7 +9,7 @@ use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; -use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, sym}; declare_clippy_lint! { /// ### What it does @@ -375,21 +375,21 @@ impl EmptyLineAfter { &mut self, cx: &EarlyContext<'_>, kind: &ItemKind, - ident: &Ident, + ident: &Option, span: Span, attrs: &[Attribute], id: NodeId, ) { self.items.push(ItemInfo { kind: kind.descr(), - name: ident.name, - span: if span.contains(ident.span) { + name: if let Some(ident) = ident { ident.name } else { sym::dummy }, + span: if let Some(ident) = ident { span.with_hi(ident.span.hi()) } else { span.with_hi(span.lo()) }, mod_items: match kind { - ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items + ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items .iter() .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_))) .map(|i| i.id) @@ -471,7 +471,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.ident, + &item.kind.ident(), item.span, &item.attrs, item.id, @@ -482,7 +482,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.ident, + &item.kind.ident(), item.span, &item.attrs, item.id, @@ -490,6 +490,6 @@ impl EarlyLintPass for EmptyLineAfter { } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id); + self.check_item_kind(cx, &item.kind, &item.kind.ident(), item.span, &item.attrs, item.id); } } diff --git a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs index 743ec5b9ea7fb..7d87f04fef9d8 100644 --- a/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs +++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs @@ -74,10 +74,9 @@ declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM impl EarlyLintPass for EmptyWithBrackets { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let span_after_ident = item.span.with_lo(item.ident.span.hi()); - - if let ItemKind::Struct(var_data, _) = &item.kind + if let ItemKind::Struct(ident, var_data, _) = &item.kind && has_brackets(var_data) + && let span_after_ident = item.span.with_lo(ident.span.hi()) && has_no_fields(cx, var_data, span_after_ident) { span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs index ba2b37fbf11a3..aae8291905d37 100644 --- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs @@ -51,7 +51,7 @@ declare_lint_pass!(FieldScopedVisibilityModifiers => [FIELD_SCOPED_VISIBILITY_MO impl EarlyLintPass for FieldScopedVisibilityModifiers { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(ref st, _) = item.kind else { + let ItemKind::Struct(_, ref st, _) = item.kind else { return; }; for field in st.fields() { diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 0e1980a6acb61..4b32ba83b325e 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs @@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]); impl EarlyLintPass for MultipleBoundLocations { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) { - if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind + if let FnKind::Fn(_, _, Fn { generics, .. }) = kind && !generics.params.is_empty() && !generics.where_clause.predicates.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs index 267e2067e101a..cda752d003fa0 100644 --- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs +++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs @@ -41,7 +41,7 @@ declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]); impl EarlyLintPass for PartialPubFields { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let ItemKind::Struct(ref st, _) = item.kind else { + let ItemKind::Struct(_, ref st, _) = item.kind else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs index fa08245350429..35f80b2acda68 100644 --- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs +++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs @@ -174,11 +174,11 @@ impl SingleComponentPathImports { } match &item.kind { - ItemKind::Mod(_, ModKind::Loaded(items, ..)) => { + ItemKind::Mod(_, _, ModKind::Loaded(items, ..)) => { self.check_mod(items); }, - ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => { - macros.push(item.ident.name); + ItemKind::MacroDef(ident, MacroDef { macro_rules: true, .. }) => { + macros.push(ident.name); }, ItemKind::Use(use_tree) => { let segments = &use_tree.prefix.segments; diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b16..ff63eb505a5c3 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -321,17 +321,18 @@ pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool { } pub fn eq_item(l: &Item, r: &Item, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool { - eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) + over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) } #[expect(clippy::similar_names, clippy::too_many_lines)] // Just a big match statement pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { use ItemKind::*; match (l, r) { - (ExternCrate(l), ExternCrate(r)) => l == r, + (ExternCrate(ls, li), ExternCrate(rs, ri)) => ls == rs && eq_id(*li, *ri), (Use(l), Use(r)) => eq_use_tree(l, r), ( Static(box StaticItem { + ident: li, ty: lt, mutability: lm, expr: le, @@ -339,16 +340,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { define_opaque: _, }), Static(box StaticItem { + ident: ri, ty: rt, mutability: rm, expr: re, safety: rs, define_opaque: _, }), - ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => eq_id(*li, *ri) + && lm == rm + && ls == rs + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()), ( Const(box ConstItem { defaultness: ld, + ident: li, generics: lg, ty: lt, expr: le, @@ -356,16 +363,22 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { }), Const(box ConstItem { defaultness: rd, + ident: ri, generics: rg, ty: rt, expr: re, define_opaque: _, }), - ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()), ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -374,6 +387,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -382,12 +396,14 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) }, - (Mod(lu, lmk), Mod(ru, rmk)) => { - lu == ru + (Mod(ls, li, lmk), Mod(rs, ri, rmk)) => { + ls == rs + && eq_id(*li, *ri) && match (lmk, rmk) { (ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => { linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind)) @@ -421,33 +437,40 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) }, - (Enum(le, lg), Enum(re, rg)) => over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg), - (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => { - eq_variant_data(lv, rv) && eq_generics(lg, rg) + (Enum(li, le, lg), Enum(ri, re, rg)) => { + eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg) + } + (Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => { + eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg) }, ( Trait(box ast::Trait { is_auto: la, safety: lu, + ident: li, generics: lg, bounds: lb, - items: li, + items: lis, }), Trait(box ast::Trait { is_auto: ra, safety: ru, + ident: ri, generics: rg, bounds: rb, - items: ri, + items: ris, }), ) => { la == ra && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) - && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) + && over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, - (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), + (TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => { + eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) + } ( Impl(box ast::Impl { safety: lu, @@ -480,7 +503,9 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, (MacCall(l), MacCall(r)) => eq_mac_call(l, r), - (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body), + (MacroDef(li, ld), MacroDef(ri, rd)) => { + eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body) + } _ => false, } } @@ -490,6 +515,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { match (l, r) { ( Static(box StaticItem { + ident: li, ty: lt, mutability: lm, expr: le, @@ -497,17 +523,25 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { define_opaque: _, }), Static(box StaticItem { + ident: ri, ty: rt, mutability: rm, expr: re, safety: rs, define_opaque: _, }), - ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs, + ) => { + eq_id(*li, *ri) + && eq_ty(lt, rt) + && lm == rm + && eq_expr_opt(le.as_ref(), re.as_ref()) + && ls == rs + } ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -516,6 +550,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -524,6 +559,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) @@ -560,6 +596,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ( Const(box ConstItem { defaultness: ld, + ident: li, generics: lg, ty: lt, expr: le, @@ -567,16 +604,24 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { }), Const(box ConstItem { defaultness: rd, + ident: ri, generics: rg, ty: rt, expr: re, define_opaque: _, }), - ) => eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()), + ) => { + eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && eq_ty(lt, rt) + && eq_expr_opt(le.as_ref(), re.as_ref()) + } ( Fn(box ast::Fn { defaultness: ld, sig: lf, + ident: li, generics: lg, contract: lc, body: lb, @@ -585,6 +630,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { Fn(box ast::Fn { defaultness: rd, sig: rf, + ident: ri, generics: rg, contract: rc, body: rb, @@ -593,6 +639,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) + && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_opt_fn_contract(lc, rc) && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r)) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index fdda885b7298d..322af97d9dc47 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -333,12 +333,12 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => { + visit::FnKind::Fn(visit::FnCtxt::Assoc(..), vis, ast::Fn { sig, generics, .. }) => { let mut fn_sig = FnSig::from_method_sig(sig, generics, vis); fn_sig.defaultness = defaultness; fn_sig } - visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig { + visit::FnKind::Fn(_, vis, ast::Fn { sig, generics, .. }) => FnSig { decl, generics, ext: sig.header.ext, @@ -750,11 +750,10 @@ impl<'a> FmtVisitor<'a> { (Type(lty), Type(rty)) if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) => { - a.ident.as_str().cmp(b.ident.as_str()) - } - (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => { - a.ident.as_str().cmp(b.ident.as_str()) + lty.ident.as_str().cmp(rty.ident.as_str()) } + (Const(ca), Const(cb)) => ca.ident.as_str().cmp(cb.ident.as_str()), + (MacCall(..), MacCall(..)) => Ordering::Equal, (Fn(..), Fn(..)) | (Delegation(..), Delegation(..)) => { a.span.lo().cmp(&b.span.lo()) } @@ -1105,14 +1104,16 @@ impl<'a> StructParts<'a> { } pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (prefix, def, generics) = match item.kind { - ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), - ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), + let (prefix, def, ident, generics) = match item.kind { + ast::ItemKind::Struct(ident, ref def, ref generics) => { + ("struct ", def, ident, generics) + } + ast::ItemKind::Union(ident, ref def, ref generics) => ("union ", def, ident, generics), _ => unreachable!(), }; StructParts { prefix, - ident: item.ident, + ident, vis: &item.vis, def, generics: Some(generics), @@ -1168,6 +1169,7 @@ pub(crate) fn format_trait( let ast::Trait { is_auto, safety, + ident, ref generics, ref bounds, ref items, @@ -1186,13 +1188,13 @@ pub(crate) fn format_trait( let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = - rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?; + rewrite_generics(context, rewrite_ident(context, ident), generics, shape).ok()?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. if !bounds.is_empty() { // Retrieve *unnormalized* ident (See #6069) - let source_ident = context.snippet(item.ident.span); + let source_ident = context.snippet(ident.span); let ident_hi = context.snippet_provider.span_after(item.span, source_ident); let bound_hi = bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); @@ -1699,7 +1701,6 @@ struct TyAliasRewriteInfo<'c, 'g>( pub(crate) fn rewrite_type_alias<'a>( ty_alias_kind: &ast::TyAlias, vis: &ast::Visibility, - ident: Ident, context: &RewriteContext<'a>, indent: Indent, visitor_kind: ItemVisitorKind, @@ -1709,6 +1710,7 @@ pub(crate) fn rewrite_type_alias<'a>( let ast::TyAlias { defaultness, + ident, ref generics, ref bounds, ref ty, @@ -2022,14 +2024,23 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (defaultness, prefix, safety, ty, mutability, expr, generics) = match &item.kind { - ast::ItemKind::Static(s) => { - (None, "static", s.safety, &s.ty, s.mutability, &s.expr, None) - } + let (defaultness, prefix, safety, ident, ty, mutability, expr, generics) = match &item.kind + { + ast::ItemKind::Static(s) => ( + None, + "static", + s.safety, + s.ident, + &s.ty, + s.mutability, + &s.expr, + None, + ), ast::ItemKind::Const(c) => ( Some(c.defaultness), "const", ast::Safety::Default, + c.ident, &c.ty, ast::Mutability::Not, &c.expr, @@ -2041,7 +2052,7 @@ impl<'a> StaticParts<'a> { prefix, safety, vis: &item.vis, - ident: item.ident, + ident, generics, ty, mutability, @@ -2051,7 +2062,7 @@ impl<'a> StaticParts<'a> { } } - pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { + pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self { let (defaultness, ty, expr_opt, generics) = match &ti.kind { ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), @@ -2060,7 +2071,7 @@ impl<'a> StaticParts<'a> { prefix: "const", safety: ast::Safety::Default, vis: &ti.vis, - ident: ti.ident, + ident, generics, ty, mutability: ast::Mutability::Not, @@ -2070,7 +2081,7 @@ impl<'a> StaticParts<'a> { } } - pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { + pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self { let (defaultness, ty, expr, generics) = match &ii.kind { ast::AssocItemKind::Const(c) => (c.defaultness, &c.ty, &c.expr, Some(&c.generics)), _ => unreachable!(), @@ -2079,7 +2090,7 @@ impl<'a> StaticParts<'a> { prefix: "const", safety: ast::Safety::Default, vis: &ii.vis, - ident: ii.ident, + ident, generics, ty, mutability: ast::Mutability::Not, @@ -3440,6 +3451,7 @@ impl Rewrite for ast::ForeignItem { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -3451,7 +3463,8 @@ impl Rewrite for ast::ForeignItem { let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &self.vis, fn_kind), &sig.decl, self.span, defaultness, @@ -3462,7 +3475,7 @@ impl Rewrite for ast::ForeignItem { rewrite_fn_base( context, shape.indent, - self.ident, + ident, &FnSig::from_method_sig(sig, generics, &self.vis), span, FnBraceStyle::None, @@ -3481,7 +3494,7 @@ impl Rewrite for ast::ForeignItem { vis, safety, mut_str, - rewrite_ident(context, self.ident) + rewrite_ident(context, static_foreign_item.ident) ); // 1 = ; rewrite_assign_rhs( @@ -3497,15 +3510,7 @@ impl Rewrite for ast::ForeignItem { } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let kind = ItemVisitorKind::ForeignItem; - rewrite_type_alias( - ty_alias, - &self.vis, - self.ident, - context, - shape.indent, - kind, - self.span, - ) + rewrite_type_alias(ty_alias, &self.vis, context, shape.indent, kind, self.span) } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, context, shape, MacroPosition::Item) @@ -3568,12 +3573,13 @@ fn rewrite_attrs( pub(crate) fn rewrite_mod( context: &RewriteContext<'_>, item: &ast::Item, + ident: Ident, attrs_shape: Shape, ) -> Option { let mut result = String::with_capacity(32); result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); - result.push_str(rewrite_ident(context, item.ident)); + result.push_str(rewrite_ident(context, ident)); result.push(';'); rewrite_attrs(context, item, &result, attrs_shape) } @@ -3600,7 +3606,7 @@ pub(crate) fn rewrite_extern_crate( pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { !matches!( item.kind, - ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) + ast::ItemKind::Mod(_, _, ast::ModKind::Loaded(_, ast::Inline::Yes, _, _)) ) } diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs index a40ee7f66a978..bc5a6d3e70402 100644 --- a/src/tools/rustfmt/src/modules.rs +++ b/src/tools/rustfmt/src/modules.rs @@ -152,7 +152,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { let mut visitor = visitor::CfgIfVisitor::new(self.psess); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = module_item.item.kind { self.visit_sub_mod( &module_item.item, Module::new( @@ -178,7 +178,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { continue; } - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind { let span = item.span; self.visit_sub_mod( &item, @@ -204,7 +204,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + if let ast::ItemKind::Mod(_, _, ref sub_mod_kind) = item.kind { let span = item.span; self.visit_sub_mod( item, @@ -248,7 +248,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { if is_mod_decl(item) { // mod foo; // Look for an extern file. - self.find_external_module(item.ident, &item.attrs, sub_mod) + self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod) } else { // An internal module (`mod foo { /* ... */ }`); Ok(Some(SubModKind::Internal(item))) @@ -291,7 +291,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) } SubModKind::Internal(item) => { - self.push_inline_mod_directory(item.ident, &item.attrs); + self.push_inline_mod_directory(item.kind.ident().unwrap(), &item.attrs); self.visit_sub_mod_after_directory_update(sub_mod, None) } SubModKind::MultiExternal(mods) => { diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs index 8a31e0ac816e3..2460b61698ccf 100644 --- a/src/tools/rustfmt/src/reorder.rs +++ b/src/tools/rustfmt/src/reorder.rs @@ -25,14 +25,17 @@ use crate::visitor::FmtVisitor; /// Choose the ordering between the given two items. fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { match (&a.kind, &b.kind) { - (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { - a.ident.as_str().cmp(b.ident.as_str()) + (&ast::ItemKind::Mod(_, a_ident, _), &ast::ItemKind::Mod(_, b_ident, _)) => { + a_ident.as_str().cmp(b_ident.as_str()) } - (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { + ( + &ast::ItemKind::ExternCrate(ref a_name, a_ident), + &ast::ItemKind::ExternCrate(ref b_name, b_ident), + ) => { // `extern crate foo as bar;` // ^^^ Comparing this. - let a_orig_name = a_name.unwrap_or(a.ident.name); - let b_orig_name = b_name.unwrap_or(b.ident.name); + let a_orig_name = a_name.unwrap_or(a_ident.name); + let b_orig_name = b_name.unwrap_or(b_ident.name); let result = a_orig_name.as_str().cmp(b_orig_name.as_str()); if result != Ordering::Equal { return result; @@ -44,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (Some(..), None) => Ordering::Greater, (None, Some(..)) => Ordering::Less, (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.as_str().cmp(b.ident.as_str()), + (Some(..), Some(..)) => a_ident.as_str().cmp(b_ident.as_str()), } } _ => unreachable!(), @@ -69,7 +72,7 @@ fn rewrite_reorderable_item( ) -> Option { match item.kind { ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape), - ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape), + ast::ItemKind::Mod(_, ident, _) => rewrite_mod(context, item, ident, shape), _ => None, } } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index c73976d90b1e6..1dc0a9069231e 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -377,6 +377,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // on traits do not get handled here. pub(crate) fn visit_fn( &mut self, + ident: Ident, fk: visit::FnKind<'_>, fd: &ast::FnDecl, s: Span, @@ -388,7 +389,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite = match fk { visit::FnKind::Fn( _, - ident, _, ast::Fn { body: Some(ref b), .. @@ -397,7 +397,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { block = b; self.rewrite_fn_before_block( indent, - *ident, + ident, &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), ) @@ -444,7 +444,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let should_visit_node_again = match item.kind { // For use/extern crate items, skip rewriting attributes but check for a skip attribute. - ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => { + ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(..) => { if contains_skip(attrs) { self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span()); false @@ -497,11 +497,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent)); self.push_rewrite(item.span, rw); } - ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { + ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => { let shape = Shape::indented(self.block_indent, self.config); let rw = format_trait_alias( &self.get_context(), - item.ident, + ident, &item.vis, generics, generic_bounds, @@ -509,7 +509,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rw); } - ast::ItemKind::ExternCrate(_) => { + ast::ItemKind::ExternCrate(..) => { let rw = rewrite_extern_crate(&self.get_context(), item, self.shape()); let span = if attrs.is_empty() { item.span @@ -521,14 +521,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { self.visit_struct(&StructParts::from_item(item)); } - ast::ItemKind::Enum(ref def, ref generics) => { + ast::ItemKind::Enum(ident, ref def, ref generics) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.visit_enum(item.ident, &item.vis, def, generics, item.span); + self.visit_enum(ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(safety, ref mod_kind) => { + ast::ItemKind::Mod(safety, ident, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(mod_kind, safety, &item.vis, item.span, item.ident, attrs); + self.format_mod(mod_kind, safety, &item.vis, item.span, ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, MacroPosition::Item); @@ -544,6 +544,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -555,7 +556,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &item.vis, fn_kind), &sig.decl, item.span, defaultness, @@ -564,28 +566,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = self - .rewrite_required_fn( - indent, item.ident, sig, &item.vis, generics, item.span, - ) + .rewrite_required_fn(indent, ident, sig, &item.vis, generics, item.span) .ok(); self.push_rewrite(item.span, rewrite); } } ast::ItemKind::TyAlias(ref ty_alias) => { use ItemVisitorKind::Item; - self.visit_ty_alias_kind(ty_alias, &item.vis, item.ident, Item, item.span); + self.visit_ty_alias_kind(ty_alias, &item.vis, Item, item.span); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); } - ast::ItemKind::MacroDef(ref def) => { + ast::ItemKind::MacroDef(ident, ref def) => { let rewrite = rewrite_macro_def( &self.get_context(), self.shape(), self.block_indent, def, - item.ident, + ident, &item.vis, item.span, ) @@ -606,14 +606,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &mut self, ty_kind: &ast::TyAlias, vis: &ast::Visibility, - ident: Ident, visitor_kind: ItemVisitorKind, span: Span, ) { let rewrite = rewrite_type_alias( ty_kind, vis, - ident, &self.get_context(), self.block_indent, visitor_kind, @@ -642,16 +640,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // TODO(calebcartwright): consider enabling box_patterns feature gate match (&ai.kind, visitor_kind) { - (ast::AssocItemKind::Const(..), AssocTraitItem) => { - self.visit_static(&StaticParts::from_trait_item(ai)) + (ast::AssocItemKind::Const(c), AssocTraitItem) => { + self.visit_static(&StaticParts::from_trait_item(ai, c.ident)) } - (ast::AssocItemKind::Const(..), AssocImplItem) => { - self.visit_static(&StaticParts::from_impl_item(ai)) + (ast::AssocItemKind::Const(c), AssocImplItem) => { + self.visit_static(&StaticParts::from_impl_item(ai, c.ident)) } (ast::AssocItemKind::Fn(ref fn_kind), _) => { let ast::Fn { defaultness, ref sig, + ident, ref generics, ref body, .. @@ -660,7 +659,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let inner_attrs = inner_attributes(&ai.attrs); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind), + ident, + visit::FnKind::Fn(fn_ctxt, &ai.vis, fn_kind), &sig.decl, ai.span, defaultness, @@ -669,13 +669,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { let indent = self.block_indent; let rewrite = self - .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span) + .rewrite_required_fn(indent, fn_kind.ident, sig, &ai.vis, generics, ai.span) .ok(); self.push_rewrite(ai.span, rewrite); } } (ast::AssocItemKind::Type(ref ty_alias), _) => { - self.visit_ty_alias_kind(ty_alias, &ai.vis, ai.ident, visitor_kind, ai.span); + self.visit_ty_alias_kind(ty_alias, &ai.vis, visitor_kind, ai.span); } (ast::AssocItemKind::MacCall(ref mac), _) => { self.visit_mac(mac, MacroPosition::Item); diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 191daff2137d8..24e3894864787 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -10,9 +10,9 @@ ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 WherePredicate 72 ( 1.1%) 1 72 ast-stats-1 - BoundPredicate 72 ( 1.1%) 1 +ast-stats-1 ForeignItem 80 ( 1.2%) 1 80 +ast-stats-1 - Fn 80 ( 1.2%) 1 ast-stats-1 Local 80 ( 1.2%) 1 80 -ast-stats-1 ForeignItem 88 ( 1.3%) 1 88 -ast-stats-1 - Fn 88 ( 1.3%) 1 ast-stats-1 Arm 96 ( 1.4%) 2 48 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 Param 160 ( 2.4%) 4 40 @@ -23,37 +23,37 @@ ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 FieldDef 208 ( 3.1%) 2 104 ast-stats-1 Variant 208 ( 3.1%) 2 104 -ast-stats-1 AssocItem 352 ( 5.3%) 4 88 -ast-stats-1 - Fn 176 ( 2.6%) 2 -ast-stats-1 - Type 176 ( 2.6%) 2 -ast-stats-1 GenericBound 352 ( 5.3%) 4 88 -ast-stats-1 - Trait 352 ( 5.3%) 4 -ast-stats-1 GenericParam 480 ( 7.2%) 5 96 +ast-stats-1 AssocItem 320 ( 4.8%) 4 80 +ast-stats-1 - Fn 160 ( 2.4%) 2 +ast-stats-1 - Type 160 ( 2.4%) 2 +ast-stats-1 GenericBound 352 ( 5.2%) 4 88 +ast-stats-1 - Trait 352 ( 5.2%) 4 +ast-stats-1 GenericParam 480 ( 7.1%) 5 96 ast-stats-1 Pat 504 ( 7.5%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 -ast-stats-1 - Ident 360 ( 5.4%) 5 +ast-stats-1 - Ident 360 ( 5.3%) 5 ast-stats-1 Expr 576 ( 8.6%) 8 72 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.1%) 2 ast-stats-1 - Block 216 ( 3.2%) 3 -ast-stats-1 PathSegment 744 (11.1%) 31 24 -ast-stats-1 Ty 896 (13.4%) 14 64 +ast-stats-1 PathSegment 744 (11.0%) 31 24 +ast-stats-1 Ty 896 (13.3%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 ast-stats-1 - Path 640 ( 9.5%) 10 -ast-stats-1 Item 1_224 (18.3%) 9 136 -ast-stats-1 - Enum 136 ( 2.0%) 1 -ast-stats-1 - ForeignMod 136 ( 2.0%) 1 -ast-stats-1 - Impl 136 ( 2.0%) 1 -ast-stats-1 - Trait 136 ( 2.0%) 1 -ast-stats-1 - Fn 272 ( 4.1%) 2 -ast-stats-1 - Use 408 ( 6.1%) 3 +ast-stats-1 Item 1_296 (19.2%) 9 144 +ast-stats-1 - Enum 144 ( 2.1%) 1 +ast-stats-1 - ForeignMod 144 ( 2.1%) 1 +ast-stats-1 - Impl 144 ( 2.1%) 1 +ast-stats-1 - Trait 144 ( 2.1%) 1 +ast-stats-1 - Fn 288 ( 4.3%) 2 +ast-stats-1 - Use 432 ( 6.4%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_704 116 +ast-stats-1 Total 6_736 116 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -61,12 +61,12 @@ ast-stats-2 ---------------------------------------------------------------- ast-stats-2 Crate 40 ( 0.5%) 1 40 ast-stats-2 GenericArgs 40 ( 0.5%) 1 40 ast-stats-2 - AngleBracketed 40 ( 0.5%) 1 -ast-stats-2 ExprField 48 ( 0.7%) 1 48 +ast-stats-2 ExprField 48 ( 0.6%) 1 48 ast-stats-2 WherePredicate 72 ( 1.0%) 1 72 ast-stats-2 - BoundPredicate 72 ( 1.0%) 1 +ast-stats-2 ForeignItem 80 ( 1.1%) 1 80 +ast-stats-2 - Fn 80 ( 1.1%) 1 ast-stats-2 Local 80 ( 1.1%) 1 80 -ast-stats-2 ForeignItem 88 ( 1.2%) 1 88 -ast-stats-2 - Fn 88 ( 1.2%) 1 ast-stats-2 Arm 96 ( 1.3%) 2 48 ast-stats-2 FnDecl 120 ( 1.6%) 5 24 ast-stats-2 InlineAsm 120 ( 1.6%) 1 120 @@ -81,13 +81,13 @@ ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Block 192 ( 2.6%) 6 32 ast-stats-2 FieldDef 208 ( 2.8%) 2 104 ast-stats-2 Variant 208 ( 2.8%) 2 104 -ast-stats-2 AssocItem 352 ( 4.8%) 4 88 -ast-stats-2 - Fn 176 ( 2.4%) 2 -ast-stats-2 - Type 176 ( 2.4%) 2 +ast-stats-2 AssocItem 320 ( 4.3%) 4 80 +ast-stats-2 - Fn 160 ( 2.2%) 2 +ast-stats-2 - Type 160 ( 2.2%) 2 ast-stats-2 GenericBound 352 ( 4.8%) 4 88 ast-stats-2 - Trait 352 ( 4.8%) 4 ast-stats-2 GenericParam 480 ( 6.5%) 5 96 -ast-stats-2 Pat 504 ( 6.9%) 7 72 +ast-stats-2 Pat 504 ( 6.8%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 4.9%) 5 @@ -96,24 +96,24 @@ ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Struct 72 ( 1.0%) 1 -ast-stats-2 - Lit 144 ( 2.0%) 2 +ast-stats-2 - Lit 144 ( 1.9%) 2 ast-stats-2 - Block 216 ( 2.9%) 3 -ast-stats-2 PathSegment 864 (11.8%) 36 24 -ast-stats-2 Ty 896 (12.2%) 14 64 +ast-stats-2 PathSegment 864 (11.7%) 36 24 +ast-stats-2 Ty 896 (12.1%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.7%) 2 -ast-stats-2 - Path 640 ( 8.7%) 10 -ast-stats-2 Item 1_496 (20.3%) 11 136 -ast-stats-2 - Enum 136 ( 1.8%) 1 -ast-stats-2 - ExternCrate 136 ( 1.8%) 1 -ast-stats-2 - ForeignMod 136 ( 1.8%) 1 -ast-stats-2 - Impl 136 ( 1.8%) 1 -ast-stats-2 - Trait 136 ( 1.8%) 1 -ast-stats-2 - Fn 272 ( 3.7%) 2 -ast-stats-2 - Use 544 ( 7.4%) 4 +ast-stats-2 - Path 640 ( 8.6%) 10 +ast-stats-2 Item 1_584 (21.4%) 11 144 +ast-stats-2 - Enum 144 ( 1.9%) 1 +ast-stats-2 - ExternCrate 144 ( 1.9%) 1 +ast-stats-2 - ForeignMod 144 ( 1.9%) 1 +ast-stats-2 - Impl 144 ( 1.9%) 1 +ast-stats-2 - Trait 144 ( 1.9%) 1 +ast-stats-2 - Fn 288 ( 3.9%) 2 +ast-stats-2 - Use 576 ( 7.8%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_352 127 +ast-stats-2 Total 7_400 127 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size From ec10833609aa63327437aabfaedfbe8a0edcc4d9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Apr 2025 14:49:58 +1100 Subject: [PATCH 232/333] Address review comments. --- .../rustc_ast_passes/src/ast_validation.rs | 16 ++-- .../src/proc_macro_harness.rs | 7 +- compiler/rustc_expand/src/expand.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 33 ++++---- .../rustc_resolve/src/build_reduced_graph.rs | 79 ++++++++++--------- compiler/rustc_resolve/src/def_collector.rs | 5 +- compiler/rustc_resolve/src/late.rs | 5 +- .../rustc_resolve/src/late/diagnostics.rs | 10 +-- .../clippy_lints/src/empty_line_after.rs | 15 ++-- .../clippy/clippy_utils/src/ast_utils/mod.rs | 14 +++- src/tools/rustfmt/src/visitor.rs | 2 +- tests/ui/custom_test_frameworks/full.rs | 7 +- 12 files changed, 101 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 86661f3f35905..839d5d3bb954d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -817,10 +817,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.has_proc_macro_decls = true; } - if attr::contains_name(&item.attrs, sym::no_mangle) { - if let Some(ident) = item.kind.ident() { - self.check_nomangle_item_asciionly(ident, item.span); - } + if let Some(ident) = item.kind.ident() + && attr::contains_name(&item.attrs, sym::no_mangle) + { + self.check_nomangle_item_asciionly(ident, item.span); } match &item.kind { @@ -1412,10 +1412,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - if attr::contains_name(&item.attrs, sym::no_mangle) { - if let Some(ident) = item.kind.ident() { - self.check_nomangle_item_asciionly(ident, item.span); - } + if let Some(ident) = item.kind.ident() + && attr::contains_name(&item.attrs, sym::no_mangle) + { + self.check_nomangle_item_asciionly(ident, item.span); } if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 7c25f26895ca0..8862965c0532c 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -213,10 +213,8 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; }; - // First up, make sure we're checking a bare function. If we're not then - // we're just not interested in this item. - // - // If we find one, try to locate a `#[proc_macro_derive]` attribute on it. + // Make sure we're checking a bare function. If we're not then we're + // just not interested any further in this item. let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind { fn_.ident } else { @@ -243,6 +241,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; } + // Try to locate a `#[proc_macro_derive]` attribute. if attr.has_name(sym::proc_macro_derive) { self.collect_custom_derive(item, fn_ident, attr); } else if attr.has_name(sym::proc_macro_attribute) { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d1dd454fa73d7..bca846d2ec423 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1223,9 +1223,7 @@ impl InvocationCollectorNode for P { // Work around borrow checker not seeing through `P`'s deref. let (span, mut attrs) = (node.span, mem::take(&mut node.attrs)); - let ItemKind::Mod(_, ident, mod_kind) = &mut node.kind else { unreachable!() }; - let ident = *ident; - + let ItemKind::Mod(_, ident, ref mut mod_kind) = node.kind else { unreachable!() }; let ecx = &mut collector.cx; let (file_path, dir_path, dir_ownership) = match mod_kind { ModKind::Loaded(_, inline, _, _) => { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ed6522850960d..e93fb2473fbfb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -243,8 +243,7 @@ impl<'a> Parser<'a> { // STATIC ITEM self.bump(); // `static` let mutability = self.parse_mutability(); - let item = self.parse_static_item(safety, mutability)?; - ItemKind::Static(Box::new(item)) + self.parse_static_item(safety, mutability)? } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -681,7 +680,7 @@ impl<'a> Parser<'a> { } None => (None, ty_first), // impl Type }; - let item_kind = ItemKind::Impl(Box::new(Impl { + Ok(ItemKind::Impl(Box::new(Impl { safety, polarity, defaultness, @@ -690,9 +689,7 @@ impl<'a> Parser<'a> { of_trait, self_ty, items: impl_items, - })); - - Ok(item_kind) + }))) } fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { @@ -1222,13 +1219,12 @@ impl<'a> Parser<'a> { safety = Safety::Unsafe(self.token.span); let _ = self.eat_keyword(exp!(Unsafe)); } - let module = ast::ForeignMod { + Ok(ItemKind::ForeignMod(ast::ForeignMod { extern_span, safety, abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, - }; - Ok(ItemKind::ForeignMod(module)) + })) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1370,7 +1366,8 @@ impl<'a> Parser<'a> { Ok(item_kind) } - /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in `mutability`. + /// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in + /// `mutability`. /// /// ```ebnf /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ; @@ -1379,7 +1376,7 @@ impl<'a> Parser<'a> { &mut self, safety: Safety, mutability: Mutability, - ) -> PResult<'a, StaticItem> { + ) -> PResult<'a, ItemKind> { let ident = self.parse_ident()?; if self.token == TokenKind::Lt && self.may_recover() { @@ -1391,7 +1388,8 @@ impl<'a> Parser<'a> { // FIXME: This could maybe benefit from `.may_recover()`? let ty = match (self.eat(exp!(Colon)), self.check(exp!(Eq)) | self.check(exp!(Semi))) { (true, false) => self.parse_ty()?, - // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing type. + // If there wasn't a `:` or the colon was followed by a `=` or `;`, recover a missing + // type. (colon, _) => self.recover_missing_global_item_type(colon, Some(mutability)), }; @@ -1399,7 +1397,8 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok(StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }) + let item = StaticItem { ident, ty, safety, mutability, expr, define_opaque: None }; + Ok(ItemKind::Static(Box::new(item))) } /// Parse a constant item with the prefix `"const"` already parsed. @@ -1537,7 +1536,7 @@ impl<'a> Parser<'a> { } let prev_span = self.prev_token.span; - let id = self.parse_ident()?; + let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; @@ -1548,10 +1547,10 @@ impl<'a> Parser<'a> { (thin_vec![], Trailing::No) } else { self.parse_delim_comma_seq(exp!(OpenBrace), exp!(CloseBrace), |p| { - p.parse_enum_variant(id.span) + p.parse_enum_variant(ident.span) }) .map_err(|mut err| { - err.span_label(id.span, "while parsing this enum"); + err.span_label(ident.span, "while parsing this enum"); if self.token == token::Colon { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); @@ -1577,7 +1576,7 @@ impl<'a> Parser<'a> { }; let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() }; - Ok(ItemKind::Enum(id, enum_definition, generics)) + Ok(ItemKind::Enum(ident, enum_definition, generics)) } fn parse_enum_variant(&mut self, span: Span) -> PResult<'a, Option> { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7f29f1a084e6f..4368f7882ff46 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -10,8 +10,8 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, ForeignItem, - ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, + ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias, }; use rustc_attr_parsing as attr; use rustc_expand::base::ResolverExpand; @@ -764,8 +764,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::ExternCrate(orig_name, ident) => { self.build_reduced_graph_for_extern_crate( orig_name, - ident, item, + ident, local_def_id, vis, parent, @@ -797,7 +797,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { | ItemKind::Static(box StaticItem { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); } - ItemKind::Fn(box ast::Fn { ident, .. }) => { + ItemKind::Fn(box Fn { ident, .. }) => { self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion)); // Functions introducing procedural macros reserve a slot @@ -806,7 +806,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items live in the type namespace. - ItemKind::TyAlias(box ast::TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { + ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } @@ -900,8 +900,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn build_reduced_graph_for_extern_crate( &mut self, orig_name: Option, - ident: Ident, item: &Item, + ident: Ident, local_def_id: LocalDefId, vis: ty::Visibility, parent: Module<'ra>, @@ -1362,14 +1362,16 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { - if let ForeignItemKind::MacCall(_) = foreign_item.kind { - self.visit_invoc_in_module(foreign_item.id); - return; - } + let ident = match foreign_item.kind { + ForeignItemKind::Static(box StaticItem { ident, .. }) + | ForeignItemKind::Fn(box Fn { ident, .. }) + | ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident, + ForeignItemKind::MacCall(_) => { + self.visit_invoc_in_module(foreign_item.id); + return; + } + }; - // `unwrap` is safe because `MacCall` has been excluded, and other foreign item kinds have - // an ident. - let ident = foreign_item.kind.ident().unwrap(); self.build_reduced_graph_for_foreign_item(foreign_item, ident); visit::walk_item(self, foreign_item); } @@ -1384,26 +1386,35 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - if let AssocItemKind::MacCall(_) = item.kind { - match ctxt { - AssocCtxt::Trait => { - self.visit_invoc_in_module(item.id); - } - AssocCtxt::Impl { .. } => { - let invoc_id = item.id.placeholder_to_expn_id(); - if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) { - self.r - .impl_unexpanded_invocations - .entry(self.r.invocation_parent(invoc_id)) - .or_default() - .insert(invoc_id); + let (ident, ns) = match item.kind { + AssocItemKind::Const(box ConstItem { ident, .. }) + | AssocItemKind::Fn(box Fn { ident, .. }) + | AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS), + + AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS), + + AssocItemKind::MacCall(_) => { + match ctxt { + AssocCtxt::Trait => { + self.visit_invoc_in_module(item.id); + } + AssocCtxt::Impl { .. } => { + let invoc_id = item.id.placeholder_to_expn_id(); + if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) { + self.r + .impl_unexpanded_invocations + .entry(self.r.invocation_parent(invoc_id)) + .or_default() + .insert(invoc_id); + } + self.visit_invoc(item.id); } - self.visit_invoc(item.id); } + return; } - return; - } + AssocItemKind::DelegationMac(..) => bug!(), + }; let vis = self.resolve_visibility(&item.vis); let feed = self.r.feed(item.id); let local_def_id = feed.key(); @@ -1418,16 +1429,6 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.feed_visibility(feed, vis); } - let ns = match item.kind { - AssocItemKind::Const(..) | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => { - ValueNS - } - AssocItemKind::Type(..) => TypeNS, - AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above - }; - // `unwrap` is safe because `MacCall`/`DelegationMac` have been excluded, and other foreign - // item kinds have an ident. - let ident = item.kind.ident().unwrap(); if ctxt == AssocCtxt::Trait { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6ad056edbaf85..13dfb59f27fc0 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -186,8 +186,11 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { FnKind::Fn( _ctxt, _vis, - Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. }, + Fn { + sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, .. + }, ) if let Some(coroutine_kind) = header.coroutine_kind => { + self.visit_ident(ident); self.visit_fn_header(header); self.visit_generics(generics); if let Some(contract) = contract { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d4dd0800452a3..20e19caf9096b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1025,9 +1025,10 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, generics, .. }) - | FnKind::Fn(_, _, Fn { sig, generics, body: None, .. }) => { + FnKind::Fn(FnCtxt::Foreign, _, Fn { sig, ident, generics, .. }) + | FnKind::Fn(_, _, Fn { sig, ident, generics, body: None, .. }) => { self.visit_fn_header(&sig.header); + self.visit_ident(ident); self.visit_generics(generics); self.with_lifetime_rib( LifetimeRibKind::AnonymousCreateParameter { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2a2b1ecef1613..b62bc6c45e0c5 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -227,14 +227,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind && let Some(items) = self.diag_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { - if let Some(ident) = i.kind.ident() - && ident.name == item_str.name - { + i.kind.ident().is_some_and(|ident| { // Don't suggest if the item is in Fn signature arguments (#112590). - !sig.span.contains(item_span) - } else { - false - } + ident.name == item_str.name && !sig.span.contains(item_span) + }) }) { let sp = item_span.shrink_to_lo(); diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index 899b5c5952614..c67dcd3c82b50 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -8,8 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle}; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::impl_lint_pass; -use rustc_span::symbol::kw; -use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, sym}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol, kw}; declare_clippy_lint! { /// ### What it does @@ -375,14 +374,16 @@ impl EmptyLineAfter { &mut self, cx: &EarlyContext<'_>, kind: &ItemKind, - ident: &Option, + ident: Option, span: Span, attrs: &[Attribute], id: NodeId, ) { self.items.push(ItemInfo { kind: kind.descr(), - name: if let Some(ident) = ident { ident.name } else { sym::dummy }, + // FIXME: this `sym::empty` can be leaked, see + // https://github.com/rust-lang/rust/pull/138740#discussion_r2021979899 + name: if let Some(ident) = ident { ident.name } else { kw::Empty }, span: if let Some(ident) = ident { span.with_hi(ident.span.hi()) } else { @@ -471,7 +472,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.kind.ident(), + item.kind.ident(), item.span, &item.attrs, item.id, @@ -482,7 +483,7 @@ impl EarlyLintPass for EmptyLineAfter { self.check_item_kind( cx, &item.kind.clone().into(), - &item.kind.ident(), + item.kind.ident(), item.span, &item.attrs, item.id, @@ -490,6 +491,6 @@ impl EarlyLintPass for EmptyLineAfter { } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - self.check_item_kind(cx, &item.kind, &item.kind.ident(), item.span, &item.attrs, item.id); + self.check_item_kind(cx, &item.kind, item.kind.ident(), item.span, &item.attrs, item.id); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index ff63eb505a5c3..eba576392ebce 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -567,20 +567,23 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ( TyAlias(box ast::TyAlias { defaultness: ld, + ident: li, generics: lg, + where_clauses: _, bounds: lb, ty: lt, - .. }), TyAlias(box ast::TyAlias { defaultness: rd, + ident: ri, generics: rg, + where_clauses: _, bounds: rb, ty: rt, - .. }), ) => { eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) @@ -647,20 +650,23 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ( Type(box TyAlias { defaultness: ld, + ident: li, generics: lg, + where_clauses: _, bounds: lb, ty: lt, - .. }), Type(box TyAlias { defaultness: rd, + ident: ri, generics: rg, + where_clauses: _, bounds: rb, ty: rt, - .. }), ) => { eq_defaultness(*ld, *rd) + && eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && both(lt.as_ref(), rt.as_ref(), |l, r| eq_ty(l, r)) diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 1dc0a9069231e..16d1f5105d5f9 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -623,13 +623,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_assoc_item(&mut self, ai: &ast::AssocItem, visitor_kind: ItemVisitorKind) { use ItemVisitorKind::*; - // TODO(calebcartwright): Not sure the skip spans are correct let assoc_ctxt = match visitor_kind { AssocTraitItem => visit::AssocCtxt::Trait, // There is no difference between trait and inherent assoc item formatting AssocImplItem => visit::AssocCtxt::Impl { of_trait: false }, _ => unreachable!(), }; + // TODO(calebcartwright): Not sure the skip spans are correct let skip_span = ai.span; skip_out_of_file_lines_range_visitor!(self, ai.span); diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs index 6be29f0418d61..57b55e9437bf3 100644 --- a/tests/ui/custom_test_frameworks/full.rs +++ b/tests/ui/custom_test_frameworks/full.rs @@ -28,12 +28,13 @@ const TEST_1: IsFoo = IsFoo("hello"); static TEST_2: IsFoo = IsFoo("foo"); // FIXME: `test_case` is currently ignored on anything other than -// fn/const/static. Should this be a warning/error? +// fn/const/static. This should be an error. Compare this with `#[test]` and +// #[bench] whose expanders emit "error: expected a non-associated function, +// found […]" if applied to invalid items. #[test_case] struct _S; -// FIXME: `test_case` is currently ignored on anything other than -// fn/const/static. Should this be a warning/error? +// FIXME: as above. #[test_case] impl _S { fn _f() {} From cb7ebf6f05a08a3dc7d2562eed1a3e3c5523ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 1 Apr 2025 07:57:05 +0200 Subject: [PATCH 233/333] Bump metadata version --- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index bbdc986ef7a26..f4cf338ffb5d4 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -56,7 +56,7 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 9; +const METADATA_VERSION: u8 = 10; /// Metadata header which includes `METADATA_VERSION`. /// From 27b866d59a3e5ccbaf9723a37d353db6d2079f16 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 1 Apr 2025 13:22:45 +0800 Subject: [PATCH 234/333] Add ui test ui/traits/object/suggestion-trait-object-issue-139174.rs Signed-off-by: xizheyin --- .../suggestion-trait-object-issue-139174.rs | 24 ++++++++ ...uggestion-trait-object-issue-139174.stderr | 55 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/ui/traits/object/suggestion-trait-object-issue-139174.rs create mode 100644 tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs new file mode 100644 index 0000000000000..f8fa410b7d495 --- /dev/null +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs @@ -0,0 +1,24 @@ +//@compile-flags: --edition 2021 + +fn f<'a>(x: Box Option>) -> usize { + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] + 0 +} + +fn create_adder<'a>(x: i32) -> usize + 'a { + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] + move |y| x + y +} + +struct Struct<'a>{ + x: usize + 'a, + //~^ ERROR expected trait, found builtin type `usize` + //~| ERROR expected a type, found a trait [E0782] +} + + +fn main() { + +} diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr new file mode 100644 index 0000000000000..ddee0d5586b07 --- /dev/null +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr @@ -0,0 +1,55 @@ +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:3:36 + | +LL | fn f<'a>(x: Box Option>) -> usize { + | ^^^^^ not a trait + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 + | +LL | fn create_adder<'a>(x: i32) -> usize + 'a { + | ^^^^^ not a trait + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 + | +LL | x: usize + 'a, + | ^^^^^ not a trait + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:3:36 + | +LL | fn f<'a>(x: Box Option>) -> usize { + | ^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | fn f<'a>(x: Box Option>) -> usize { + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 + | +LL | fn create_adder<'a>(x: i32) -> usize + 'a { + | ^^^^^^^^^^ + | +help: `usize + 'a` is dyn-incompatible, use `impl usize + 'a` to return an opaque type, as long as you return a single underlying type + | +LL | fn create_adder<'a>(x: i32) -> impl usize + 'a { + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 + | +LL | x: usize + 'a, + | ^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | x: dyn usize + 'a, + | +++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0782. +For more information about an error, try `rustc --explain E0404`. From 12604fa071b01f7342520224507e43e432294c2c Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 1 Apr 2025 14:19:40 +0800 Subject: [PATCH 235/333] Skip suggest impl or dyn when poly trait is not a real trait Signed-off-by: xizheyin --- .../src/hir_ty_lowering/lint.rs | 1 + .../suggestion-trait-object-issue-139174.stderr | 15 --------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 5588631228441..8e62dce21913b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -86,6 +86,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "expected a type, found a trait" ); if self_ty.span.can_be_used_for_suggestions() + && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(self_ty, &mut diag) && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag) { diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr index ddee0d5586b07..0d1ce85fc2888 100644 --- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr @@ -21,33 +21,18 @@ error[E0782]: expected a type, found a trait | LL | fn f<'a>(x: Box Option>) -> usize { | ^^^^^^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | fn f<'a>(x: Box Option>) -> usize { - | +++ error[E0782]: expected a type, found a trait --> $DIR/suggestion-trait-object-issue-139174.rs:9:32 | LL | fn create_adder<'a>(x: i32) -> usize + 'a { | ^^^^^^^^^^ - | -help: `usize + 'a` is dyn-incompatible, use `impl usize + 'a` to return an opaque type, as long as you return a single underlying type - | -LL | fn create_adder<'a>(x: i32) -> impl usize + 'a { - | ++++ error[E0782]: expected a type, found a trait --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 | LL | x: usize + 'a, | ^^^^^^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | x: dyn usize + 'a, - | +++ error: aborting due to 6 previous errors From f0efb9748ea02b7e6f15bef45881403ddcfba125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 1 Apr 2025 08:59:04 +0200 Subject: [PATCH 236/333] Support metadata version 10 in proc-macro-srv --- .../rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs index 4e28aaced9b0a..7668f419040cf 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib/version.rs @@ -110,7 +110,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result { )); } let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]); - // Last supported version is: + // Last breaking version change is: // https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318 let (mut metadata_portion, bytes_before_version) = match version { 8 => { @@ -118,7 +118,7 @@ pub fn read_version(obj: &object::File<'_>) -> io::Result { let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize; (&dot_rustc[12..data_len + 12], 13) } - 9 => { + 9 | 10 => { let len_bytes = &dot_rustc[8..16]; let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize; (&dot_rustc[16..data_len + 12], 17) From f153685fd0478fbbc346cfeb49f57965a9bc43d1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:36:26 +0100 Subject: [PATCH 237/333] Improve docs of ValTreeKind --- compiler/rustc_middle/src/ty/consts/valtree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 72263d8458085..2f21d19e03c70 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -33,7 +33,7 @@ pub enum ValTreeKind<'tcx> { /// The fields of any kind of aggregate. Structs, tuples and arrays are represented by /// listing their fields' values in order. /// - /// Enums are represented by storing their discriminant as a field, followed by all + /// Enums are represented by storing their variant index as a u32 field, followed by all /// the fields of the variant. /// /// ZST types are represented as an empty slice. From a7b687c26ef55bfc3481761fef6e46154e5f95ea Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 11:48:06 +0000 Subject: [PATCH 238/333] Decouple trait impls of different traits wrt incremental --- compiler/rustc_hir_analysis/src/coherence/mod.rs | 5 ++++- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 ++ compiler/rustc_middle/src/query/mod.rs | 5 +++++ src/tools/clippy/clippy_lints/src/derive.rs | 6 ++---- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 15e0a72fdcbd5..16bac4304910c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) { } fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> { + let impls = tcx.local_trait_impls(def_id); // If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything // anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge. - let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) }; + if impls.is_empty() { + return Ok(()); + } // Trigger building the specialization graph for the trait. This will detect and report any // overlap errors. let mut res = tcx.ensure_ok().specialization_graph_of(def_id); diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 52f155a16b868..80370910032dc 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -368,7 +368,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] { - self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) + self.local_trait_impls(trait_did) } /// Gets the attributes on the crate. This is preferable to diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 347bc5ea31289..cae9b2fb5448c 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) { } }; providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; + providers.local_trait_impls = + |tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]); providers.expn_that_defined = |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()); providers.in_scope_traits_map = |tcx, id| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d7ed703f4ae30..4b3236e4b8412 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1502,6 +1502,11 @@ rustc_queries! { desc { "finding local trait impls" } } + /// Return all `impl` blocks of the given trait in the current crate. + query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { + desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } + } + /// Given a trait `trait_id`, return all known `impl` blocks. query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { arena_cache diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 2ae35b4005579..fae01026487a0 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -324,11 +324,9 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h // there's a Copy impl for any instance of the adt. if !is_copy(cx, ty) { if ty_subs.non_erasable_generics().next().is_some() { - let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).is_some_and(|impls| { - impls.iter().any(|&id| { - matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) + let has_copy_impl = cx.tcx.local_trait_impls(copy_id).iter().any(|&id| { + matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()) - }) }); if !has_copy_impl { return; From aec77398378cc7af99043c3d1dd2394eb3d33c43 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:03:48 +0000 Subject: [PATCH 239/333] Remove an unnecessary dtor computation and use the cached query result instead --- compiler/rustc_mir_transform/src/check_const_item_mutation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index ceea72c6755a0..76d1e671c5d8a 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -53,7 +53,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> { // // #[const_mutation_allowed] // pub const LOG: Log = Log { msg: "" }; - match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) { + match self.tcx.adt_destructor(def_id) { Some(_) => None, None => Some(def_id), } From c0fe46d6b72c96bda16bf62e7476e6d85ba68afe Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:08:00 +0000 Subject: [PATCH 240/333] Make missing optimized MIR error more informative --- compiler/rustc_monomorphize/messages.ftl | 2 +- compiler/rustc_monomorphize/src/collector.rs | 1 + compiler/rustc_monomorphize/src/errors.rs | 1 + tests/ui/rmeta/no_optitimized_mir.rs | 2 +- tests/ui/rmeta/no_optitimized_mir.stderr | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index aae2d79c16109..6b6653e7de021 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -48,7 +48,7 @@ monomorphize_large_assignments = .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` monomorphize_no_optimized_mir = - missing optimized MIR for an item in the crate `{$crate_name}` + missing optimized MIR for `{$instance}` in the crate `{$crate_name}` .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?) monomorphize_recursion_limit = diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2a1b20ba48b87..6e676ac6b8d53 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> tcx.dcx().emit_fatal(NoOptimizedMir { span: tcx.def_span(def_id), crate_name: tcx.crate_name(def_id.krate), + instance: instance.to_string(), }); } diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index dffa372279f9f..adfe096f0cdcb 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir { #[note] pub span: Span, pub crate_name: Symbol, + pub instance: String, } #[derive(LintDiagnostic)] diff --git a/tests/ui/rmeta/no_optitimized_mir.rs b/tests/ui/rmeta/no_optitimized_mir.rs index 708cdfc803fa7..c8ed00b039b23 100644 --- a/tests/ui/rmeta/no_optitimized_mir.rs +++ b/tests/ui/rmeta/no_optitimized_mir.rs @@ -10,4 +10,4 @@ fn main() { rmeta_meta::missing_optimized_mir(); } -//~? ERROR missing optimized MIR for an item in the crate `rmeta_meta` +//~? ERROR missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta` diff --git a/tests/ui/rmeta/no_optitimized_mir.stderr b/tests/ui/rmeta/no_optitimized_mir.stderr index 92f22d7800050..254f100aa7b5e 100644 --- a/tests/ui/rmeta/no_optitimized_mir.stderr +++ b/tests/ui/rmeta/no_optitimized_mir.stderr @@ -1,4 +1,4 @@ -error: missing optimized MIR for an item in the crate `rmeta_meta` +error: missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta` | note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled with `--emit=metadata`?) --> $DIR/auxiliary/rmeta-meta.rs:10:1 From 23f1fb58f201cce980128a0dae491c4e5393629a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:08:00 +0000 Subject: [PATCH 241/333] Store adt_destructor in metadata --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 5 +---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/ty/parameterized.rs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 776b081a4630f..5c425e7a41853 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -330,10 +330,7 @@ provide! { tcx, def_id, other, cdata, visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } - adt_destructor => { - let _ = cdata; - tcx.calculate_dtor(def_id, |_,_| Ok(())) - } + adt_destructor => { table } adt_async_destructor => { let _ = cdata; tcx.calculate_async_dtor(def_id, |_,_| Ok(())) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ab3d432bdf81..a9beab1a70a3e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1633,6 +1633,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.fn_sig[variant.def_id] <- fn_sig); } } + + if let Some(destructor) = tcx.adt_destructor(local_def_id) { + record!(self.tables.adt_destructor[def_id] <- destructor); + } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index dc453b1e747ca..fb5fcff8d33d3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -446,6 +446,7 @@ define_tables! { fn_arg_names: Table>>, coroutine_kind: Table, coroutine_for_closure: Table, + adt_destructor: Table>, coroutine_by_move_body_def_id: Table, eval_static_initializer: Table>>, trait_def: Table>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 19e2b57456327..d6f181669563b 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! { ty::AssocItemContainer, ty::Asyncness, ty::DeducedParamAttrs, + ty::Destructor, ty::Generics, ty::ImplPolarity, ty::ImplTraitInTraitData, From 2b1c416da724a45f5a9c8e501c27a87ca4b536cc Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:46:04 +0000 Subject: [PATCH 242/333] Store adt_async_destructor in metadata --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 5 +---- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 ++++ compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/ty/parameterized.rs | 1 + 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 5c425e7a41853..3dc82ce9d183d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -331,10 +331,7 @@ provide! { tcx, def_id, other, cdata, visibility => { cdata.get_visibility(def_id.index) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { table } - adt_async_destructor => { - let _ = cdata; - tcx.calculate_async_dtor(def_id, |_,_| Ok(())) - } + adt_async_destructor => { table } associated_item_def_ids => { tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a9beab1a70a3e..b6f799e7ff799 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1637,6 +1637,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Some(destructor) = tcx.adt_destructor(local_def_id) { record!(self.tables.adt_destructor[def_id] <- destructor); } + + if let Some(destructor) = tcx.adt_async_destructor(local_def_id) { + record!(self.tables.adt_async_destructor[def_id] <- destructor); + } } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index fb5fcff8d33d3..8fef3ef235552 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -447,6 +447,7 @@ define_tables! { coroutine_kind: Table, coroutine_for_closure: Table, adt_destructor: Table>, + adt_async_destructor: Table>, coroutine_by_move_body_def_id: Table, eval_static_initializer: Table>>, trait_def: Table>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index d6f181669563b..61b35b33a096c 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -65,6 +65,7 @@ trivially_parameterized_over_tcx! { crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, + ty::AsyncDestructor, ty::AssocItemContainer, ty::Asyncness, ty::DeducedParamAttrs, From 51184c70c897619f6a2883538f8a85292306a0c8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 27 Mar 2025 12:48:54 +0000 Subject: [PATCH 243/333] Ensure `calculcate_dtor` is only ever called on local types --- compiler/rustc_hir_analysis/src/check/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/util.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d8ae421452759..ee1e78a79cd4d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) + tcx.calculate_dtor(def_id, always_applicable::check_drop_impl) } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl) + tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl) } /// Given a `DefId` for an opaque type in return position, find its parent item's return diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c0d4130336e52..61d8b5ce52ed8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -389,7 +389,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Calculate the destructor of a given type. pub fn calculate_dtor( self, - adt_did: DefId, + adt_did: LocalDefId, validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let drop_trait = self.lang_items().drop_trait()?; @@ -426,7 +426,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Calculate the async destructor of a given type. pub fn calculate_async_dtor( self, - adt_did: DefId, + adt_did: LocalDefId, validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let async_drop_trait = self.lang_items().async_drop_trait()?; From 2dc650b97b240c0bd279704b01916970c2031c4b Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 28 Mar 2025 18:12:29 +0530 Subject: [PATCH 244/333] replace commit placeholder in vendor status with actual commit --- src/bootstrap/bootstrap.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 68400ba0ea029..140f601253c31 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1162,6 +1162,30 @@ def build_triple(self): config = self.get_toml("build") return config or default_build_triple(self.verbose) + def is_git_repository(self, repo_path): + return os.path.isdir(os.path.join(repo_path, ".git")) + + def get_latest_commit(self): + repo_path = self.rust_root + author_email = self.stage0_data.get("git_merge_commit_email") + if not self.is_git_repository(repo_path): + return "" + cmd = [ + "git", + "-C", + repo_path, + "rev-list", + "--author", + author_email, + "-n1", + "HEAD", + ] + try: + commit = subprocess.check_output(cmd, universal_newlines=True).strip() + return commit or "" + except subprocess.CalledProcessError: + return "" + def check_vendored_status(self): """Check that vendoring is configured properly""" # keep this consistent with the equivalent check in bootstrap: @@ -1174,7 +1198,8 @@ def check_vendored_status(self): eprint(" use vendored sources by default.") cargo_dir = os.path.join(self.rust_root, ".cargo") - url = "https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz" + commit = self.get_latest_commit() + url = f"https://ci-artifacts.rust-lang.org/rustc-builds/{commit}/rustc-nightly-src.tar.xz" if self.use_vendored_sources: vendor_dir = os.path.join(self.rust_root, "vendor") if not os.path.exists(vendor_dir): From 624eb8550b8411a8b8773acf3fce0082f9554a7b Mon Sep 17 00:00:00 2001 From: highcloudwind Date: Tue, 1 Apr 2025 21:05:34 +0800 Subject: [PATCH 245/333] chore: remove redundant backtick Signed-off-by: highcloudwind --- src/etc/test-float-parse/src/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs index 1ee57723e6a62..73473eef0bfdb 100644 --- a/src/etc/test-float-parse/src/ui.rs +++ b/src/etc/test-float-parse/src/ui.rs @@ -157,7 +157,7 @@ pub fn set_panic_hook(drop_bars: &[ProgressBar]) { })); } -/// Allow non-Debug items in a `derive(Debug)` struct`. +/// Allow non-Debug items in a `derive(Debug)` struct. #[derive(Clone)] struct NoDebug(T); From e638ba69f09d72b0f1e2f00b03ff530460d1bfe3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Apr 2025 15:11:10 +0200 Subject: [PATCH 246/333] interpret: add a version of run_for_validation for &self --- .../rustc_const_eval/src/interpret/memory.rs | 43 ++++++++++++++----- .../src/interpret/validity.rs | 2 +- src/tools/miri/src/concurrency/data_race.rs | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 8f286971e6389..d077900587e9c 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -8,8 +8,9 @@ use std::assert_matches::assert_matches; use std::borrow::{Borrow, Cow}; +use std::cell::Cell; use std::collections::VecDeque; -use std::{fmt, mem, ptr}; +use std::{fmt, ptr}; use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; @@ -131,7 +132,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> { /// This stores whether we are currently doing reads purely for the purpose of validation. /// Those reads do not trigger the machine's hooks for memory reads. /// Needless to say, this must only be set with great care! - validation_in_progress: bool, + validation_in_progress: Cell, } /// A reference to some allocation that was already bounds-checked for the given region @@ -158,7 +159,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> { alloc_map: M::MemoryMap::default(), extra_fn_ptr_map: FxIndexMap::default(), dead_alloc_map: FxIndexMap::default(), - validation_in_progress: false, + validation_in_progress: Cell::new(false), } } @@ -715,7 +716,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized // accesses. That means we cannot rely on the closure above or the `Some` branch below. We // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked. - if !self.memory.validation_in_progress { + if !self.memory.validation_in_progress.get() { if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) { M::before_alloc_read(self, alloc_id)?; } @@ -723,7 +724,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - if !self.memory.validation_in_progress { + if !self.memory.validation_in_progress.get() { M::before_memory_read( self.tcx, &self.machine, @@ -801,7 +802,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, Option>> { let tcx = self.tcx; - let validation_in_progress = self.memory.validation_in_progress; + let validation_in_progress = self.memory.validation_in_progress.get(); let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes let ptr_and_alloc = Self::check_and_deref_ptr( @@ -1087,23 +1088,43 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// We do this so Miri's allocation access tracking does not show the validation /// reads as spurious accesses. - pub fn run_for_validation(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + pub fn run_for_validation_mut(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. assert!( - mem::replace(&mut self.memory.validation_in_progress, true) == false, + self.memory.validation_in_progress.replace(true) == false, "`validation_in_progress` was already set" ); let res = f(self); assert!( - mem::replace(&mut self.memory.validation_in_progress, false) == true, + self.memory.validation_in_progress.replace(false) == true, + "`validation_in_progress` was unset by someone else" + ); + res + } + + /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be + /// suppressed. Needless to say, this must only be set with great care! Cannot be nested. + /// + /// We do this so Miri's allocation access tracking does not show the validation + /// reads as spurious accesses. + pub fn run_for_validation_ref(&self, f: impl FnOnce(&Self) -> R) -> R { + // This deliberately uses `==` on `bool` to follow the pattern + // `assert!(val.replace(new) == old)`. + assert!( + self.memory.validation_in_progress.replace(true) == false, + "`validation_in_progress` was already set" + ); + let res = f(self); + assert!( + self.memory.validation_in_progress.replace(false) == true, "`validation_in_progress` was unset by someone else" ); res } pub(super) fn validation_in_progress(&self) -> bool { - self.memory.validation_in_progress + self.memory.validation_in_progress.get() } } @@ -1375,7 +1396,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - assert!(!self.memory.validation_in_progress, "we can't be copying during validation"); + assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation"); // For the overlapping case, it is crucial that we trigger the read hook // before the write hook -- the aliasing model cares about the order. M::before_memory_read( diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index eb3f552cd2787..fb7ba6d7ef57e 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1322,7 +1322,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); // Run the visitor. - self.run_for_validation(|ecx| { + self.run_for_validation_mut(|ecx| { let reset_padding = reset_provenance_and_padding && { // Check if `val` is actually stored in memory. If not, padding is not even // represented and we need not reset it. diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index b1ca434361b4a..923031dbbd1eb 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -717,7 +717,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // The program didn't actually do a read, so suppress the memory access hooks. // This is also a very special exception where we just ignore an error -- if this read // was UB e.g. because the memory is uninitialized, we don't want to know! - let old_val = this.run_for_validation(|this| this.read_scalar(dest)).discard_err(); + let old_val = this.run_for_validation_mut(|this| this.read_scalar(dest)).discard_err(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; this.buffered_atomic_write(val, dest, atomic, old_val) From d2358f7f2e1ec1a058308fc3149ecd5e7d3d4a12 Mon Sep 17 00:00:00 2001 From: futreall <86553580+futreall@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:26:55 +0300 Subject: [PATCH 247/333] fix link in netbsd.md Update netbsd.md Update netbsd.md --- src/doc/rustc/src/platform-support/netbsd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index ef9337befa643..5c2ce0ee9005e 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -34,7 +34,7 @@ are built for NetBSD 8.x but also work on newer OS versions). ## Designated Developers - [@he32](https://github.com/he32), `he@NetBSD.org` -- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust +- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust185/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust - [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc. - [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself From 6c3be19f578f589431d0bcc8c0b71b204d2241c1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 1 Apr 2025 06:47:55 -0700 Subject: [PATCH 248/333] Update mdbook to 0.4.48 This brings in several updates. Two significant ones are to halve the search index size, and the other introduces major changes to footnote rendering. Changelog: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#mdbook-0448 --- src/doc/rustc/src/SUMMARY.md | 3 +-- src/tools/rustbook/Cargo.lock | 4 ++-- src/tools/rustbook/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d08e0bd1edf2a..e1ba27c07daef 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -102,7 +102,7 @@ - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md) - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - - [sparcv9-sun-solaris](platform-support/solaris.md) + - [solaris](platform-support/solaris.md) - [\*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) @@ -126,7 +126,6 @@ - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) - [x86_64-pc-cygwin](platform-support/x86_64-pc-cygwin.md) - - [x86_64-pc-solaris](platform-support/solaris.md) - [x86_64-unknown-linux-none.md](platform-support/x86_64-unknown-linux-none.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [xtensa-\*-none-elf](platform-support/xtensa.md) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index e54747c129a0c..a1ccaa4874903 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -880,9 +880,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.47" +version = "0.4.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84" +checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1" dependencies = [ "ammonia", "anyhow", diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 831233e3065d3..a0b220c3557d6 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] -version = "0.4.47" +version = "0.4.48" default-features = false features = ["search"] From 770fcbf8c13871620b689fcadec36f5936c5fe5a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:11:58 +0000 Subject: [PATCH 249/333] Move test-float-parse to the 2024 edition --- src/etc/test-float-parse/Cargo.toml | 2 +- .../src/{gen => gen_}/exhaustive.rs | 0 .../src/{gen => gen_}/exponents.rs | 0 .../src/{gen => gen_}/fuzz.rs | 0 .../src/{gen => gen_}/integers.rs | 0 .../src/{gen => gen_}/long_fractions.rs | 0 .../src/{gen => gen_}/many_digits.rs | 0 .../src/{gen => gen_}/sparse.rs | 0 .../src/{gen => gen_}/spot_checks.rs | 0 .../src/{gen => gen_}/subnorm.rs | 0 src/etc/test-float-parse/src/lib.rs | 38 +++++++++---------- 11 files changed, 20 insertions(+), 20 deletions(-) rename src/etc/test-float-parse/src/{gen => gen_}/exhaustive.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/exponents.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/fuzz.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/integers.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/long_fractions.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/many_digits.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/sparse.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/spot_checks.rs (100%) rename src/etc/test-float-parse/src/{gen => gen_}/subnorm.rs (100%) diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml index bacb9e09f3f6a..8a9c5322ef7bd 100644 --- a/src/etc/test-float-parse/Cargo.toml +++ b/src/etc/test-float-parse/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "test-float-parse" version = "0.1.0" -edition = "2021" +edition = "2024" publish = false [dependencies] diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen_/exhaustive.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/exhaustive.rs rename to src/etc/test-float-parse/src/gen_/exhaustive.rs diff --git a/src/etc/test-float-parse/src/gen/exponents.rs b/src/etc/test-float-parse/src/gen_/exponents.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/exponents.rs rename to src/etc/test-float-parse/src/gen_/exponents.rs diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen_/fuzz.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/fuzz.rs rename to src/etc/test-float-parse/src/gen_/fuzz.rs diff --git a/src/etc/test-float-parse/src/gen/integers.rs b/src/etc/test-float-parse/src/gen_/integers.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/integers.rs rename to src/etc/test-float-parse/src/gen_/integers.rs diff --git a/src/etc/test-float-parse/src/gen/long_fractions.rs b/src/etc/test-float-parse/src/gen_/long_fractions.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/long_fractions.rs rename to src/etc/test-float-parse/src/gen_/long_fractions.rs diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen_/many_digits.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/many_digits.rs rename to src/etc/test-float-parse/src/gen_/many_digits.rs diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen_/sparse.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/sparse.rs rename to src/etc/test-float-parse/src/gen_/sparse.rs diff --git a/src/etc/test-float-parse/src/gen/spot_checks.rs b/src/etc/test-float-parse/src/gen_/spot_checks.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/spot_checks.rs rename to src/etc/test-float-parse/src/gen_/spot_checks.rs diff --git a/src/etc/test-float-parse/src/gen/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs similarity index 100% rename from src/etc/test-float-parse/src/gen/subnorm.rs rename to src/etc/test-float-parse/src/gen_/subnorm.rs diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs index e2f84b085c6f5..3c3ef5802b6aa 100644 --- a/src/etc/test-float-parse/src/lib.rs +++ b/src/etc/test-float-parse/src/lib.rs @@ -17,7 +17,7 @@ use traits::{Float, Generator, Int}; use validate::CheckError; /// Test generators. -mod gen { +mod gen_ { pub mod exhaustive; pub mod exponents; pub mod fuzz; @@ -136,24 +136,24 @@ where { if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE { // Only run exhaustive tests if there is a chance of completion. - TestInfo::register::>(tests); + TestInfo::register::>(tests); } - gen::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); - - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); - TestInfo::register::(tests); - TestInfo::register::(tests); - TestInfo::register::>(tests); - TestInfo::register::>(tests); + gen_::fuzz::Fuzz::::set_iterations(cfg.fuzz_count); + + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); + TestInfo::register::(tests); + TestInfo::register::(tests); + TestInfo::register::>(tests); + TestInfo::register::>(tests); } /// Configuration for a single test. @@ -343,7 +343,7 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration { /// /// This calls the generator's iterator multiple times (in parallel) and validates each output. fn test_runner>(test: &TestInfo, cfg: &Config) { - let gen = G::new(); + let gen_ = G::new(); let executed = AtomicU64::new(0); let failures = AtomicU64::new(0); @@ -387,7 +387,7 @@ fn test_runner>(test: &TestInfo, cfg: &Config) { // Run the test iterations in parallel. Each thread gets a string buffer to write // its check values to. - let res = gen.par_bridge().try_for_each_init(String::new, check_one); + let res = gen_.par_bridge().try_for_each_init(String::new, check_one); let elapsed = started.elapsed(); let executed = executed.into_inner(); From f922e74f71371abe3eceda4a131c4d0137591548 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:12:07 +0000 Subject: [PATCH 250/333] Make coroutine_drop_cleanup 2024 edition compatible --- tests/mir-opt/coroutine_drop_cleanup.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs index 33fdd2dd0d9cb..4ae97273cd90a 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.rs +++ b/tests/mir-opt/coroutine_drop_cleanup.rs @@ -8,7 +8,7 @@ // EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir fn main() { - let gen = #[coroutine] + let gen_ = #[coroutine] || { let _s = String::new(); yield; From a2f29439bf0fbf9823cf99cee61254875379e2c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:12:30 +0000 Subject: [PATCH 251/333] Use the 2024 edition in ./x.py fmt --- src/bootstrap/src/core/build_steps/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 7aa5cb2b6e5e1..b1a97bde97b5b 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -31,7 +31,7 @@ fn rustfmt( // Avoid the submodule config paths from coming into play. We only allow a single global config // for the workspace for now. cmd.arg("--config-path").arg(src.canonicalize().unwrap()); - cmd.arg("--edition").arg("2021"); + cmd.arg("--edition").arg("2024"); cmd.arg("--unstable-features"); cmd.arg("--skip-children"); if check { From 242558058a0aa3d5b64d911f45a07f27930016e7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:13:53 +0000 Subject: [PATCH 252/333] Allow formatting example/gen_block_iterate.rs --- .../example/gen_block_iterate.rs | 16 ++++++++++++---- compiler/rustc_codegen_cranelift/rustfmt.toml | 4 ---- rustfmt.toml | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs index 25bfe542d228a..de9a3d550eccd 100644 --- a/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs +++ b/compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs @@ -6,16 +6,25 @@ #![feature(gen_blocks)] fn foo() -> impl Iterator { - gen { yield 42; for x in 3..6 { yield x } } + gen { + yield 42; + for x in 3..6 { + yield x + } + } } fn moved() -> impl Iterator { let mut x = "foo".to_string(); gen move { yield 42; - if x == "foo" { return } + if x == "foo" { + return; + } x.clear(); - for x in 3..6 { yield x } + for x in 3..6 { + yield x + } } } @@ -32,5 +41,4 @@ fn main() { let mut iter = moved(); assert_eq!(iter.next(), Some(42)); assert_eq!(iter.next(), None); - } diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml index f31fa9c76abc6..35c92663eb904 100644 --- a/compiler/rustc_codegen_cranelift/rustfmt.toml +++ b/compiler/rustc_codegen_cranelift/rustfmt.toml @@ -1,7 +1,3 @@ -ignore = [ - "example/gen_block_iterate.rs", # uses edition 2024 -] - # Matches rustfmt.toml of rustc style_edition = "2024" use_small_heuristics = "Max" diff --git a/rustfmt.toml b/rustfmt.toml index 8feeb60ca12c2..c884a33729c44 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -49,7 +49,6 @@ ignore = [ # These are ignored by a standard cargo fmt run. "compiler/rustc_codegen_cranelift/scripts", - "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024 "compiler/rustc_codegen_gcc/tests", # Code automatically generated and included. "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", From df18de57a540cc9ae2309fd53e49c9a627f7d849 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 30 Mar 2025 15:56:41 +0200 Subject: [PATCH 253/333] Add unstable `--print=crate-root-lint-levels` --- compiler/rustc_driver_impl/src/lib.rs | 28 +++++ compiler/rustc_session/src/config.rs | 3 + .../print-crate-root-lint-levels.md | 23 ++++ .../print-crate-root-lint-levels/lib.rs | 5 + .../print-crate-root-lint-levels/rmake.rs | 118 ++++++++++++++++++ tests/run-make/rustc-help/help-v.stdout | 2 +- tests/run-make/rustc-help/help.stdout | 2 +- .../print-without-arg.stderr | 2 +- tests/ui/invalid-compile-flags/print.stderr | 2 +- .../ui/print-request/print-lints-help.stderr | 2 +- tests/ui/print-request/stability.rs | 4 + 11 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md create mode 100644 tests/run-make/print-crate-root-lint-levels/lib.rs create mode 100644 tests/run-make/print-crate-root-lint-levels/rmake.rs diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 37755e7d61db1..f1dc4bb795e51 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -691,6 +691,34 @@ fn print_crate_info( }; println_info!("{}", passes::get_crate_name(sess, attrs)); } + CrateRootLintLevels => { + let Some(attrs) = attrs.as_ref() else { + // no crate attributes, print out an error and exit + return Compilation::Continue; + }; + let crate_name = passes::get_crate_name(sess, attrs); + let lint_store = crate::unerased_lint_store(sess); + let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs); + let features = rustc_expand::config::features(sess, attrs, crate_name); + let lint_levels = rustc_lint::LintLevelsBuilder::crate_root( + sess, + &features, + true, + lint_store, + ®istered_tools, + attrs, + ); + for lint in lint_store.get_lints() { + if let Some(feature_symbol) = lint.feature_gate + && !features.enabled(feature_symbol) + { + // lint is unstable and feature gate isn't active, don't print + continue; + } + let level = lint_levels.lint_level(lint).0; + println_info!("{}={}", lint.name_lower(), level.as_str()); + } + } Cfg => { let mut cfgs = sess .psess diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ed336cc559612..1b01efda2a9ea 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -50,6 +50,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[ ("check-cfg", PrintKind::CheckCfg), ("code-models", PrintKind::CodeModels), ("crate-name", PrintKind::CrateName), + ("crate-root-lint-levels", PrintKind::CrateRootLintLevels), ("deployment-target", PrintKind::DeploymentTarget), ("file-names", PrintKind::FileNames), ("host-tuple", PrintKind::HostTuple), @@ -881,6 +882,7 @@ pub enum PrintKind { CheckCfg, CodeModels, CrateName, + CrateRootLintLevels, DeploymentTarget, FileNames, HostTuple, @@ -2067,6 +2069,7 @@ fn check_print_request_stability( match print_kind { PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg + | PrintKind::CrateRootLintLevels | PrintKind::SupportedCrateTypes | PrintKind::TargetSpecJson if !unstable_opts.unstable_options => diff --git a/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md new file mode 100644 index 0000000000000..0bad8b8ab96bd --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/print-crate-root-lint-levels.md @@ -0,0 +1,23 @@ +# `print=crate-root-lint-levels` + +The tracking issue for this feature is: [#139180](https://github.com/rust-lang/rust/issues/139180). + +------------------------ + +This option of the `--print` flag print the list of lints with print out all the lints and their associated levels (`allow`, `warn`, `deny`, `forbid`) based on the regular Rust rules at crate root, that is *(roughly)*: + - command line args (`-W`, `-A`, `--force-warn`, `--cap-lints`, ...) + - crate root attributes (`#![allow]`, `#![warn]`, `#[expect]`, ...) + - *the special `warnings` lint group* + - the default lint level + +The output format is `LINT_NAME=LINT_LEVEL`, e.g.: +```text +unknown_lint=warn +arithmetic_overflow=deny +``` + +To be used like this: + +```bash +rustc --print=crate-root-lint-levels -Zunstable-options lib.rs +``` diff --git a/tests/run-make/print-crate-root-lint-levels/lib.rs b/tests/run-make/print-crate-root-lint-levels/lib.rs new file mode 100644 index 0000000000000..dc846f8fd9514 --- /dev/null +++ b/tests/run-make/print-crate-root-lint-levels/lib.rs @@ -0,0 +1,5 @@ +#![allow(unexpected_cfgs)] +#![expect(unused_mut)] + +#[deny(unknown_lints)] +mod my_mod {} diff --git a/tests/run-make/print-crate-root-lint-levels/rmake.rs b/tests/run-make/print-crate-root-lint-levels/rmake.rs new file mode 100644 index 0000000000000..e373c91102dfa --- /dev/null +++ b/tests/run-make/print-crate-root-lint-levels/rmake.rs @@ -0,0 +1,118 @@ +//! This checks the output of `--print=crate-root-lint-levels` + +extern crate run_make_support; + +use std::collections::HashSet; +use std::iter::FromIterator; + +use run_make_support::rustc; + +struct CrateRootLintLevels { + args: &'static [&'static str], + contains: Contains, +} + +struct Contains { + contains: &'static [&'static str], + doesnt_contain: &'static [&'static str], +} + +fn main() { + check(CrateRootLintLevels { + args: &[], + contains: Contains { + contains: &[ + "unexpected_cfgs=allow", + "unused_mut=expect", + "warnings=warn", + "stable_features=warn", + "unknown_lints=warn", + ], + doesnt_contain: &["unexpected_cfgs=warn", "unused_mut=warn"], + }, + }); + check(CrateRootLintLevels { + args: &["-Wunexpected_cfgs"], + contains: Contains { + contains: &["unexpected_cfgs=allow", "warnings=warn"], + doesnt_contain: &["unexpected_cfgs=warn"], + }, + }); + check(CrateRootLintLevels { + args: &["-Dwarnings"], + contains: Contains { + contains: &[ + "unexpected_cfgs=allow", + "warnings=deny", + "stable_features=deny", + "unknown_lints=deny", + ], + doesnt_contain: &["warnings=warn"], + }, + }); + check(CrateRootLintLevels { + args: &["-Dstable_features"], + contains: Contains { + contains: &["warnings=warn", "stable_features=deny", "unexpected_cfgs=allow"], + doesnt_contain: &["warnings=deny"], + }, + }); + check(CrateRootLintLevels { + args: &["-Dwarnings", "--force-warn=stable_features"], + contains: Contains { + contains: &["warnings=deny", "stable_features=force-warn", "unknown_lints=deny"], + doesnt_contain: &["warnings=warn"], + }, + }); + check(CrateRootLintLevels { + args: &["-Dwarnings", "--cap-lints=warn"], + contains: Contains { + contains: &[ + "unexpected_cfgs=allow", + "warnings=warn", + "stable_features=warn", + "unknown_lints=warn", + ], + doesnt_contain: &["warnings=deny"], + }, + }); +} + +#[track_caller] +fn check(CrateRootLintLevels { args, contains }: CrateRootLintLevels) { + let output = rustc() + .input("lib.rs") + .arg("-Zunstable-options") + .print("crate-root-lint-levels") + .args(args) + .run(); + + let stdout = output.stdout_utf8(); + + let mut found = HashSet::::new(); + + for l in stdout.lines() { + assert!(l == l.trim()); + if let Some((left, right)) = l.split_once('=') { + assert!(!left.contains("\"")); + assert!(!right.contains("\"")); + } else { + assert!(l.contains('=')); + } + assert!(found.insert(l.to_string()), "{}", &l); + } + + let Contains { contains, doesnt_contain } = contains; + + { + let should_found = HashSet::::from_iter(contains.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_found.difference(&found).collect(); + assert!(diff.is_empty(), "should found: {:?}, didn't found {:?}", &should_found, &diff); + } + { + let should_not_find = + HashSet::::from_iter(doesnt_contain.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_not_find.intersection(&found).collect(); + assert!(diff.is_empty(), "should not find {:?}, did found {:?}", &should_not_find, &diff); + } +} diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index 98e56735082d1..f19ca1e9f90ab 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -29,7 +29,7 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index 040555f1d04fe..f7d352966035b 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -29,7 +29,7 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr index aa8a2ae42db29..8abaee5056bab 100644 --- a/tests/ui/invalid-compile-flags/print-without-arg.stderr +++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr @@ -1,5 +1,5 @@ error: Argument to option 'print' missing Usage: - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] + --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] Compiler information to print on stdout diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr index f9cfb1616ce5a..e3374eb1e6e7e 100644 --- a/tests/ui/invalid-compile-flags/print.stderr +++ b/tests/ui/invalid-compile-flags/print.stderr @@ -1,5 +1,5 @@ error: unknown print request: `yyyy` | - = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/print-request/print-lints-help.stderr b/tests/ui/print-request/print-lints-help.stderr index 0530d11f2e802..bc48b2fa73cc7 100644 --- a/tests/ui/print-request/print-lints-help.stderr +++ b/tests/ui/print-request/print-lints-help.stderr @@ -1,6 +1,6 @@ error: unknown print request: `lints` | - = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` = help: use `-Whelp` to print a list of lints = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs index c3421224d7206..0ec0886e941e7 100644 --- a/tests/ui/print-request/stability.rs +++ b/tests/ui/print-request/stability.rs @@ -18,6 +18,10 @@ //@[all_target_specs_json] compile-flags: --print=all-target-specs-json //@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed +//@ revisions: crate_root_lint_levels +//@[crate_root_lint_levels] compile-flags: --print=crate-root-lint-levels +//@[crate_root_lint_levels] error-pattern: the `-Z unstable-options` flag must also be passed + //@ revisions: check_cfg //@[check_cfg] compile-flags: --print=check-cfg //@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed From 49ed25b5d2d5dc88f9fa3e268d9bd210acc875de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 21:31:17 +1000 Subject: [PATCH 254/333] Remove `NtExpr` and `NtLiteral`. Notes about tests: - tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are now duplicated due to repeated parsing. - tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto. - `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. - `tests/ui/attributes/nonterminal-expansion.rs`: a slight span degradation, somehow related to the recent massive attr parsing rewrite (#135726). I couldn't work out exactly what is going wrong, but I don't think it's worth holding things up for a single slightly suboptimal error message. --- compiler/rustc_ast/src/ast_traits.rs | 2 - compiler/rustc_ast/src/mut_visit.rs | 2 - compiler/rustc_ast/src/token.rs | 71 ++--- compiler/rustc_ast/src/tokenstream.rs | 1 - compiler/rustc_expand/src/mbe/transcribe.rs | 35 ++- compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 220 +++++++++----- compiler/rustc_parse/src/parser/item.rs | 53 +++- compiler/rustc_parse/src/parser/mod.rs | 32 +- .../rustc_parse/src/parser/nonterminal.rs | 16 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- tests/ui/attributes/nonterminal-expansion.rs | 4 +- .../attributes/nonterminal-expansion.stderr | 11 +- .../cfg-attr-syntax-validation.rs | 2 +- .../cfg-attr-syntax-validation.stderr | 2 +- tests/ui/macros/nonterminal-matching.rs | 4 +- tests/ui/macros/nonterminal-matching.stderr | 4 +- .../extern-abi-from-mac-literal-frag.rs | 4 + tests/ui/parser/float-field-interpolated.rs | 8 +- .../ui/parser/float-field-interpolated.stderr | 8 +- .../ui/parser/macro/trait-non-item-macros.rs | 2 +- .../parser/macro/trait-non-item-macros.stderr | 2 +- .../proc-macro/macro-rules-derive-cfg.stdout | 129 +++++---- .../rfc-2294-if-let-guard/feature-gate.rs | 2 + .../rfc-2294-if-let-guard/feature-gate.stderr | 26 +- .../disallowed-positions.feature.stderr | 264 +++++++++-------- .../disallowed-positions.no_feature.stderr | 274 ++++++++++-------- .../disallowed-positions.nothing.stderr | 196 ++++++------- .../disallowed-positions.rs | 4 + 30 files changed, 801 insertions(+), 585 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 849cc650e9d6a..c9e2e9911ef0a 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -209,13 +209,11 @@ impl HasTokens for Attribute { impl HasTokens for Nonterminal { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(), Nonterminal::NtBlock(block) => block.tokens(), } } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(), Nonterminal::NtBlock(block) => block.tokens_mut(), } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 30af6d910bfa2..f7d13acdfc402 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -899,8 +899,6 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { match nt { token::NtBlock(block) => vis.visit_block(block), - token::NtExpr(expr) => vis.visit_expr(expr), - token::NtLiteral(expr) => vis.visit_expr(expr), } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 6e6f0f1b2660e..2081777fff359 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -198,16 +198,17 @@ impl Lit { } } - /// Keep this in sync with `Token::can_begin_literal_maybe_minus` excluding unary negation. + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Parser::eat_token_lit` (excluding unary negation). pub fn from_token(token: &Token) -> Option { match token.uninterpolate().kind { Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), - Interpolated(ref nt) - if let NtExpr(expr) | NtLiteral(expr) = &**nt - && let ast::ExprKind::Lit(token_lit) = expr.kind => - { - Some(token_lit) + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal | MetaVarKind::Expr { .. }, + ))) => { + // Unreachable with the current test suite. + panic!("from_token metavar"); } _ => None, } @@ -590,6 +591,9 @@ impl Token { /// for which spans affect name resolution and edition checks. /// Note that keywords are also identifiers, so they should use this /// if they keep spans or perform edition checks. + // + // Note: `Parser::uninterpolated_token_span` may give better information + // than this method does. pub fn uninterpolated_span(&self) -> Span { match self.kind { NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, @@ -642,12 +646,7 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => - matches!(&**nt, - NtBlock(..) | - NtExpr(..) | - NtLiteral(..) - ), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | MetaVarKind::Expr { .. } | @@ -677,11 +676,6 @@ impl Token { Lt | // path (UFCS constant) Shl => true, // path (double UFCS) Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern - Interpolated(nt) => - matches!(&**nt, - | NtExpr(..) - | NtLiteral(..) - ), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Literal | @@ -724,7 +718,7 @@ impl Token { match self.kind { OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => matches!(&**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)), + Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, @@ -768,22 +762,12 @@ impl Token { /// /// In other words, would this token be a valid start of `parse_literal_maybe_minus`? /// - /// Keep this in sync with and `Lit::from_token`, excluding unary negation. + /// Keep this in sync with `Lit::from_token` and `Parser::eat_token_lit` + /// (excluding unary negation). pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | Minus => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - ast::ExprKind::Unary(ast::UnOp::Neg, e) => { - matches!(&e.kind, ast::ExprKind::Lit(_)) - } - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { @@ -798,14 +782,6 @@ impl Token { pub fn can_begin_string_literal(&self) -> bool { match self.uninterpolate().kind { Literal(..) => true, - Interpolated(ref nt) => match &**nt { - NtLiteral(_) => true, - NtExpr(e) => match &e.kind { - ast::ExprKind::Lit(_) => true, - _ => false, - }, - _ => false, - }, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal, @@ -869,12 +845,17 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? - pub fn is_whole_expr(&self) -> bool { + pub fn is_metavar_expr(&self) -> bool { #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind - && let NtExpr(_) | NtLiteral(_) | NtBlock(_) = &**nt + && let NtBlock(_) = &**nt { true + } else if matches!( + self.is_metavar_seq(), + Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path) + ) { + true } else { matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) } @@ -882,6 +863,7 @@ impl Token { /// Is the token an interpolated block (`$b:block`)? pub fn is_whole_block(&self) -> bool { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let Interpolated(nt) = &self.kind && let NtBlock(..) = &**nt { @@ -1100,8 +1082,6 @@ pub enum NtExprKind { /// For interpolation during macro expansion. pub enum Nonterminal { NtBlock(P), - NtExpr(P), - NtLiteral(P), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] @@ -1191,15 +1171,12 @@ impl Nonterminal { pub fn use_span(&self) -> Span { match self { NtBlock(block) => block.span, - NtExpr(expr) | NtLiteral(expr) => expr.span, } } pub fn descr(&self) -> &'static str { match self { NtBlock(..) => "block", - NtExpr(..) => "expression", - NtLiteral(..) => "literal", } } } @@ -1218,8 +1195,6 @@ impl fmt::Debug for Nonterminal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { NtBlock(..) => f.pad("NtBlock(..)"), - NtExpr(..) => f.pad("NtExpr(..)"), - NtLiteral(..) => f.pad("NtLiteral(..)"), } } } @@ -1242,7 +1217,7 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Lit, 12); static_assert_size!(LitKind, 2); - static_assert_size!(Nonterminal, 16); + static_assert_size!(Nonterminal, 8); static_assert_size!(Token, 24); static_assert_size!(TokenKind, 16); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index bdd244be6d1cc..161f8e67551fa 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -462,7 +462,6 @@ impl TokenStream { pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { match nt { Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr), } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index cffa4af6ac3d0..6e47ed6eb67c1 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -3,11 +3,10 @@ use std::sync::Arc; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Nonterminal, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; -use rustc_ast::{ExprKind, StmtKind, TyKind}; +use rustc_ast::{ExprKind, StmtKind, TyKind, UnOp}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize}; use rustc_parse::lexer::nfc_normalize; @@ -340,6 +339,30 @@ pub(super) fn transcribe<'a>( MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat), ), + MatchedSingle(ParseNtResult::Expr(expr, kind)) => { + let (can_begin_literal_maybe_minus, can_begin_string_literal) = + match &expr.kind { + ExprKind::Lit(_) => (true, true), + ExprKind::Unary(UnOp::Neg, e) + if matches!(&e.kind, ExprKind::Lit(_)) => + { + (true, false) + } + _ => (false, false), + }; + mk_delimited( + expr.span, + MetaVarKind::Expr { + kind: *kind, + can_begin_literal_maybe_minus, + can_begin_string_literal, + }, + TokenStream::from_ast(expr), + ) + } + MatchedSingle(ParseNtResult::Literal(lit)) => { + mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit)) + } MatchedSingle(ParseNtResult::Ty(ty)) => { let is_path = matches!(&ty.kind, TyKind::Path(None, _path)); mk_delimited( @@ -869,10 +892,8 @@ fn extract_symbol_from_pnr<'a>( }, _, )) => Ok(*symbol), - ParseNtResult::Nt(nt) - if let Nonterminal::NtLiteral(expr) = &**nt - && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = - &expr.kind => + ParseNtResult::Literal(expr) + if let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => { Ok(*symbol) } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 24679692a0b0b..93fa89b68b97a 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -858,7 +858,7 @@ parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surro parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items -parse_unexpected_token_after_dot = unexpected token: `{$actual}` +parse_unexpected_token_after_dot = unexpected token: {$actual} parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label .suggestion_remove_label = consider removing the label diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 55cb76878238e..dfdef018bc374 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1696,10 +1696,10 @@ pub(crate) struct SelfArgumentPointer { #[derive(Diagnostic)] #[diag(parse_unexpected_token_after_dot)] -pub(crate) struct UnexpectedTokenAfterDot<'a> { +pub(crate) struct UnexpectedTokenAfterDot { #[primary_span] pub span: Span, - pub actual: Cow<'a, str>, + pub actual: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 00e75cc2c2fc1..424fee968e1d1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,10 +4,10 @@ use core::mem; use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; -use ast::token::{IdentIsRaw, MetaVarKind}; +use ast::token::IdentIsRaw; use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::case::Case; use rustc_ast::util::classify; @@ -19,7 +19,6 @@ use rustc_ast::{ MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind, }; -use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_lexer::unescape::unescape_char; @@ -605,7 +604,7 @@ impl<'a> Parser<'a> { // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), token::Literal(..) | token::Pound => true, - _ => t.is_whole_expr(), + _ => t.is_metavar_expr(), }; self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr) } @@ -641,6 +640,13 @@ impl<'a> Parser<'a> { TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { self.prev_token.span } + TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + // `expr.span` is the interpolated span, because invisible open + // and close delims both get marked with the same span, one + // that covers the entire thing between them. (See + // `rustc_expand::mbe::transcribe::transcribe`.) + self.prev_token.span + } _ => expr.span, } } @@ -979,12 +985,30 @@ impl<'a> Parser<'a> { } fn error_unexpected_after_dot(&self) { - let actual = pprust::token_to_string(&self.token); + let actual = super::token_descr(&self.token); let span = self.token.span; let sm = self.psess.source_map(); let (span, actual) = match (&self.token.kind, self.subparser_name) { - (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => { - (span.shrink_to_hi(), actual.into()) + (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => { + (span.shrink_to_hi(), format!("`{}`", snippet)) + } + (token::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))), _) => { + // No need to report an error. This case will only occur when parsing a pasted + // metavariable, and we should have emitted an error when parsing the macro call in + // the first place. E.g. in this code: + // ``` + // macro_rules! m { ($e:expr) => { $e }; } + // + // fn main() { + // let f = 1; + // m!(f.); + // } + // ``` + // we'll get an error "unexpected token: `)` when parsing the `m!(f.)`, so we don't + // want to issue a second error when parsing the expansion `«f.»` (where `«`/`»` + // represent the invisible delimiters). + self.dcx().span_delayed_bug(span, "bad dot expr in metavariable"); + return; } _ => (span, actual), }; @@ -1364,17 +1388,31 @@ impl<'a> Parser<'a> { let span = self.token.span; if let token::Interpolated(nt) = &self.token.kind { match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } token::NtBlock(block) => { let block = block.clone(); self.bump(); return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); } }; + } else if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + let expr = this.parse_expr(); + // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly + // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line + // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in + // `compiler/rustc_index/src/bit_set/tests.rs`. + if this.token.kind == token::Comma { + this.bump(); + } + expr + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) }) { @@ -2062,87 +2100,107 @@ impl<'a> Parser<'a> { .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char)) } - fn recover_after_dot(&mut self) -> Option { - let mut recovered = None; + fn recover_after_dot(&mut self) { if self.token == token::Dot { // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where // dot would follow an optional literal, so we do this unconditionally. - recovered = self.look_ahead(1, |next_token| { + let recovered = self.look_ahead(1, |next_token| { + // If it's an integer that looks like a float, then recover as such. + // + // We will never encounter the exponent part of a floating + // point literal here, since there's no use of the exponent + // syntax that also constitutes a valid integer, so we need + // not check for that. if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = next_token.kind + && suffix.is_none_or(|s| s == sym::f32 || s == sym::f64) + && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') + && self.token.span.hi() == next_token.span.lo() { - // If this integer looks like a float, then recover as such. - // - // We will never encounter the exponent part of a floating - // point literal here, since there's no use of the exponent - // syntax that also constitutes a valid integer, so we need - // not check for that. - if suffix.is_none_or(|s| s == sym::f32 || s == sym::f64) - && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') - && self.token.span.hi() == next_token.span.lo() - { - let s = String::from("0.") + symbol.as_str(); - let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); - return Some(Token::new(kind, self.token.span.to(next_token.span))); - } + let s = String::from("0.") + symbol.as_str(); + let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); + Some(Token::new(kind, self.token.span.to(next_token.span))) + } else { + None } - None }); - if let Some(token) = &recovered { - self.bump(); + if let Some(recovered) = recovered { self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart { - span: token.span, - suggestion: token.span.shrink_to_lo(), + span: recovered.span, + suggestion: recovered.span.shrink_to_lo(), }); + self.bump(); + self.token = recovered; } } + } - recovered + /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and + /// `Lit::from_token` (excluding unary negation). + fn eat_token_lit(&mut self) -> Option { + match self.token.uninterpolate().kind { + token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => { + self.bump(); + Some(token::Lit::new(token::Bool, name, None)) + } + token::Literal(token_lit) => { + self.bump(); + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Literal, + ))) => { + let lit = self + .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + .expect("metavar seq literal"); + let ast::ExprKind::Lit(token_lit) = lit.kind else { + panic!("didn't reparse a literal"); + }; + Some(token_lit) + } + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. }, + ))) => { + let expr = self + .eat_metavar_seq(mv_kind, |this| this.parse_expr()) + .expect("metavar seq expr"); + let ast::ExprKind::Lit(token_lit) = expr.kind else { + panic!("didn't reparse an expr"); + }; + Some(token_lit) + } + _ => None, + } } /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - let span = token.span; - - token::Lit::from_token(token).map(|token_lit| { - self.bump(); - (token_lit, span) - }) + fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> { + self.recover_after_dot(); + let span = self.token.span; + self.eat_token_lit().map(|token_lit| (token_lit, span)) } /// Matches `lit = true | false | token_lit`. /// Returns `None` if the next token is not a literal. - pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option { - let recovered = self.recover_after_dot(); - let token = recovered.as_ref().unwrap_or(&self.token); - match token::Lit::from_token(token) { - Some(lit) => { - match MetaItemLit::from_token_lit(lit, token.span) { - Ok(lit) => { - self.bump(); - Some(lit) - } - Err(err) => { - let span = token.uninterpolated_span(); - self.bump(); - let guar = report_lit_error(self.psess, err, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix); - Some( - MetaItemLit::from_token_lit(lit, span) - .unwrap_or_else(|_| unreachable!()), - ) - } + fn parse_opt_meta_item_lit(&mut self) -> Option { + self.recover_after_dot(); + let span = self.token.span; + let uninterpolated_span = self.uninterpolated_token_span(); + self.eat_token_lit().map(|token_lit| { + match MetaItemLit::from_token_lit(token_lit, span) { + Ok(lit) => lit, + Err(err) => { + let guar = report_lit_error(&self.psess, err, token_lit, uninterpolated_span); + // Pack possible quotes and prefixes from the original literal into + // the error literal's symbol so they can be pretty-printed faithfully. + let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None); + let symbol = Symbol::intern(&suffixless_lit.to_string()); + let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix); + MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap() } } - None => None, - } + }) } pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) { @@ -2166,9 +2224,10 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - if let token::Interpolated(nt) = &self.token.kind { - match &**nt { - // FIXME(nnethercote) The `NtExpr` case should only match if + if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + // FIXME(nnethercote) The `expr` case should only match if // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing // an `UnOp::Neg` and an `ExprKind::Lit`, like how // `can_begin_literal_maybe_minus` works. But this method has @@ -2178,13 +2237,14 @@ impl<'a> Parser<'a> { // `ExprKind::Path` must be accepted when parsing range // patterns. That requires some care. So for now, we continue // being less strict here than we should be. - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - self.bump(); - return Ok(e); - } - _ => {} - }; + this.parse_expr() + }, + ) { + return Ok(expr); + } else if let Some(lit) = + self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) + { + return Ok(lit); } let lo = self.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e93fb2473fbfb..20833a0f70f2d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1290,12 +1290,24 @@ impl<'a> Parser<'a> { } fn is_unsafe_foreign_mod(&self) -> bool { - self.token.is_keyword(kw::Unsafe) - && self.is_keyword_ahead(1, &[kw::Extern]) - && self.look_ahead( - 2 + self.look_ahead(2, |t| t.can_begin_string_literal() as usize), - |t| *t == token::OpenDelim(Delimiter::Brace), - ) + // Look for `unsafe`. + if !self.token.is_keyword(kw::Unsafe) { + return false; + } + // Look for `extern`. + if !self.is_keyword_ahead(1, &[kw::Extern]) { + return false; + } + + // Look for the optional ABI string literal. + let n = if self.look_ahead(2, |t| t.can_begin_string_literal()) { 3 } else { 2 }; + + // Look for the `{`. Use `tree_look_ahead` because the ABI (if present) + // might be a metavariable i.e. an invisible-delimited sequence, and + // `tree_look_ahead` will consider that a single element when looking + // ahead. + self.tree_look_ahead(n, |t| matches!(t, TokenTree::Delimited(_, _, Delimiter::Brace, _))) + == Some(true) } fn is_static_global(&mut self) -> bool { @@ -2604,13 +2616,36 @@ impl<'a> Parser<'a> { }) // `extern ABI fn` || self.check_keyword_case(exp!(Extern), case) + // Use `tree_look_ahead` because `ABI` might be a metavariable, + // i.e. an invisible-delimited sequence, and `tree_look_ahead` + // will consider that a single element when looking ahead. && self.look_ahead(1, |t| t.can_begin_string_literal()) - && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || + && (self.tree_look_ahead(2, |tt| { + match tt { + TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case), + TokenTree::Delimited(..) => false, + } + }) == Some(true) || // This branch is only for better diagnostics; `pub`, `unsafe`, etc. are not // allowed here. (self.may_recover() - && self.look_ahead(2, |t| ALL_QUALS.iter().any(|exp| t.is_keyword(exp.kw))) - && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)))) + && self.tree_look_ahead(2, |tt| { + match tt { + TokenTree::Token(t, _) => + ALL_QUALS.iter().any(|exp| { + t.is_keyword(exp.kw) + }), + TokenTree::Delimited(..) => false, + } + }) == Some(true) + && self.tree_look_ahead(3, |tt| { + match tt { + TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case), + TokenTree::Delimited(..) => false, + } + }) == Some(true) + ) + ) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index d865fd427641d..a08fbde52a7ce 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -24,8 +24,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token, - TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind, + Token, TokenKind, }; use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree}; use rustc_ast::util::case::Case; @@ -101,6 +101,7 @@ pub enum ForceCollect { #[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { + #[allow(irrefutable_let_patterns)] // FIXME: temporary if let token::Interpolated(nt) = &$p.token.kind && let token::$constructor(x) = &**nt { @@ -299,6 +300,10 @@ impl TokenTreeCursor { self.stream.get(self.index) } + fn look_ahead(&self, n: usize) -> Option<&TokenTree> { + self.stream.get(self.index + n) + } + #[inline] fn bump(&mut self) { self.index += 1; @@ -1290,6 +1295,17 @@ impl<'a> Parser<'a> { looker(&token) } + /// Like `lookahead`, but skips over token trees rather than tokens. Useful + /// when looking past possible metavariable pasting sites. + pub fn tree_look_ahead( + &self, + dist: usize, + looker: impl FnOnce(&TokenTree) -> R, + ) -> Option { + assert_ne!(dist, 0); + self.token_cursor.curr.look_ahead(dist - 1).map(looker) + } + /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) @@ -1706,6 +1722,16 @@ impl<'a> Parser<'a> { pub fn approx_token_stream_pos(&self) -> u32 { self.num_bump_calls } + + pub fn uninterpolated_token_span(&self) -> Span { + match &self.token.kind { + token::Interpolated(nt) => nt.use_span(), + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { + self.look_ahead(1, |t| t.span) + } + _ => self.token.span, + } + } } pub(crate) fn make_unclosed_delims_error( @@ -1758,6 +1784,8 @@ pub enum ParseNtResult { Item(P), Stmt(P), Pat(P, NtPatKind), + Expr(P, NtExprKind), + Literal(P), Ty(P), Meta(P), Path(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 1123755ce0037..b4e540d670d16 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -48,10 +48,6 @@ impl<'a> Parser<'a> { /// Old variant of `may_be_ident`. Being phased out. fn nt_may_be_ident(nt: &Nonterminal) -> bool { match nt { - NtExpr(_) - | NtLiteral(_) // `true`, `false` - => true, - NtBlock(_) => false, } } @@ -95,7 +91,7 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, token::Interpolated(nt) => match &**nt { - NtBlock(_) | NtExpr(_) | NtLiteral(_) => true, + NtBlock(_) => true, }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block @@ -179,10 +175,14 @@ impl<'a> Parser<'a> { pat_kind, )); } - NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr(expr_kind) => { + return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)); + } NonterminalKind::Literal => { - // The `:literal` matcher does not support attributes - NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) + // The `:literal` matcher does not support attributes. + return Ok(ParseNtResult::Literal( + self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, + )); } NonterminalKind::Ty => { return Ok(ParseNtResult::Ty( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 174cc929fa70d..9612f71b2af93 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1252,7 +1252,7 @@ impl<'a> Parser<'a> { || *t == token::Dot // e.g. `.5` for recovery; || matches!(t.kind, token::Literal(..) | token::Minus) || t.is_bool_lit() - || t.is_whole_expr() + || t.is_metavar_expr() || t.is_lifetime() // recover `'a` instead of `'a'` || (self.may_recover() // recover leading `(` && *t == token::OpenDelim(Delimiter::Parenthesis) diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs index 83c8f00999a72..004a8a23fd61f 100644 --- a/tests/ui/attributes/nonterminal-expansion.rs +++ b/tests/ui/attributes/nonterminal-expansion.rs @@ -5,8 +5,7 @@ macro_rules! pass_nonterminal { ($n:expr) => { #[repr(align($n))] - //~^ ERROR expected unsuffixed literal, found expression `n!()` - //~^^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693] + //~^ ERROR expected unsuffixed literal, found `expr` metavariable struct S; }; } @@ -16,5 +15,6 @@ macro_rules! n { } pass_nonterminal!(n!()); +//~^ ERROR incorrect `repr(align)` attribute format: `align` expects a literal integer as argument [E0693] fn main() {} diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr index 8a85731bd5a13..9c6cb98f61965 100644 --- a/tests/ui/attributes/nonterminal-expansion.stderr +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -1,4 +1,4 @@ -error: expected unsuffixed literal, found expression `n!()` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/nonterminal-expansion.rs:7:22 | LL | #[repr(align($n))] @@ -10,15 +10,10 @@ LL | pass_nonterminal!(n!()); = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0693]: incorrect `repr(align)` attribute format: `align` expects a literal integer as argument - --> $DIR/nonterminal-expansion.rs:7:22 + --> $DIR/nonterminal-expansion.rs:17:19 | -LL | #[repr(align($n))] - | ^^ -... LL | pass_nonterminal!(n!()); - | ----------------------- in this macro invocation - | - = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 416145a0c1560..47418b4e091b2 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -28,7 +28,7 @@ struct S9; macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] - //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` + //~^ ERROR expected unsuffixed literal, found `expr` metavariable struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index d02d0d70a8bcf..66ce2ee98589d 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -54,7 +54,7 @@ LL | #[cfg(a = b"hi")] | | | help: consider removing the prefix -error: expected unsuffixed literal, found expression `concat!("nonexistent")` +error: expected unsuffixed literal, found `expr` metavariable --> $DIR/cfg-attr-syntax-validation.rs:30:25 | LL | #[cfg(feature = $expr)] diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index b0a7f3e4650fd..a03ede20c5499 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -29,8 +29,8 @@ macro_rules! foo { (ident $x:ident) => { bar!(ident $x); }; (lifetime $x:lifetime) => { bar!(lifetime $x); }; (tt $x:tt) => { bar!(tt $x); }; - (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected expression `3` - (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected literal `4` + (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected `expr` metavariable + (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected `literal` metavariable (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected `path` metavariable (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected `stmt` metavariable } diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index 2d9252fbfc1fa..d01561415664c 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -23,7 +23,7 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected expression `3` +error: no rules expected `expr` metavariable --> $DIR/nonterminal-matching.rs:32:35 | LL | (expr $x:expr) => { bar!(expr $x); }; @@ -45,7 +45,7 @@ LL | (expr 3) => {}; = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: no rules expected literal `4` +error: no rules expected `literal` metavariable --> $DIR/nonterminal-matching.rs:33:44 | LL | (literal $x:literal) => { bar!(literal $x); }; diff --git a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs index a4e9134218cea..12b6c98705ce6 100644 --- a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs +++ b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs @@ -12,6 +12,8 @@ macro_rules! abi_from_lit_frag { fn _import(); } + unsafe extern $abi {} + extern $abi fn _export() {} type _PTR = extern $abi fn(); @@ -24,6 +26,8 @@ macro_rules! abi_from_expr_frag { fn _import(); } + unsafe extern $abi {} + extern $abi fn _export() {} type _PTR = extern $abi fn(); diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs index 990f2926dc861..bf7163039c420 100644 --- a/tests/ui/parser/float-field-interpolated.rs +++ b/tests/ui/parser/float-field-interpolated.rs @@ -5,10 +5,10 @@ macro_rules! generate_field_accesses { let s = S(0, (0, 0)); s.$a; // OK - { s.$b; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` - { s.$c; } //~ ERROR unexpected token: `1.1` - //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` + { s.$b; } //~ ERROR unexpected token: `literal` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable + { s.$c; } //~ ERROR unexpected token: `expr` metavariable + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable }; } diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr index 2a1a4926cb3c6..e2b7e3a7dbe75 100644 --- a/tests/ui/parser/float-field-interpolated.stderr +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -1,4 +1,4 @@ -error: unexpected token: `1.1` +error: unexpected token: `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -9,7 +9,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found literal `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | LL | { s.$b; } @@ -20,7 +20,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: unexpected token: `1.1` +error: unexpected token: `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } @@ -31,7 +31,7 @@ LL | generate_field_accesses!(1.1, 1.1, 1.1); | = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected one of `.`, `;`, `?`, `}`, or an operator, found expression `1.1` +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | LL | { s.$c; } diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs index e93000193b6e3..b4140613cbae7 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.rs +++ b/tests/ui/parser/macro/trait-non-item-macros.rs @@ -1,7 +1,7 @@ macro_rules! bah { ($a:expr) => { $a - }; //~^ ERROR macro expansion ignores expression `2` and any tokens following + }; //~^ ERROR macro expansion ignores `expr` metavariable and any tokens following } trait Bar { diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr index 1a82848377895..62b42fa8b8dd7 100644 --- a/tests/ui/parser/macro/trait-non-item-macros.stderr +++ b/tests/ui/parser/macro/trait-non-item-macros.stderr @@ -1,4 +1,4 @@ -error: macro expansion ignores expression `2` and any tokens following +error: macro expansion ignores `expr` metavariable and any tokens following --> $DIR/trait-non-item-macros.rs:3:9 | LL | $a diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout index c1e46b50d40c2..9482b2784d222 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -1,8 +1,9 @@ PRINT-DERIVE INPUT (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] -{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct -Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)] +Foo([bool; #[rustc_dummy(first)] +#[rustc_dummy(second)] { #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]); PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { @@ -53,97 +54,103 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ ], span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3), }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), - }, Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "second", - span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), - }, - ], - span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), - }, - Group { - delimiter: Brace, + delimiter: None, stream: TokenStream [ Punct { ch: '#', - spacing: Joint, - span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), - }, - Punct { - ch: '!', spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "third", - span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + ident: "second", + span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), - }, - Punct { - ch: '#', - spacing: Alone, - span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0), }, Group { - delimiter: Bracket, + delimiter: Brace, stream: TokenStream [ - Ident { - ident: "rustc_dummy", - span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + Punct { + ch: '#', + spacing: Joint, + span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0), }, Group { - delimiter: Parenthesis, + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0), + }, + Group { + delimiter: Bracket, stream: TokenStream [ Ident { - ident: "fourth", - span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0), + span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0), - }, - Literal { - kind: Integer, - symbol: "30", - suffix: None, - span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0), + span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), }, ], - span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0), + span: $DIR/macro-rules-derive-cfg.rs:18:64: 18:69 (#3), }, ], span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3), diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs index 4b2fc4a03b620..110c03d0e5491 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs @@ -59,8 +59,10 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement match () { #[cfg(FALSE)] () if let 0 = 1 => {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr index 1c710b04897cb..0997f0c81a019 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr @@ -124,15 +124,33 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/feature-gate.rs:62:16 + --> $DIR/feature-gate.rs:60:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:63:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: no rules expected keyword `let` - --> $DIR/feature-gate.rs:70:15 + --> $DIR/feature-gate.rs:72:15 | LL | macro_rules! use_expr { | --------------------- when calling this macro @@ -202,7 +220,7 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: you can write `if matches!(, )` instead of `if let = ` error[E0658]: `if let` guards are experimental - --> $DIR/feature-gate.rs:66:12 + --> $DIR/feature-gate.rs:68:12 | LL | () if let 0 = 1 => {} | ^^^^^^^^^^^^ @@ -262,6 +280,6 @@ LL | () if let Range { start: _, end: _ } = (true..true) && false => {} = help: add `#![feature(let_chains)]` 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 23 previous errors +error: aborting due to 25 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index db32b8c1de4ff..817e226bc45d5 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,15 +995,51 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1012,7 +1048,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1023,7 +1059,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1034,7 +1070,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1045,7 +1081,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1056,7 +1092,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1064,7 +1100,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1073,7 +1109,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1084,7 +1120,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1095,7 +1131,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1106,7 +1142,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1117,7 +1153,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1125,7 +1161,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1136,14 +1172,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 121 previous errors +error: aborting due to 125 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr index ad16a0f8ed812..bab50c22c0308 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -995,12 +995,48 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:16 + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:91:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0658]: `let` expressions in this position are unstable --> $DIR/disallowed-positions.rs:49:8 @@ -1043,7 +1079,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:404:8 + --> $DIR/disallowed-positions.rs:408:8 | LL | if let Some(a) = opt && (true && true) { | ^^^^^^^^^^^^^^^^^ @@ -1053,7 +1089,7 @@ LL | if let Some(a) = opt && (true && true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:420:28 + --> $DIR/disallowed-positions.rs:424:28 | LL | if (true && (true)) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1063,7 +1099,7 @@ LL | if (true && (true)) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:423:18 + --> $DIR/disallowed-positions.rs:427:18 | LL | if (true) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1073,7 +1109,7 @@ LL | if (true) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:426:16 + --> $DIR/disallowed-positions.rs:430:16 | LL | if true && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -1083,7 +1119,7 @@ LL | if true && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:431:8 + --> $DIR/disallowed-positions.rs:435:8 | LL | if let true = (true && fun()) && (true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1093,7 +1129,7 @@ LL | if let true = (true && fun()) && (true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:130:8 + --> $DIR/disallowed-positions.rs:134:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1102,7 +1138,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:139:12 + --> $DIR/disallowed-positions.rs:143:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1113,7 +1149,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:142:12 + --> $DIR/disallowed-positions.rs:146:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1124,7 +1160,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:148:12 + --> $DIR/disallowed-positions.rs:152:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1135,7 +1171,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:154:12 + --> $DIR/disallowed-positions.rs:158:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1146,7 +1182,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:110:20 + --> $DIR/disallowed-positions.rs:114:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1154,7 +1190,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:221:11 + --> $DIR/disallowed-positions.rs:225:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1163,7 +1199,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:230:15 + --> $DIR/disallowed-positions.rs:234:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1174,7 +1210,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:233:15 + --> $DIR/disallowed-positions.rs:237:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1185,7 +1221,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:239:15 + --> $DIR/disallowed-positions.rs:243:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1196,7 +1232,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:245:15 + --> $DIR/disallowed-positions.rs:249:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1207,7 +1243,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:201:23 + --> $DIR/disallowed-positions.rs:205:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1215,7 +1251,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:330:10 + --> $DIR/disallowed-positions.rs:334:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1226,14 +1262,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:305:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 130 previous errors +error: aborting due to 134 previous errors Some errors have detailed explanations: E0277, E0308, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index 2d5fd1144addd..943956feb4e07 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -233,7 +233,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:99:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:104:9 + --> $DIR/disallowed-positions.rs:108:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:114:9 + --> $DIR/disallowed-positions.rs:118:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:16 + --> $DIR/disallowed-positions.rs:121:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:117:13 + --> $DIR/disallowed-positions.rs:121:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:17 + --> $DIR/disallowed-positions.rs:123:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:121:25 + --> $DIR/disallowed-positions.rs:125:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:25 + --> $DIR/disallowed-positions.rs:127:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:127:12 + --> $DIR/disallowed-positions.rs:131:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:130:15 + --> $DIR/disallowed-positions.rs:134:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:133:11 + --> $DIR/disallowed-positions.rs:137:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:9 + --> $DIR/disallowed-positions.rs:139:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:139:8 + --> $DIR/disallowed-positions.rs:143:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:142:8 + --> $DIR/disallowed-positions.rs:146:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:148:8 + --> $DIR/disallowed-positions.rs:152:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:8 + --> $DIR/disallowed-positions.rs:158:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:158:19 + --> $DIR/disallowed-positions.rs:162:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:161:15 + --> $DIR/disallowed-positions.rs:165:15 | LL | if return let 0 = 0 {} | ^^^ @@ -390,7 +390,7 @@ LL | if return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:164:21 + --> $DIR/disallowed-positions.rs:168:21 | LL | loop { if break let 0 = 0 {} } | ^^^ @@ -398,7 +398,7 @@ LL | loop { if break let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:15 + --> $DIR/disallowed-positions.rs:171:15 | LL | if (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -406,7 +406,7 @@ LL | if (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:9 + --> $DIR/disallowed-positions.rs:174:9 | LL | if (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | if (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:173:9 + --> $DIR/disallowed-positions.rs:177:9 | LL | if (let 0 = 0,) {} | ^^^^^^^^^ @@ -422,7 +422,7 @@ LL | if (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:177:13 + --> $DIR/disallowed-positions.rs:181:13 | LL | if (let 0 = 0).await {} | ^^^^^^^^^ @@ -430,7 +430,7 @@ LL | if (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:12 + --> $DIR/disallowed-positions.rs:185:12 | LL | if (|| let 0 = 0) {} | ^^^ @@ -438,7 +438,7 @@ LL | if (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:9 + --> $DIR/disallowed-positions.rs:188:9 | LL | if (let 0 = 0)() {} | ^^^^^^^^^ @@ -446,7 +446,7 @@ LL | if (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:190:12 + --> $DIR/disallowed-positions.rs:194:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -454,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:193:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -462,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -470,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:12 + --> $DIR/disallowed-positions.rs:201:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -478,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:205:12 + --> $DIR/disallowed-positions.rs:209:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -486,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:208:19 + --> $DIR/disallowed-positions.rs:212:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:208:16 + --> $DIR/disallowed-positions.rs:212:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:210:20 + --> $DIR/disallowed-positions.rs:214:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:28 + --> $DIR/disallowed-positions.rs:216:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:214:28 + --> $DIR/disallowed-positions.rs:218:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:222:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -531,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:221:18 + --> $DIR/disallowed-positions.rs:225:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -539,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:224:14 + --> $DIR/disallowed-positions.rs:228:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -547,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:12 + --> $DIR/disallowed-positions.rs:230:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -555,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:230:11 + --> $DIR/disallowed-positions.rs:234:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -563,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:11 + --> $DIR/disallowed-positions.rs:237:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -571,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:11 + --> $DIR/disallowed-positions.rs:243:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:11 + --> $DIR/disallowed-positions.rs:249:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -587,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:249:22 + --> $DIR/disallowed-positions.rs:253:22 | LL | while let true = let true = true {} | ^^^ @@ -595,7 +595,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:18 + --> $DIR/disallowed-positions.rs:256:18 | LL | while return let 0 = 0 {} | ^^^ @@ -603,7 +603,7 @@ LL | while return let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:39 + --> $DIR/disallowed-positions.rs:259:39 | LL | 'outer: loop { while break 'outer let 0 = 0 {} } | ^^^ @@ -611,7 +611,7 @@ LL | 'outer: loop { while break 'outer let 0 = 0 {} } = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:18 + --> $DIR/disallowed-positions.rs:262:18 | LL | while (match let 0 = 0 { _ => { false } }) {} | ^^^ @@ -619,7 +619,7 @@ LL | while (match let 0 = 0 { _ => { false } }) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:12 + --> $DIR/disallowed-positions.rs:265:12 | LL | while (let 0 = 0, false).1 {} | ^^^^^^^^^ @@ -627,7 +627,7 @@ LL | while (let 0 = 0, false).1 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:12 + --> $DIR/disallowed-positions.rs:268:12 | LL | while (let 0 = 0,) {} | ^^^^^^^^^ @@ -635,7 +635,7 @@ LL | while (let 0 = 0,) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:268:16 + --> $DIR/disallowed-positions.rs:272:16 | LL | while (let 0 = 0).await {} | ^^^^^^^^^ @@ -643,7 +643,7 @@ LL | while (let 0 = 0).await {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:15 + --> $DIR/disallowed-positions.rs:276:15 | LL | while (|| let 0 = 0) {} | ^^^ @@ -651,7 +651,7 @@ LL | while (|| let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:275:12 + --> $DIR/disallowed-positions.rs:279:12 | LL | while (let 0 = 0)() {} | ^^^^^^^^^ @@ -659,7 +659,7 @@ LL | while (let 0 = 0)() {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:292:6 + --> $DIR/disallowed-positions.rs:296:6 | LL | &let 0 = 0; | ^^^ @@ -667,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | !let 0 = 0; | ^^^ @@ -675,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:297:6 + --> $DIR/disallowed-positions.rs:301:6 | LL | *let 0 = 0; | ^^^ @@ -683,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:299:6 + --> $DIR/disallowed-positions.rs:303:6 | LL | -let 0 = 0; | ^^^ @@ -691,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:301:13 + --> $DIR/disallowed-positions.rs:305:13 | LL | let _ = let _ = 3; | ^^^ @@ -699,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:6 + --> $DIR/disallowed-positions.rs:313:6 | LL | (let 0 = 0)?; | ^^^ @@ -707,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:312:13 + --> $DIR/disallowed-positions.rs:316:13 | LL | true || let 0 = 0; | ^^^ @@ -715,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:14 + --> $DIR/disallowed-positions.rs:318:14 | LL | (true || let 0 = 0); | ^^^ @@ -723,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:22 + --> $DIR/disallowed-positions.rs:320:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -731,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:320:9 + --> $DIR/disallowed-positions.rs:324:9 | LL | x = let 0 = 0; | ^^^ @@ -739,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:12 + --> $DIR/disallowed-positions.rs:327:12 | LL | true..(let 0 = 0); | ^^^ @@ -747,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:325:8 + --> $DIR/disallowed-positions.rs:329:8 | LL | ..(let 0 = 0); | ^^^ @@ -755,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:6 + --> $DIR/disallowed-positions.rs:331:6 | LL | (let 0 = 0)..; | ^^^ @@ -763,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -771,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:6 + --> $DIR/disallowed-positions.rs:338:6 | LL | (let true = let true = true); | ^^^ @@ -779,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:334:17 + --> $DIR/disallowed-positions.rs:338:17 | LL | (let true = let true = true); | ^^^ @@ -787,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:25 + --> $DIR/disallowed-positions.rs:344:25 | LL | let x = true && let y = 1; | ^^^ @@ -795,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:346:19 + --> $DIR/disallowed-positions.rs:350:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -803,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:6 + --> $DIR/disallowed-positions.rs:355:6 | LL | &let 0 = 0 | ^^^ @@ -811,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:362:17 + --> $DIR/disallowed-positions.rs:366:17 | LL | true && let 1 = 1 | ^^^ @@ -819,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:367:17 + --> $DIR/disallowed-positions.rs:371:17 | LL | true && let 1 = 1 | ^^^ @@ -827,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:372:17 + --> $DIR/disallowed-positions.rs:376:17 | LL | true && let 1 = 1 | ^^^ @@ -835,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:17 + --> $DIR/disallowed-positions.rs:387:17 | LL | true && let 1 = 1 | ^^^ @@ -843,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:383:9 + --> $DIR/disallowed-positions.rs:387:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -854,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:393:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:397:9 + --> $DIR/disallowed-positions.rs:401:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:9 + --> $DIR/disallowed-positions.rs:404:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:400:32 + --> $DIR/disallowed-positions.rs:404:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:408:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:412:31 + --> $DIR/disallowed-positions.rs:416:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:416:9 + --> $DIR/disallowed-positions.rs:420:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:436:22 + --> $DIR/disallowed-positions.rs:440:22 | LL | let x = (true && let y = 1); | ^^^ @@ -979,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:441:20 + --> $DIR/disallowed-positions.rs:445:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 8eb8d617d581c..99f99c2be72de 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -90,8 +90,12 @@ fn _macros() { } use_expr!((let 0 = 1 && 0 == 0)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); //[feature,no_feature]~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR expected expression, found `let` statement } #[cfg(not(nothing))] From d59b17c5cdbf345d0088d90fc03faf2501a39757 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Mar 2025 15:54:14 +1100 Subject: [PATCH 255/333] Remove `Token::uninterpolated_span`. In favour of the similar method on `Parser`, which works on things other than identifiers and lifetimes. --- compiler/rustc_ast/src/token.rs | 27 +++++-------------- compiler/rustc_parse/src/parser/expr.rs | 14 +++++----- compiler/rustc_parse/src/parser/item.rs | 10 +++---- compiler/rustc_parse/src/parser/mod.rs | 35 +++++++++++++++++++------ compiler/rustc_parse/src/parser/ty.rs | 6 ++--- 5 files changed, 48 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2081777fff359..d57a369eebf2e 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -448,8 +448,9 @@ pub enum TokenKind { /// Identifier token. /// Do not forget about `NtIdent` when you want to match on identifiers. - /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to - /// treat regular and interpolated identifiers in the same way. + /// It's recommended to use `Token::{ident,uninterpolate}` and + /// `Parser::token_uninterpolated_span` to treat regular and interpolated + /// identifiers in the same way. Ident(Symbol, IdentIsRaw), /// This identifier (and its span) is the identifier passed to the /// declarative macro. The span in the surrounding `Token` is the span of @@ -458,8 +459,9 @@ pub enum TokenKind { /// Lifetime identifier token. /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. - /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to - /// treat regular and interpolated lifetime identifiers in the same way. + /// It's recommended to use `Token::{ident,uninterpolate}` and + /// `Parser::token_uninterpolated_span` to treat regular and interpolated + /// identifiers in the same way. Lifetime(Symbol, IdentIsRaw), /// This identifier (and its span) is the lifetime passed to the /// declarative macro. The span in the surrounding `Token` is the span of @@ -585,23 +587,6 @@ impl Token { Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span) } - /// For interpolated tokens, returns a span of the fragment to which the interpolated - /// token refers. For all other tokens this is just a regular span. - /// It is particularly important to use this for identifiers and lifetimes - /// for which spans affect name resolution and edition checks. - /// Note that keywords are also identifiers, so they should use this - /// if they keep spans or perform edition checks. - // - // Note: `Parser::uninterpolated_token_span` may give better information - // than this method does. - pub fn uninterpolated_span(&self) -> Span { - match self.kind { - NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, - Interpolated(ref nt) => nt.use_span(), - _ => self.span, - } - } - pub fn is_range_separator(&self) -> bool { [DotDot, DotDotDot, DotDotEq].contains(&self.kind) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 424fee968e1d1..1c2df3ffcd109 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1318,7 +1318,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { + if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) { return Ok(self.mk_await_expr(self_arg, lo)); } @@ -1509,9 +1509,9 @@ impl<'a> Parser<'a> { this.parse_expr_let(restrictions) } else if this.eat_keyword(exp!(Underscore)) { Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore)) - } else if this.token.uninterpolated_span().at_least_rust_2018() { + } else if this.token_uninterpolated_span().at_least_rust_2018() { // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly. - if this.token.uninterpolated_span().at_least_rust_2024() + if this.token_uninterpolated_span().at_least_rust_2024() // check for `gen {}` and `gen move {}` // or `async gen {}` and `async gen move {}` && (this.is_gen_block(kw::Gen, 0) @@ -2186,7 +2186,7 @@ impl<'a> Parser<'a> { fn parse_opt_meta_item_lit(&mut self) -> Option { self.recover_after_dot(); let span = self.token.span; - let uninterpolated_span = self.uninterpolated_token_span(); + let uninterpolated_span = self.token_uninterpolated_span(); self.eat_token_lit().map(|token_lit| { match MetaItemLit::from_token_lit(token_lit, span) { Ok(lit) => lit, @@ -2390,7 +2390,7 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable }; - let coroutine_kind = if self.token.uninterpolated_span().at_least_rust_2018() { + let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() { self.parse_coroutine_kind(Case::Sensitive) } else { None @@ -2939,7 +2939,7 @@ impl<'a> Parser<'a> { /// Parses `for await? in ` (`for` token already eaten). fn parse_expr_for(&mut self, opt_label: Option